'**************************************************************************** '* * '* 16 bit 24EP128MC202 microcontroller * '* Godfried-Willem Raes * '* 2017 * ' *************************************************************************** ' NOTE: Pickit3 must be used for programming these devices! ' Each interrupt has its own handler, simply write one handler for each interrupting ' device without having to work out which interrupt it is. ' Timers are more logical: specify the count going upwards that will trigger an ' interrupt rather than working out when the counter would underflow. ' COMMENTS made during development of HybrLo: '02.08.2016: 1M resistor added over X-tal pins '03.08.2016: Finaly got the clock up and running on the X-tal ' Working out the MIDI UART now. ' Midi-in buffering implemented. ' Trying to use the pwm channels... we cannot use the HPWM commands... ' Implementing velocity control with timers ' Repeats working now. '04.08.2016: Adding 12 bit ADC on channel AN0 ' Midi out looks like working using the Basic command HSROut ' 1 midi packet (3 bytes) takes some 1ms, which conforms to the standard. ' adding initialisation for the PWM channels ' This is as yet not working... '05.08.2016: with 60Mhz clock the frequency range for PWM would be 60MHz --> 915Hz ' so, for audio use we need a prescale devider :64 ' Thus the frequency range would become 14Hz --> 937.5kHz '06.08.2016: pwm begint stilaan goed te werken. ' different modes of operation implemented for the pwm channels ' pwmmodus 0 fully debugged. ' pwmmodus 2 fully debugged (3-phase motor control) ' pwmmodus 1 fully debugged (3 independent PWM channels) ' pwmmodus 3 added: AC motor with capacitor phase shifter using 2 pwm channels ' PWM principieel werkend nu. ' eventueel kunnen nog dead times toegevoegd worden indien nodig voor een toepassing ' We kunnen overbodige pwm pinnen nog disablen en beschikbaar maken voor ' andere funkties. '07.08.2016: Lookup tables for frequencies in 12-tone equal temperament added. Ambitus= 22-127 ' looks like it's possible to implement a 3-voice midi synth on this platform. ' Just did it: the 3-channel synth is working! ' Studying the implementation of 32-bit timers ' timers 2/3 and 4/5 implemented as 32-bits timers ' trying to use timer23 instead of our loop counter. ' This now works fine ' We could use timer1 as a motor speed controller for a stepper ' Timer 45 could be used as a high resolution, extreme ambitus tone generator ' Timer 1,4,5 implemented as fast timers in 16 bits for ADSR implementation ' PWM lookups added for this. '10.08.2016: Different approach to adsr - simplified, using timers ' ADSR works now, but we will need a steep lowpass filter on the output ' with this code we are at the limit of what the PIC can handle. ' As it is now, we can have 6 independent PWM channels. ' For the 3-voice synth we need them all and we used up all available timers. ' The priority settings for the IRQ's are very important for this code to work well. ' This version saved as PIC24_008.bas '11-12.08.2016: application written for midi-invertor: Mirrored_X.bas. Tested o.k. '13.08.2016: metacompiler statements for UART-TX and UART-RX added. ' Buffered midi-out fully implemented. ' For some reason the ADSR pwm is no longer working now... ' Rearranging priority levels made it work again. ' ADSR timers must have a :8 divider setting. ' This version saved as PIC24_009 ' Working version saved as P14_synth1.bas '14.08.2016: To relax the interrupt density, we could also invert the pwm functions and ' use the timers 1,4,5 for frequency generation with waveform duty cycle whilst ' the 3 real PWM channel could do the ADRS at the highest possible frequency. ' This requires PWMmodus to be set to 0. ' looks like PWM needs to be inverted now. Done. ' ADSR works fine now, but the load on the processor is still very high. ' we should try to get the divisions out of the main loop now. Done.\ ' Further improvements: decrease nr. of steps for ADSR, as 127 steps ' for an attack time of say 100ms seems largely overkill... '15.06.2016: ADSR coding restructured to make it more readible. ' Tests o.k. bit we still have glitches and seem to be working at the ' edge of what the processor can do. '23.08.2016: Evaluation board finished. This works o.k. ' bug removed in the duty cycle control: cannot be zero! ' This file now saved as HybrLo_22_24.bas '-------------------------------------------------------------------------------------- '23.08.2016: Start delopment of specific HybrLo code. ' This code implements notes 22, 23 and 24 and their octaves. '20.09.2016: Looks like release is no longer working now... ' We could try to nake the 947 constant for scaling the ADSR smaller ' ADSR_scale constant introduced. ' release bug found: scale multiply forgotten in the noteoff proc. ' if we set ADSR_scale to 1024, we can avoid many multiplies in the code... ' done with the introduction of ADSR_shift = 10 ' 10.10.2016: Recoding to avoid float's in the code. ' Now with 40dB scalings. ' Ommited ADSR flags reset on note-On command, was the first cause of the glitches. ' real time modulation of volume added using ctrl's 70-82 ' For the other boards, just change the $define Boardx_x compiler metacommand. ' 11.10.2016: Extending range with an octave... ' extending with yet one more octave... ' 12.10.2016: 40dB lookups herberekend voor bovenste bereik van de PWM ' dit zou de S/R verhouding moeten verbeteren. ' 60dB lookups added again. ' This version uploaded. Version 003. ' 13.10.2016: start implementation of ctrl#1 for frequency jitter. ' ADSR periods halved. ' Jitter controller (#1) added ' Release range reset to 512 ms. Attack and decay are now 256ms '------------------------------------------------------------------------------- ' 16.02.2017: Start from the framework of HybrLo to code for ' First thing: try to generate the required very high pitches. ' Prescalers for the timers set to :8, rather than :64 on Hybrlo ' Priorities set to 6 ' So far this works, if we shift the period lookups 2 octaves down. ' PTPER set to 512 - this works. We can even go higher it seems. ' First tests on note 84 passed. ' 19.02.2017: Lookups for the 15 different compilations added. ' Four PIC's on board 1 programmed. ' 20.02.2017: First test with the pipes mounted. ' there are glitches in the ADRS..., the principle seems to work well. ' Problems with ports being high on init... try using portb.6 for ctrl.66 ' 23.02.2017: Attack_time, decay_time, release_time changed to dword as they could overflow ' 28.02.2017: Code problems in boards 3 and 4. Ctrl66 does not seem to work. ' Problem solved: poling wrong on the Omron Relay. ' 03.03.2017: Code optimised. Shift in ADR reduced to 8. ' We have to check the tuning: the octaves are a bit wrong!!! ' Start implementing microtuning using ctrl's 72-116 ' Pitch-periods are now declared constants. ' ADSR range made consistent with PTPER : now 9 bits. ' 04.03.2017: Microtuning support added, ctrl's 72 to 117 ' all 15 processors reflashed. Version 1.1 now ' 05.03.2017: the microtuning implementation appears not to work... ' 07.03.2017: duty cycle controll is now pitch dependent. Version 1.3, saved as backup ' 08.03.2017: start implementation of just intonation tunings ' This will be version 1.4 ' here we will try to set the timer prescaler to 0, to increase ' tuning precision with a factor 8. ' This now seems to work on the test board. ' However, changing the tuning seems not to work at all. ' Maybe the timer IRQ's are blocking the calculations. ' so, let's try to disable interrupts on reception of tuning commands. ' Bug found: was not in this code, but in the GMT test-code!!! ' Mircrotuning now works. ' JI lookups lead to way too high freq's. There must be a scaling bug here. ' 09.03.2017: This bug was due to a compiler bug in that it did not calculate the constants ' at compilation time. ' Period[127] = Note95 * 5 / 32 leads to errors! ' So, we wrote a utility in PBCC to calculate all JI pitch lookups. ' There are precision errors increasing with frequency. ' Compensation for this requires further analysis. ' note 126 in EQ measures 11655.6 Hz, it should be 11840 Hz, so a 184.4Hz fault, or 1.557% ' note 84 in EQ measures 1045.1 Hz, it should be 1047 Hz, so a 1.9Hz fault, or 0.18% ' we can compensate in the lookups for these errors, assuming a linear curve. ' After applying compensations to the lookup tables the measured frequency error are: ' 0.05% for note 84, 0.06% for note 126. We consider this a very good result. ' On request of early adopters, we doubled the release time values. ' This be version 1.5: flashed in all PIC's. ' 10.03.2017: The formula to use for the calculation of the periods needs to be: ' period = ((1/freq) - t) / k ' wherein k = 1 / 60MHz and t = ISR service time, measured as 1.3us ' with this formula applied, the error for note 126 is only 0.018% ' for note 84, the error is 0.045% ' for note 85, the error is 0.022% ' 11.03.2017: lookup algorithm improved with constant ISR time ' now all errors <= 0.02% ' version 1.6 now. Flashed. ' ------------------------------------------------------------------------------------------------------------- ' 16.03.2017: Start from Pi code, coding for Rodo ' Timers need a :8 setting here ' Coding should be monophonic ' ADC to be implemented for sampling ' PWM resolution should be 12 bits ' 18.03.2017: Hardware bug remedied: 7400 replaced with 7430, 8-input NAND gate. ' ctrl 13 changed. ' Bugs: ' CC5 off should switch off sounding note ' CC4 on blocks everything ---> check sampling rate ' CC3 works ok ' CC6 only works if set to 1 ' CC5 bug solved. ' ADC sampling rate tested. ' however, the AN0 input is not working. Is it switched to input? ' TRISA was set to output... ' 21.03.2017: Still we cannot get the ADC system to work, neither in 10-bit, nor in 12-bit mode. ' Note that the analog input pins are NOT 5V tolerant!!! ' After 3 days of debugging, we finally got the ADC to work: ANSELA.0 = 1 is crucial. ' Of course with this coding, we get a strong sample rate base frequency in the output. ' To get rid of this, the sampling rate has to be raised to above 16kHz. ' Recoded for 16384 S/s in timer 5 and scaling for Timer 4 adapted accordingly in the lookup. ' IGBT mounted on the board. Tests under real load conditions can start. ' This version saved as Rodo_edrive_001.bas ' Continuing research to get ADC->PWM to work directly ' This works. ' Instead of the hardware AND construction, we could also mix the inject and the feedback signals ' into a single PWM stream. To be researched and coded. '-------------------------------------------------------------------------------------------------------------- ' 25.03.2017: Starting from edrive code, coding for the radar interfaces. ' Requirements for this code: ' 12 bit analog sampler ' 1 external interrupt for period measurement ' midi merger (Rx/Tx) ' 1 PWM output for FM modulation of the microwave emitter ' 31.03.2017: External IRQ on INT0 working ' ADC not working ' 01.04.2017: Sampling working now. ' Adding data acquisition code ' Midi transmit input to output added. ' 02.04.2017: PDC2 connected to blue LED's for speed monitoring ' PDC3 connected to white LED's for surface monitoring ' DC offsets in hardware changed. This was a hardware bug... ' Start coding a a gesture mapping for radar 1. ' Version 1.0 ready for testing on ' 03.04.2017: metacompiler commands for the two radar boards added. ' CC70: dT for derivative of speed added ' CC71: dT for derivative of surface added ' CC74: noise level for surface data ' First tests on ' red lite goes on, blue never ' Controllers tested. ' Midi merge works fine so far. ' 04.04.2017: Note repetitions added using Task0. This works. ' Implement Channel aftertouch for communication between radar1 and 2? ' Further work on the RadaRodo piece. ' e-bow not working in radar modus... ' 05.04.2017: Second radar board hardware finished. ' e-bow bug found: time was defined as word. Must be dword! ' blue light bug found: symbol definition was wrong. ' main-loop has very high jitter with the RadaRoto piece as ' midi out seems to cause quite some timing uncertainty. ' 06.04.2017: jitter coding improved. ' now used floats for much better integration at the detriment of speed. ' IRQ priorities changes. ' 07.04.2017: Dead-time introduction for INT0 to avoid jitter (INT0 coding) ' Controllers 75 and 76 introduced for DC_Offset adjustment. ' Test code for this added in GMT+slagwerk - Rodo. ' Compilation problems: asm faults reported... ' The floats in the IRS seem to be the problem... ' 08.04.2017: using differenciator/rectifier using only words in the ADC ISR ' sampling rate lowered to 1024 S/s ' speed sampling rate lowered to ca. 250 S/s ' 09.04.2017: Nothing seems to work anymore now, except the 12 bit ADC... ' Hardware bug solved: oscillation on the 3v3 analog supply pin... ' No more floats and irq calls in IRS's ' Seems to work fine now. Retest on ... ' Sensitivities have to be changed now. ' Test o.k. but lights not working. ' Range for accel changed in radarodo task ' dynamic during repeats made interactive. ' Radar 2 board updated also. Strange observation: this board using ' the same component values as Radar 1 does not have the oscillation problem... ' 10.04.2017: Version 003 now ' INT0 coding improved. ' First tests on Rodo with 2 radars ' start-up sequence changed. Now initialisation are sent by Radar 2 only ' aftertouch used for communication between Radar1 and Radar2 ' dS implemented now, but not yet used in composition coding ' 11.04.2017: Version 004 now ' still after start-up the ebow does not work. It only starts working ' if we send the appropriate controllers after start-up. (CC3, CC5, CC6) ' Red and Blue light coding changed, although we have no cue as to why it was not ' working. ' 12.04.2017: Red/Blue lights still not working... ' Oscillation problem solved: there is just to much vibration on the mounting plate ' thus the radars suffer from mechanical feedback. ' code restructured. ' accellerations mapping now works ' we can use different interactive programs if we implement prog. change for the selection. ' we could have different programs for radar1 and radar2 ' 13.04.2017: Procedures added for midi-out ' midi-out buffer enlarged to 512 ' loop speed limited to timer resolution ' Radar2 seems to crash. Do we still have buffer overflows? ' Bug found: indexes have to be word var's now. ' This be version 007. ' 14.04.2017: A third PCB made and finished, with a much better comparator design. ' The radar board on Rodo appear to be stable now. ' 15.04.2017: code added for autoregulation of the pitch mapping. ' 16.04.2017: ctrl. inits changed. ' 17.04.2017: Further testing. e-bow board upgraded also with larger midi-buffers. ' This does not seem to solve our problems... ' Pacing removed from main loop. ' now e-bow seems to work, but we have no sound explanation... ' 18.04.2017: Stack size increased. ' This does not make any difference... ' 19.04.2017: Start coding for a second embedded composition ' 20.04.2017: Speed algo changed in INT0 en TMR1 ' 21.04.2017: with some nop's in the midiTX procs to seems to work a lot better. ' slow timers added for automatic piece swapping ' 23.04.2017: still not working reliably. ' now trying to use tasks to sequence the controller commands ' 24.04.2017: The sequenced approach to midi seems to work now. ' Thus we do no longer use Timvals[2] for startup. ' 25.04.2017: Now at version 10. ' If Rodo stays ON for a long time (> 4 hours) the ebow stops working. ' Changing the interactive composition with a prog.change command causes all ' dampers to go down thus overloading the damper power supply. ' 26.04.2017: further testing and improving (...we hope) ' 28.04.2017: odd behaviour of the compiler... ' 29.04.2017: and we go on... ' 30.04.2017: ebow board repaired. Works again now. ' Further testing can continue. ' 01.05.2017: Radar3 and Radar4 board finished. These are not for Rodo. ' 03.05.2017: Display procedures and implementation added for Radar4 board. ' 04.05.2017: Hexdis procedure added and debugged. This works fine now. ' 06.05.2017: UART TX coding changed, avoiding internal 4 byte overflows to occur. ' This should make sequencing of midi-out data unneeded. ' We must have introduced a bug, as nothing of the interactive coding works now... ' Bug found and killed (>= ipv < in the piece switcher...) ' Now let's try to go without sequencing for midi again. ' Seems to work now... ' Surface mapping changed from quadratic, to mixed. ' Sensitivity values have to be changed now ' New sensit values: CC74 = 5, CC72,73= 36 ' ----------------------------------------------------------------------------------------------- ' 24.10.2017: Starting from the -radar code, developping a radar board for ' 25.10.2017: Detailed descriptions for the hardware and the pcb's used are in ' \logoswebsite\ii\Radar_2017 ' Hardware: Radar board 3. ' 26.10.2017: if we encounter problems with midi pacing we should consider to use the pacing setting ' with Proton Basic's hsrout command, rather than use pacing in the main loop as we did ' in the code for the parser board on ' However, we have to check in the asm code, whether or not pacing is using a timer resource. ' 27.10.2017: Monitoring the midi our messages reveals that we have midibytes > 127 after statusbytes... ' something goes wrong. ' 28.10.2017: Midi pacing added. This seems to solve the invalid midi problem. ' 29.10.2017: Radar board mounted on . In principle -but not musically- it works. ' However the amplitude white LED stays very bright... This was not the case on our desktop ' Do we have electroluniscent bulb interference on the radar? Or, do we have interference from ' the pwm driven solenoids on Aeio itself? ' 30.10.2017: We have the interference only in the Tetrahedron... WiFi? Cellulars? Neighbours? ' On my desktop, the disturbance does not occur. ' For comparative tests we programmed Radar4 with the same code. ' Extensive tests revealed: the 5V power supply is unstable and showed oscillations, propagating ' to the radar board. Thus we have to replace the +5V logic power supply with a low noise 3A type. ' 31.10.2017: work on Xtof piece for Aeio ' 01.11.2017: Further testing and exploring of the radar board ' steering code added to GMT -aeio testing compilation ' We suffer fromachanical feedback on the aeio robot... ' TO DO: make autoregulation for CC74 as we can easily calculate a minimum value for noise ' defined as the minimum value ever converted. DONE. ' 02.11.2017: Firmware is now transparant for midi in. Thus, Aeio can also be controlled via the ' radar midi-input. Controllers to exit interactive mode to be added. ' Controller 79 added, to switch off interactive operation. ' 03.11.2017: to do: implement a piece using arpeggios ' recalculate values for sampling rates and dt settings ' recheck the duration of the databuffers. ' Proton compiler upgraded to version 3.6.0.2 (Proton8) and 1.0.44 (Proton24) ' accel and dS changed to float and implemented correctly as dv/dt. ' 04.11.2017: Recalculation of all low pass filter coefficients. ' Formula used: c = exp(-2.Pi.f / samplingrate) ' Calculations performed in PBCC. ' ranges for dS and accel checked and documented ' To do: invalidate calculation for accel if we are below the noise level. Done, ' but we have a logic problem now! ' 05.11.2017: To do: add lights in the pieces. Test AeioSinking code. ' done. Sense variable added for Rising and sinking pieces. ' It would be good if we could make CC73 to become autoregulating... ' CC73 test code added in GMT Aeio test-applet ' 06.11.2017: Range for enotes extended ' CC73 autoregulator remmed out. Default value to be checked again now. ' Rubber suspension made for the radar assembly. This improves mechanical feedback very much. ' Improving Xtof's piece. ' 07.11.2017: Controllers 114 - 118 implemented to change the durations of embedded compositions. ' by setting a controller to zero, the piece will be skipped. ' The maximum duration for a piece is 2h30' ' 'Aeio's response' works fine now. ' This version used for EU_Robotics as well as for the Butoh performance ' with Emilie De Vlam on november 23th. ' 30.11.2017: Considering to use speed dependent integration for better responsivity. ' 07.12.2020: TMR3 bug killed. TMR3.8 coding to be changed now!!! ' LED mapping: [ for debug and monitoring, on Radar3 board] ' Green = midi transfer toggle ' Orange = speed detection ' Yellow = ebow noot playing. ' White = doppler surface detection (PWM) ' Blue = speed/acceleration detection (PWM) ''------------------------------------------------------------------------------------------------------------- ' START: Device = 24EP128MC202 ' this code should also work on 24EP32MC202, 24EP64MC202, 24EP256MC202, 24EP512MC202 ' and dsPIC33EP32MC202, dsPIC33EP64MC202, dsPIC33EP128MC202, dsPIC33EP256MC202, dsPIC33EP512MC202 ' and dsPIC33EP32MC502, dsPIC33EP64MC502, dsPIC33EP128MC502, dsPIC33EP256MC502, dsPIC33EP512MC502 Clear ' conditional compile constants: '$define Rodo_Radar1 ' left side radar, notes 48-78 on Rodo '$define Rodo_Radar2 ' right side radar, notes 49 - 77 on Rodo $define Radar3 ' since 24.10.2017 used for '$define Radar4 ' test board with hex display, as yet uncommitted. ' port-assignments - hardware specifics '************************************** Symbol watchdog_led PORTB.6 ' red LED - pin 15 Symbol Int0 PORTB.7 ' external interrupt $ifndef Radar4 Symbol yellow_led PORTA.4 Symbol green_led PORTB.4 Symbol orange_led PORTB.5 Symbol loopcnt PORTB.0 ' pin 4 $else Symbol loopcnt PORTB.4 ' pin 11, as we cannot use the left dot on the display anyway... ' nothing connected to this pin, so we can connect the oscilloscope here. $endif Config FPOR = ALTI2C1_OFF, ALTI2C2_OFF ' I2C support OFF Config FWDT = WDTPOST_PS256, WINDIS_OFF, PLLKEN_ON, FWDTEN_OFF ' FWDTEN_OFF disables the WDT (watchdog timer) RCON.5 = 0 ' clear the watchdog enable bit for reset = SWDTEN_OFF ' first configure the clock... ' select internal FRC at POR not using PLL: Config FOSCSEL = FNOSC_FRC, IESO_OFF DelayMS 10 ' make sure we assign the correct pins to use for the ICD (Pickit3) Config FICD = ICS_PGD1, JTAGEN_OFF ' this sets the pins used for the programmer ' enable clock switching and configure POSC for XT mode with 10MHz crystal Config FOSC = FCKSM_CSECMD, OSCIOFNC_OFF, POSCMD_XT Main_Setup: ' configure PLL prescaler, PLL postscaler, PLL divisor PLLFBD = 46 CLKDIV.7 = 0 'PLLPOST N2=2 CLKDIV.6 = 0 CLKDIV.0 = 0 'PLLPRE N1=2 CLKDIV.1 = 0 CLKDIV.2 = 0 CLKDIV.3 = 0 CLKDIV.4 = 0 Write_OSCCONH ($3) ' = __builtin_write_OSCCONH(0x03) Write_OSCCONL (OSCCON | %1) ' = __builtin_write_OSCCONL(OSCCON | 0x01) PLL_Setup(48, 2, 2, $0300) ' should set it to 120MHz operation with 10MHz X-tal ' Fosc = 10MHz * 48 / 2 * 2 = 120MHz ' now we get a 10MHz clock signal on pin OSC2, pin10... ' ----------------------------- DelayMS 1000 ' wait for stability Declare Xtal = 120 ' set to Fosc - the clock frequency is 60MHz (MIPS) ' thus 1 instruction cycle is 16.666 ns ' new 18.04.2017: but this makes no difference at all in our code. Declare Stack_Size 200 ' by default it's 60 words or 120 bytes Declare Stack_Expand 1 ' expand stack automaticaly if required. $define Enable_UART_RX ' midi-in $define Enable_UART_TX ' midi-out $define Enable_ADC12bit ' precompiler instructions for 12 bit ADC single channel '$define Enable_ADC10bit $define Enable_PWM ' precompiler instructions $define Enable_Timer1 ' precompiler instructions - 16 bit timer $define Enable_Timer23 ' 32-bit timer '$define enable_Timer45 ' 32-bit timer $define Enable_Timer4 ' as 16 bit timer $define Enable_Timer5 ' as 16 bit timer - used as a sampling rate generator $define Enable_Int0 ' enable external interrupt 'Declare Hserial_Baud = 31250 ' USART1 baud rate - set to MIDI 'Declare Hrsout1_Pin = PORTB.8 ' RP40 ' Select the pin for TX with USART1 'Declare HRSin1_Pin = PORTB.9 ' RP41 PPS_Output(cOut_Pin_RP40, cOut_Fn_U1TX) ' Map UART1 TX pin to RP40 'RP35 PPS_Input(cIn_Pin_RP41, cIn_Fn_U1RX) ' Map UART1 RX pin to RP41 'RPI34 $ifdef Radar3 Symbol BlueLite = 1 ' on parser board Symbol YellowLiteL = 5 ' frontal spotlite left Symbol YellowLiteR = 6 ' frontal sporlite right Symbol RedLite = 2 ' under hammer assembly Symbol DC_Offset_Init = 2048 Symbol NrNotes = 12 ' hammers Symbol LastNote = 11 Symbol NrEnotes = 48 ' e-notes strings - 4 octaves Symbol Nr5notes = 60 ' 5 octaves Symbol Nr6Notes = 72 ' 6 octaves Symbol LastEnote = 47 ' highest index value for 4 octaves Symbol Last5note = 59 Symbol last6note = 71 $endif $ifdef Radar4 Symbol BlueLite = 1 ' on parser board Symbol YellowLiteL = 5 ' frontal spotlite left Symbol YellowLiteR = 6 ' frontal sporlite right Symbol RedLite = 2 ' under hammer assembly Symbol DC_Offset_Init = 0 '2048 Symbol NrNotes = 12 ' hammers Symbol LastNote = 11 Symbol NrEnotes = 48 ' e-notes strings Symbol Nr5notes = 60 ' 5 octaves Symbol Nr6Notes = 72 ' 6 octaves Symbol LastEnote = 47 ' highest index value Symbol Last5note = 59 Symbol last6note = 71 $endif 'constant initialisations for the midi input parser: $ifdef Radar3 Symbol Midichannel = 1 ' Aeio_Channel $endif $ifdef Radar4 Symbol Midichannel = 1 ' uncommitted so far. $endif Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel Symbol Control_Status = 176 + Midichannel Symbol ProgChange_Status = 192 + Midichannel ' 1 byte message Symbol Aftertouch_Status = 208 + Midichannel ' 1 byte follows Symbol Pitchbend_Status = 224 + Midichannel ' lsb msb follow Symbol TXBufSize $03FF ' 1023 '511 Symbol TXBufArraysize $0400 ' 1024 '512 must be a power of 2 Symbol RCBufSize $03FF ' midi receive buffer Symbol RCBufArraySize $0400 Symbol NrTasks = 7 ' used for gesture input to rodo command tasks Symbol LastTask = 6 ' = NrTasks - 1 Symbol OnVal = 85 ' %01010101 pattern Symbol CC7_default = 64 ' default startup value for controller 7 Symbol CC70_default = 48 ' dt for accel Symbol CC71_default = 164 ' dt for dS Symbol CC73_default = 2 ' sense for Aeiorising and Aeiosinking note overlap ' further comment in de code for Aeiorising. Symbol CC74_default = 1 ' noise level Symbol CC77_default = 1 ' dS multiplier Symbol CC78_default = 16 ' accel multiplier Symbol CC79_default = 0 ' radar ON ' piece numbers for 5 embedded compositions: ' changing these constants, changes the order of the pieces. (?) Symbol RadaAeio_piece = 0 Symbol AeioRising_piece = 1 Symbol Xof_piece = 2 Symbol AeioSinking_piece = 3 Symbol Aeio_Respons_piece = 4 Symbol Last_Piece = 4 ' changing these constants, changes the default durations of the pieces: ' these durations can be changed with midi controllers 114 to 119. Symbol RadaAeio_duration = 2 ' 5 = ca.6 minutes Symbol AeioRising_duration = 2 '5 Symbol Xof_duration = 2 '5 Symbol AeioSinking_duration = 2 '5 Symbol AeioRespons_duration = 2 ' to allow flexible reassignment of piece order we need codepointers. ' constants used for the operation of the PWM modules ' the modus operandi should be set at compile time! ' For the Hybr boards PWMmodus must be 0. ' For the Pi boards also PWMmodus 0. Symbol PWMmodus = 0 ' 0 = all pwm channels have the same period (frequency) ' PDC1, PDC2, PDC3 steer the PWM setting for each channel ' PTPER is the register to control the period (frequency) and thus the resolution ' PHASE1, PHASE2, PHASE3 steer the phase between output channels ' This mode can be used for ADSR control on 3 channels. ' 1 = the three PWM channels have individual period (frequency) controls ' controlled with the PHASE1, PHASE2, PHASE3 registers ' PDC1, PDC2, PDC3 registers steer the PWM ' PWM-value must be < Period ' this mode could be used to implement a 3-voice midi synth ' We only use the PWMH pins for output here, so portB.15, portB.13 and portB.11 ' are free and can be used for adrs control ' 2 = 3-phase motor control mode ' PTPER controls the period (frequency) ' MDC controls the duty cycle for the 3 channels ' PHASE1, PHASE2, PHASE3 steer the phase between the channels ' we start-up with 120 degree phase shifts. ' 3 = 2-phase ac motor using a capacitor phase shifter ' PTPER controls the period (frequency) ' MDC controls the duty cycle for the 3 cha ' PHASE1, PHASE2, PHASE3 steer the phase be' port I/O settings: ' we start-up with 90 degree phase shifts. 'TRISA = %100001 ' AN0 set to input, others set to output - we dont use these ports TRISA.0 = 1 ' irrelevant, as by default AN0 is analog input TRISB = %0101011110000000 ' PortB.7 is external interrupt input Output watchdog_led $ifndef Radar4 ' radar boards 1,2,3 Output green_led ' PortB.4 Output orange_led ' PortB.5 Output yellow_led ' PortA.4 $endif $ifdef Radar4 ' used for 1 digit 7-segment LED display here Output PORTB.4 ' left dot not implemented in display - used for loopcnt Output PORTB.5 ' D3 Output PORTA.4 ' Right dot Output PORTB.0 ' D1 Output PORTB.1 ' D2 Output PORTA.1 ' D0 $endif $ifdef Enable_Timer1 ' used for Aeio/Rodo-Radar -period timer ' this timer is triggered and reset by Int0 on the negative edge of the comparator signal IPC0bits_T1IP0 = 1'1 ' set priority 1 IPC0bits_T1IP1 = 0'1 '1 ' on hybrlo set to 5 IPC0bits_T1IP2 = 0'1 ' 6 = 011 ' setting prescaler to :256, time units become 4.266 us ' longest period before overflow is 279 ms. T1CON.5 = 1 T1CON.4 = 1 ' ----------------------- T1CON.15 = 1 ' start timer IFS0bits_T1IF = 0 ' clear Timer1 interrupt flag Clear TMR1 ' reset to zero, so we count up to &HFFFF Set PR1 ' set to maximum count &HFFFF IEC0bits_T1IE = 1 ' Enable the Timer1 interrupt ' stays enabled in the Rodo_Radar application $endif $ifdef Enable_Timer23 ' main loop clock T2CONBITs_T32 = 1 ' 32- bit timer start T2CONbits_TCS = 0 ' internal clock T2CONbits_TON = 1 T2CONbits_TSIDL = 0 T2CON.5 = 1 ' pre-scale 256 T2CON.4 = 1 ' id. TMR2 = 0 TMR3HLD = 0 Set PR2 'PR2 = 65535 Set PR3 'PR3 = 65535 IPC2bits_T3IP0 = 0 '1 ' set priority to 0 IPC2bits_T3IP1 = 0 IPC2bits_T3IP2 = 0 IFS0bits_T3IF = 0 ' clear IRQ flag IEC0bits_T3IE = 1 ' enable timer 3 interrupt $endif $ifdef enable_Timer45 T4CONBITs_T32 = 1 ' 32- bit timer start T4CONbits_TCS = 0 ' internal clock T4CONbits_TON = 1 T4CONbits_TSIDL = 0 T4CON.5 = 1 ' pre-scale 256 T4CON.4 = 1 TMR4 = 0 TMR5 = 0 PR4 = 65535 PR5 = 65535 IPC7bits_T5IP0 = 1 ' set priority to 3 IPC7bits_T5IP1 = 1 IPC7bits_T5IP2 = 0 IFS1bits_T5IF = 0 ' clear IRQ flag IEC1bits_T5IE = 1 ' enable timer 5 interrupt $endif $ifdef Enable_Timer4 ' used as speed sampling clock ' prescaler can be slower, to make a 1 second buffer... T4CON.15 = 1 ' start timer in 16 bit mode T4CON.13 = 0 T4CON.6 = 0 ' prescaler set to 0: timing resolution should be 1/60MHz = 16.6666ns ' 01 = dive by 8 ' 10 = divide by 64 ' prescaler set to 11: divide by 256, so timing resolution becomes 4.266 us T4CON.5 = 1 T4CON.4 = 1 ' ------------------------ T4CON.3 = 0 ' operate as 16 bit timer T4CON.1 = 0 ' internal clock IPC6bits_T4IP0 = 1 ' set priority to 3 IPC6bits_T4IP1 = 1 IPC6bits_T4IP2 = 0 PR4 = 1000 ' geeft 234 S/s Clear IFS1.11 ' clear interrupt flag Set IEC1.11 ' enable interrupt $endif $ifdef Enable_Timer5 ' used as sampling rate clock in and for the ADC T5CON.15 = 1 ' start timer in 16 bit mode T5CON.13 = 0 T5CON.6 = 0 ' prescaler set to 0: T5CON.5 = 1 '0 T5CON.4 = 1 '0 ' ---------------------- T5CON.1 = 0 ' internal clock IPC7bits_T5IP0 = 1 ' set priority to 5 IPC7bits_T5IP1 = 0 IPC7bits_T5IP2 = 1 IFS1bits_T5IF = 0 ' clear IRQ flag 'PR5 = 29300 ' sampling rate should be 2048 S/s PR5 = 234 '58500 ' for 1024 S/s - gives 812 S/s measured. IEC1bits_T5IE = 1 ' enable timer 5 interrupt $endif $ifdef Enable_UART_RX ' init UART1-receiver: 31250 Baud ' generates an interrupt for each byte received U1MODE.0 = 0 ' = U1MODEbits.STSEL = 0 ' 1 stop-bit U1MODE.1 = 0 ' U1MODEbits.PDSEL = 0 ' 8 bit no parity U1MODE.2 = 0 U1MODE.5 = 0 ' =U1MODE_bits.ABAUD = 0 ' no autobauding U1MODE.3 = 0 ' = U1MODEbits.BRGH =0 ' 0 = standard speed mode - 16 clocks per bit U1MODE.4 = 0 ' logic high is the idle state for the input serial data (default) U1MODE.7 = 0 ' wakeup disabled U1MODE.8 = 0 U1MODE.9 = 0 U1BRG = 119 ' 239 ' voor 120MHz 119 ' voor 60MHz ((60000000 / Hserial_baud) / 16) - 1 ' BRGVAL U1STA.5 = 0 ' no bit8 U1STA.6 = 0 ' U1STAbits.URXISEL = 0 ' receive interrupt mode selection bits U1STA.7 = 0 ' interrupt flag is set when a byte is received U1MODE.15 = 1 '=U1MODEbits.UARTEN = 1 U1MODE.12 = 0 ' disable IrDA IPC2.12 = 0 ' set priority level to 6 for receiver IPC2.13 = 1 ' 1 IPC2.14 = 1 ' tested with change to 4, 1 step lower then the note timers...[09.10.2016] ' back to 6 on 10.10.2016, as this was not the cause for the glitches. IEC0.11 = 1 ' enable IRQ for receiver IEC4.1 = 1 ' enable IRQ for error trapping on receiver $endif $ifdef Enable_UART_TX ' UART1 transmitter: 31250 Baud U1STA.15 = 0 ' interrupt generated when character transferred to tx buffer and buffer is empty U1STA.10 = 1 ' transmit enable bit U1STA.11 = 0 ' U1STA.9 = UTXBF Transmit buffer full 1= full, 0 = we can write ' U1STA.8 = TRMT read only bit 1=shift register is empty and transmit buffer is empty ' 0=buffer had data, transfer in progress or queued Clear IFS0.12 ' clear transmit interrupt flag Set IEC0.12 ' enable interrupt IPC3.0 = 0 IPC3.1 = 1 IPC3.2 = 1 ' set priority to 6 $endif $ifdef Enable_ADC10bit ' this should initialise the ADC to 10 bit sampling mode with 4 simultaneous sample and holds ' would be perfect for a quadrada interface with 4 radars. ' AD1CON1: AD1CON1.10 = 0 ' 1 = select 12-bit mode, 1 S&H AD12B bit ' 0 = 10 bit mode with 4 S&H's AD1CON1.13 = 0 ' continue adc in idle mode AD1CON1.9 = 0 ' conversion to right alligned integer 0000 dddd dddd dddd AD1CON1.8 = 0 ' id. AD1CON1.7 = 1'0 '1 ' auto-convert mode - internal counter ends sampling and starts conversion AD1CON1.6 = 1'0 '1 ' id. AD1CON1.5 = 1' '1 ' id ' if 111 the samp bit (ADC1CON1.1) is automaticaly cleared to end sampling and start conversion. ' setting these 3 bits to 0 configures manual mode AD1CON1.4 = 0 ' SSRCG sample trigger source group. Must be 0 'AD1CON1.2 = 1 ' 1 = sampling immediately after last conversion. SAMP bit is autoset. ' this overrides the sampling rate generator... AD1CON1.2 = 0 ' sampling starts when the SAMP bit is set AD1CON1.1 = 0 ' the SAMP bit is AD1CON1.1 ' when AD1CON1.0 is 1, the ADC conversion has completed. ' this causes an interrupt. ' AD1CON2: AD1CON2.15 = 0 ' ref AvDD and AsSS AD1CON2.14 = 0 AD1CON2.13 = 0 AD1CON2.10 = 0 ' 0=no scan ' bits 6-2 = 0 ==> generates interrupt after every sample conversion AD1CON2.6 = 0 AD1CON2.5 = 0 AD1CON2.4 = 0 AD1CON2.3 = 0 AD1CON2.2 = 0 AD1CON2.1 = 0 ' always fill buffer from the start adres AD1CON2.0 = 0 ' use channel input selects for sample MUXA ' AD1CON3: AD1CON3.15 = 0 ' 0 = clock derived from system clock ' 1 = clock derived from internal RC clock AD1CON3.12 = 1 ' 10000 = 16 Tad -autosample time bits AD1CON3.11 = 0 ' / AD1CON3.10 = 0 '/ AD1CON3.9 = 0 ' / AD1CON3.8 = 0 '/ AD1CON3.Byte0 = 16 '127 '16 ' ADCS ADC1 conversion clock select bits (sampling rate) ' 255 gives toggle period = 3.9kHz so sampling rate is 7.8kS/s [measured 18.03.2017] ' 127 should give 7.8kHz and SR = 15.6kS/s ' measured : 7.81285kHz, SR = 15.6257 kS/s ' 63 15.5kHz and SR = 31.2kS/s ' 31 31 kHz and SR = 62.4kS/s ' 15 61 kHz and SR = 124.8kS/s ' 16 gives 58kHz (measured 08.2016) ' in manual mode the sampling rate is controlled by timer5 in our coding ' this setting sets the conversion speed. AD1CON4.8 = 0 ' no DMA - results stored in ADC1BUF0 to ADC1BUFF registers AD1CON4.2 = 0 ' allocate just 1 word for the buffer AD1CON4.1 = 0 ' / AD1CON4.0 = 0 ' / Clear AD1CHS0 ' clear complete register. AN0 is input channel Clear AD1CSSH AD1CSSL.0 = 1 ' select AN0 for input scan ' Set AD1CSSH.9 ' select AN0 for input scan 21.03.2017 added??? Clear AD1CSSL AD1CSSL.0 = 1 ' select AN0 for input scan ANSELA.0 = 1 ' AN0 is analog input - this is crucial!!! ' now we have to enable the interrupt and find out how to transfer data to an array IEC0.13 = 1 ' 1 = enable IRQ ' 0 = disable IRQ 'IPC3 <6:4> set the priority level to 5 IPC3.6 = 1 IPC3.5 = 0 IPC3.4 = 1 AD1CON1.15 = 1 ' adc module ON - done at the end of the configuration ' --------------------------------------------------------------------------------- $endif $ifdef Enable_ADC12bit ' 30.03.2017: used to sample the radar signal ' 01.04.2017: Sampling rate should be ca. 2048 S/s ' For the radar we try to set automatic sample and manual conversion mode. ' 09.04.2017: For radar we brought the sampling rate down to ca. 840 S/s ' 25.10.2017: Same settings for -radar ' Clearing AD1CON1.1 (SAMP bit) starts the conversion ANSELA.0 = 1 ' AN0 is analog input - this is crucial!!! ' AD1CON1: AD1CON1.15 = 0 ' ADC module must be off before changing to 12-bit mode AD1CON1.10 = 1 ' 1 = select 12-bit mode, 1 S&H AD12B bit ' 0 = 10 bit mode with 4 S&H's AD1CON1.13 = 0 ' continue adc in idle mode AD1CON1.9 = 0 ' conversion to right alligned integer 0000 dddd dddd dddd AD1CON1.8 = 0 ' id. ' setting AD1CON1.9 to 1 and AD1CON1.8 to 0 gives fractional format dddd dddd dddd 0000 ' 07.04.2017: set to fractional formar for ease on integration ' so now we should have dddd dddd dddd 0000 ' did'nt help us any further, so set back to 0000 dddd dddd dddd ' SSRC bits AD1CON1.7 = 0 ' 1'0 '1 ' auto-convert mode - internal counter ends sampling and starts conversion AD1CON1.6 = 0 '1'0 '1 ' id. AD1CON1.5 = 0 '1' '1 ' id ' if 111 the samp bit (ADC1CON1.1) is automaticaly cleared to end sampling and start conversion. ' setting these 3 bits to 0 configures manual mode AD1CON1.4 = 0 ' SSRCG sample trigger source group. Must be 0 ' ASAM bit: AD1CON1.2 = 1 ' sampling immediately after last conversion. SAMP bit is autoset. 'AD1CON1.2 = 0 ' sampling starts when the SAMP bit is set ' the SAMP bit is AD1CON1.1 ' when AD1CON1.0 is 1, the ADC conversion has completed. ' this causes an interrupt. ' so now AD1CON1 should be &B0100000000000100 ' AD1CON2: AD1CON2.15 = 0 ' ref AvDD and AsSS AD1CON2.14 = 0 AD1CON2.13 = 0 AD1CON2.10 = 0 ' no scan AD1CON2.9 = 0 ' convert CH0 AD1CON2.8 = 0 ' / ' bits 6-2 = 0 ==> generates interrupt after every sample conversion AD1CON2.6 = 0 AD1CON2.5 = 0 AD1CON2.4 = 0 AD1CON2.3 = 0 AD1CON2.2 = 0 AD1CON2.1 = 0 ' always fill buffer from the start adres AD1CON2.0 = 0 ' use channel input selects for sample MUXA ' the example code in the manual clears AD1CON2.byte1 completely.... ' AD1CON3: ' AD1CON3.15 = 0 ' clock derived from system clock ' AD1CON3.12 = 1 ' 10000 = 16 Tad -autosample time bits must be >3 after datasheet ' AD1CON3.11 = 1 ' / ' AD1CON3.10 = 1 '/ ' AD1CON3.9 = 1 ' / ' AD1CON3.8 = 1 '/ Clear AD1CON3.Byte1 Set AD1CON3.Byte0 ' = 255 'AD1CON3.Byte0 = 32 ' 255 '127 '16 ' ADCS ADC1 conversion clock select bits (sampling rate) ' 255 gives toggle period = 3.9kHz so sampling rate is 7.8kS/s [measured 18.03.2017] ' 127 should give 7.8kHz and SR = 15.6kS/s ' measured : 7.81285kHz, SR = 15.6257 kS/s ' 63 15.5kHz and SR = 31.2kS/s ' 31 31 kHz and SR = 62.4kS/s ' 15 61 kHz and SR = 124.8kS/s ' 16 gives 58kHz (measured 08.2016) ' in manual mode the sampling rate is controlled by timer5 in our coding ' this setting sets the conversion speed. ' AD1CON4: 'AD1CON4.8 = 0 ' no DMA - results stored in ADC1BUF0 to ADC1BUFF registers 'AD1CON4.2 = 0 ' allocate just 1 word for the buffer DMABL<2:0> 'AD1CON4.1 = 0 ' / 'AD1CON4.0 = 0 ' / Clear AD1CON4 ' as in the manual for automatic sample and manual conversion Clear AD1CHS0 ' clear complete register. AN0 is input channel for CH0 Clear AD1CHS123 ' not implemented in 12 bit mode Clear AD1CSSH Clear AD1CSSL ' now we have to enable the interrupt and find out how to transfer data to an array IEC0.13 = 1 ' 1 = enable IRQ ' 0 = disable IRQ 'IPC3 <6:4> set the priority level to 5 IPC3.6 = 1 IPC3.5 = 0 IPC3.4 = 1 IFS0.13 = 0 ' clear interrupt flag AD1CON1.15 = 1 ' adc module ON - done at the end of the configuration ' --------------------------------------------------------------------------------- $endif $ifdef Enable_Int0 ' 31.03.2017: This works fine now. [ Rodo-Radar code] ' external int. signal is generated on window-cross of the Doppler signals ' used for half period measurement. ' IFS0.0 = INT0IF bit interrupt flag ' IEC0.0 = INT0IE bit interrupt enable flag ' IPC0.0, IPC0.1, IPC0.2 interrupt priority bits, INT0IP bits IPC0.0 = 0 ' priority level set to 4 IPC0.1 = 0 IPC0.2 = 1 Set IEC0.0 ' 0 = disable interrupt on start-up ' 1 = enable interrupt on start-up Clear IFS0.0 ' clear irq flag INTCON2.0 = 1 ' 0 = irq on positive edge INT0EP bit ' 1 = irq on negative edge ' the comparator output is high at rest INTTREG.Byte0 = %00001000 ' do we need this? $endif $ifdef Enable_PWM ' PWM channel initialisation ------------------------------------------------------ ' CNPD1 ' enable internal pull down resistor to reset the FLT32 flag on init ' disable pwm interrupts: IEC5.14 = 0 IEC5.15 = 0 IEC6.0 = 0 ' clear interrupt flags: Clear IFS5.14 Clear IFS5.15 Clear IFS6.0 ' pwm time base control register: PTCON 'PTCON.pwm Clear PTCONbits_PTEN ' = PTCON.15 = 0 ' pwmx disabled for setting the bits, should be enabled at the end. PTEN 'PTCON Timebase control register Clear PTCONbits_PTSIDL ' = PTCON.13 ' PTCONbits_SESTAT 'PTCON.12 ' status bit to read Clear PTCONbits_SEIEN ' PTCON.11 disable special event interrupt 'Set PTCONbits_EIPU ' PTCON.10 1 = active period register is updated immediately Clear PTCONbits_EIPU ' PTCON.10 0 = active period register updates occur on PWMx cycle boundaries : setting changed 09.10.2016 Clear PTCONbits_SYNCPOL ' PTCON.9 sync active high. Irrelevant here as we do not use sync Clear PTCONbits_SYNCOEN ' PTCON.8 = 0 ' disable sync output Clear PTCONbits_SYNCEN ' PTCON.7 = 0 ' no external sync Clear PTCONbits_SYNCSRC0 'PTCON.4 Clear PTCONbits_SYNCSRC1 'PTCON.5 Clear PTCONbits_SYNCSRC2 'PTCON.6 Clear PTCONbits_SEVTPS0 'PTCON.0 special event postscaler bits Clear PTCONbits_SEVTPS1 'PTCON.1 Clear PTCONbits_SEVTPS2 'PTCON.2 Clear PTCONbits_SEVTPS3 'PTCON.3 '%110 = / 64 ' timing resolution should become 64x8.5ns = 544ns = 0.544us ' PTPER register primary master time base period register 'PTPER = 64 '32678 ' master time base period register --> PWM frequency 16-bits ' 1 unit is 8.33ns with a 60MHz Fcy ' so 32678 would give 3673 Hz Select PWMmodus Case 0 ' this works o.k. now 'PWMCON1.9 = 0 ' ITB: Independent time base mode if set to 1 'PWMCON2.9 = 0 ' PTPER register steers time base if set to 0 'PWMCON3.9 = 0 ' we do not have a SPHASE1, 2, 3 register thus independent pwm control is not possible ' cfr manual example 14-14, p.44 Clear PWMCON1 Clear PWMCON2 Clear PWMCON3 ' PTCON2 register ' pwm input clock prescaler, set to 1 (no division) 'Set PTPER ' set to lowest frequency = 1831,16 Hz ' for the ADSR implementation we should set this as fast as possible! 'PTPER = 1024 ' 256 '1024 ' would this limit the useable range for PWM values??? ' 1024 gives a pwm base frequency of 117kHz PTPER = 4096 ' it gives 29kHz base freq ' with this setting we have 12-bit resolution, matching the ADC resolution Clear PTCON2bits_PCLKDIV0 ' PTCON2.0 ' bit0 Clear PTCON2bits_PCLKDIV1 ' PTCON2.1 ' bit1 Clear PTCON2bits_PCLKDIV2 ' PTCON2.2 ' bit2 Clear PDC1 Clear PDC2 Clear PDC3 Clear PHASE1 Clear PHASE2 Clear PHASE3 Set MDC ' set to longest period ' used in radar interface for debugging and FM modulation: ' The IOCON1, IOCON2, IOCON3 registers are protected and locked with a key. IOCON1.15 = 1 ' pwm module controls the PWM1H pin - pin 25 IOCON1.14 = 1 ' pwm module controls the PWM1L pin - pin 26 : radar FM control ' polarity bits: ' we invert polarity for PWM1 only: IOCON1.13 = 0 ' 1 - pwmH pin is active low '0 = pwmH pin is active high IOCON1.12 = 0 ' 1 = pwmL pin is active low '0 = pwmL pin is active high - radar FM ' set to redundant outputs: IOCON1.11 = 0 ' 10 = push pull mode, 01 = redundant mode, 00 = complimentary IOCON1.10 = 1 ' IOCON1.9 = 0 ' no override IOCON1.8 = 0 'id. IOCON1.1 = 1 ' 1= swap pins, 0 = no pin swaps ' IOCON1 = %1100 0100 0000 0010 = &HC402 IOCON2.15 = 1 ' blue led IOCON2.14 = 1 ' blue led IOCON2.13 = 0 IOCON2.12 = 0 IOCON2.11 = 1 ' 10 push pull mode IOCON2.10 = 0 IOCON2.9 = 0 IOCON2.8 = 0 ' IOCON2 = %1100 1000 0000 0000 = &HC800 IOCON3.15 = 1 ' white led IOCON3.14 = 1 ' white led must be set to 0 if the pins have to be used as nomal I/O pins. IOCON3.13 = 0 IOCON3.12 = 1 IOCON3.11 = 1 ' push pull IOCON3.10 = 0 ' IOCON3 = IOCON2 = &HC800 ' the FCLCON1,2,3 and IOCON1,2,3 require a key to be written: ' pwm channel 1: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON1 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON1 ' set pwm ownership and polarity to IOCON1 ' IOCON1 = 0xC000 sets pwm mode to complementary outputs Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC402, w0 ' required value for IOCON1 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON1 ' pwm channel 2: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON2 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON2 ' set pwm ownership and polarity to IOCON2 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC800, w0 ' required value for IOCON2 - complementary Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON2 ' pwm channel 3: ----------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON3 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON3 ' set pwm ownership and polarity to IOCON1 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC800, w0 ' required value for IOCON3 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON3 ' now we have ports free for the timer-tone generators: ' not used in Rodo_Radar ' Symbol Note_Port1 PORTB.15 ' Symbol Note_Port2 PORTB.13 ' Symbol Note_Port3 PORTB.11 ' Output Note_Port1 ' Output Note_Port2 ' Output Note_Port3 Case 1 ' cfr. example 14-18, p.48 in manual 'PWMCON1.9 = 1 ' ITB: Independent time base mode if set to 1 'PWMCON2.9 = 1 ' PTPER register steers time base if set to 0 'PWMCON3.9 = 1 ' we do not have a SPHASE1, 2, 3 register thus independent pwm control is not possible ' IOCON1,2,3 must be $C000 PWMCON1 = $0200 PWMCON2 = $0200 PWMCON3 = $0200 ' PTCON2 register ' pwm input clock prescaler, set to /64 Clear PTCON2bits_PCLKDIV0 ' PTCON2.0 ' bit0 Set PTCON2bits_PCLKDIV1 ' PTCON2.1 ' bit1 Set PTCON2bits_PCLKDIV2 ' PTCON2.2 ' bit2 Set PTPER '= 256 ' test value - probably irrelevant in this mode Set PHASE1 ' freq to lowest Set PHASE2 Set PHASE3 Clear PDC1 ' duty cycles note: PDC1 < PHASE1 Clear PDC2 Clear PDC3 Set MDC ' ? clear mdc - seems irrelevant here ' make the pwmL port free for general I/O: IOCON1.15 = 1 IOCON1.14 = 0 IOCON2.15 = 1 IOCON2.14 = 0 IOCON3.15 = 1 IOCON3.14 = 0 ' the FCLCON1,2,3 and IOCON1,2,3 require a key to be written: ' pwm channel 1: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON1 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON1 ' set pwm ownership and polarity to IOCON1 ' IOCON1 = 0xC000 sets pwm mode to complementary outputs Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0x8000, w0 ' required value for IOCON1 -pwmL disabled. Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON1 ' pwm channel 2: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON2 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON2 ' set pwm ownership and polarity to IOCON2 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0x8000, w0 ' required value for IOCON2 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON2 ' pwm channel 3: ----------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON3 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON3 ' set pwm ownership and polarity to IOCON1 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0x8000, w0 ' required value for IOCON3 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON3 ' now we have ports free for ADRS: Symbol ADSR_Port1 PORTB.15 Symbol ADSR_Port2 PORTB.13 Symbol ADSR_Port3 PORTB.11 Output ADSR_Port1 Output ADSR_Port2 Output ADSR_Port3 Case 2 ' 3-phase motor control setting ' ref. ,manual 14-16, p. 46 'PWMCON1.9 = 0 ' ITB: Independent time base mode if set to 1 'PWMCON2.9 = 0 ' PTPER register steers common time base if set to 0 'PWMCON3.9 = 0 PWMCON1 = $0100 PWMCON2 = $0100 PWMCON3 = $0100 ' PTCON2 register ' pwm input clock prescaler, set to /64 Clear PTCON2bits_PCLKDIV0 ' PTCON2.0 ' bit0 Set PTCON2bits_PCLKDIV1 ' PTCON2.1 ' bit1 Set PTCON2bits_PCLKDIV2 ' PTCON2.2 ' bit2 Clear MDC ' master duty cycle control - set to zero on init Set PTPER ' lowest freq. Clear PHASE1 ' 0 graden PHASE2 = 21845 ' 120 graden PHASE3 = 43690 ' 240 graden ' the FCLCON1,2,3 and IOCON1,2,3 require a key to be written: ' pwm channel 1: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON1 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON1 ' set pwm ownership and polarity to IOCON1 ' IOCON1 = 0xC000 sets pwm mode to complementary outputs Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC000, w0 ' required value for IOCON1 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON1 ' pwm channel 2: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON2 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON2 ' set pwm ownership and polarity to IOCON2 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC000, w0 ' required value for IOCON2 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON2 ' pwm channel 3: ----------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON3 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON3 ' set pwm ownership and polarity to IOCON1 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC000, w0 ' required value for IOCON3 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON3 Case 3 ' 2-phase ac motor PWMCON1 = $0100 PWMCON2 = $0100 Clear PTcon2bits_PCLKDIV0 Set PTcon2bits_PCLKDIV1 Set PTcon2bits_PCLKDIV2 Clear MDC Set PTPER Clear PHASE1 PHASE2 = 16384 ' 90 graden ' the FCLCON1,2,3 and IOCON1,2,3 require a key to be written: ' pwm channel 1: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON1 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON1 ' set pwm ownership and polarity to IOCON1 ' IOCON1 = 0xC000 sets pwm mode to complementary outputs Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC000, w0 ' required value for IOCON1 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON1 ' pwm channel 2: -------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON2 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON2 ' set pwm ownership and polarity to IOCON2 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC000, w0 ' required value for IOCON2 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON2 ' pwm channel 3: ----------------------------------------------- Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC003, w0 ' required value for FCLCON3 ' %1100000000000000 = &HC000 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, FCLCON3 ' set pwm ownership and polarity to IOCON1 Mov #0xabcd, w10 ' etc... p. 226 pwm manual Mov #0x4321, w11 Mov #0xC000, w0 ' required value for IOCON3 Mov w10, PWMKEY Mov w11, PWMKEY Mov w0, IOCON3 EndSelect ' common settings: PWMCON1.12 = 0 'fault interrupt disabled PWMCON2.12 = 0 PWMCON3.12 = 0 PWMCON1.11 = 0 'current limit disabled PWMCON2.11 = 0 PWMCON3.11 = 0 PWMCON1.10 = 0 'trigger event interrupts disabled PWMCON2.10 = 0 PWMCON3.10 = 0 ' PWMCON1.9 = 1 ' ITB: Independent time base mode if set to 1 ' PWMCON2.9 = 1 ' PTPER register steers time base if set to 0 ' PWMCON3.9 = 1 ' we do not have a SPHASE1, 2, 3 register thus independent pwm control is not possible ' PWMCON1.8 = 0 'PCD1 en SDC1 registers provide duty cycle info - ' PWMCON2.8 = 0 ' PWMCON3.8 = 0 PWMCON1.7 = 1 ' dead time disabled PWMCON2.7 = 1 PWMCON3.7 = 1 ' PWMCON1.6 = 0 ' PWMCON2.6 = 0 ' PWMCON3.6 = 0 ' PWMCON1.3 = 0 ' PWMCON2.3 = 0 ' PWMCON3.3 = 0 ' PWMCON1.2 = 0 ' edge aligned mode CAM bit. Ignored when ITB = 0 ' PWMCON2.2 = 0 ' PWMCON3.2 = 0 ' PWMCON1.1 = 0 ' PWMCON2.1 = 0 ' PWMCON3.1 = 0 ' PWMCON1.0 = 1 ' PWMCON2.0 = 1 ' PWMCON3.0 = 1 ' The pwm1 to pwm3 values for the duty cycle are in the PDC1, PDC2 and PDC3 registers ' The phases in the PHASE1, PHASE2, PHASE3 registers, if not used for frequency. AUXCON1 = 0 AUXCON2 = 0 AUXCON3 = 0 Set PTCONbits_PTEN ' = PTCON.15 pwmx should be enabled at the end. $endif Variables: ' variable declarations: ' variables for midi reception and parsing: ' if buffers are > 255, indexes must be word! Dim RCIdxIn As Word ' Pointer to the next empty location in the buffer Dim RCIdxOut As Word ' Pointer to the location of the oldest character in the buffer Dim RCBuffer[RCBufArraySize] As Byte ' Array for holding received characters in the uart Dim TXBuffer[TXBufArraysize] As Byte ' buffer for midi-output UART Dim TXIdxIn As Word Dim TXIdxOut As Word Dim Bytein As Byte ' midi byte read from buffer Dim StBit As Bytein.7 ' highest bit of ByteIn ' midi variables Dim statusbyte As Byte Dim noteUit As Byte ' note off + release value Dim release As Byte Dim noteAan As Byte ' note on + release value Dim velo As Byte Dim notePres As Byte ' note pressure + pressure value Dim pres As Byte Dim Ctrl As Byte ' continuous controller + value Dim value As Byte Dim prog As Byte ' program change + program-byte Dim aft As Byte ' channel aftertouch Dim pblsb As Byte ' pitch bend lsb Dim pbmsb As Byte ' pitch bend msb ' variables for the timing system: Dim time As Dword ' 4 us resolution 32-bits - must be Dword! Dim maxtim As time.31 ' overflow bit, will cause timer reset after 6 hours Dim i As Word Dim j As Word ' used in timer4 ISR Dim idx As Byte Dim Nxt As Dword ' must be dword Dim TimVals[NrTasks] As Dword ' task periods. Values set when inactive. Dim resort_flag As Bit ' if we load a timer-tesk, we have to set this flag Dim velflags As Word ' bits 0 to 15 for tasks 0 to 15 ' 16 bit variables and floats for the PWM system (not used in this code) Dim pwm1value As Word Dim pwm2value As Word Dim pwm3value As Word Dim pwm1freq As Word Dim pwm2freq As Word Dim pwm3freq As Word Dim pwm1phase As Word Dim pwm2phase As Word Dim pwm3phase As Word ' vaiables for speed measurement in INT0 and Timer1 30.03.2017 Dim Period_Flags As Word Dim Period_Invalid_Flag As Period_Flags.0 ' set on timer 1 overflow: movement absent or too slow Dim Period_Jitter_Flag As Period_Flags.1 ' jitter in period calculation algorithm Dim No_Data_Flag As Period_Flags.2 ' set when amplitudes are under noise level Dim Period_Overflow_Flag As Period_Flags.3 ' 04.11.2017 Dim t1val As Dword ' used in INT0 ISR changed to dword 20.04.2017 Dim t0val As Dword Dim T1overflow As Word ' hiword counter to make 32 bits Dim AvSpeed As Dword ' averaged speed value used in timer4 ISR ' these seem to offend the compiler if used in an ISR: Dim T4float As Float ' integrator for speed used in task 4 Dim ADfloat As Float ' integrator for ADC values used in task 3 ' variables for data acquisition Dim sample As Word ' used in the ADC, 12 bit direct value Dim oldsample As Word Dim dif As SWord Dim rec As Word Dim recp As Word Dim recn As Word Dim DataBuffer[256] As SWord ' adc databuffer for sampler - surface ' this buffer contains 125 ms of data ' when the sample rate is 2048 S/s ' 250 ms with 1024 S/s ' 29.10.2017: at 812 S/s the buffertime is 315 ms ' we had to make it sword for the implementation of dS 04.11.2017 Dim DataInIdx As Byte ' pointer to the most recent data. Must be byte! Dim DataOutIdx As Byte ' not used here Dim DataFlags As Byte Dim NewData As DataFlags.0 ' set when DataInIdx changes ' reset in the main loop for noise level automation 'Dim accel As SWord ' bipolar calculated in timer4 ISR ' first derivative of speed . Normal range is -64 to +63 ' if positive we have speedup ' if negative we have slowdown Dim accel As Float ' changed to float 03.11.2017 Dim Speedbuffer[256] As SWord ' 250ms buffer if the sample rate is 1000 S/s ' 29.10.2017: 834 S/s, so the buffer covers 307 ms ' note that the range is 0 to 500, so it does exceed byte-sizes Dim SpeedInIdx As Byte ' pointer to the most recent data Dim Spd[256] As Word ' filled in the INT0 ISR - primary speed data buffer Dim SpdInIdx As Byte Dim SpdOutIdx As Byte Dim minval As Byte ' for autoregulation of CC74 noise level ' controllers: Dim CC7 As Byte ' ebow level (volume) Dim Init As Word ' flag for interactivity mode initialisation RadaAeio Dim coldboot As Word ' set to 1 on init - stays 0 until power is switched off Dim difword As Word Dim CC70 As difword.Byte0 ' time interval dt for acceleration accel = dv/dt Dim surfword As Word Dim CC71 As surfword.Byte0 ' time interval for dS. differential of surface Dim dS As Float ' first derivative of moving surface data (amplitude) ' if positive we have exploding gesture ' if negative we have imploding gesture ' changed to float 03.11.2017 to implement dS = dS/dt Dim CC73 As Word ' sensit for AeioRising radar3 Dim noiseword As Word Dim CC74 As noiseword.Byte0 Dim CC77 As Word ' multiplier/rescaler for dS values - default = 1 Dim CC78 As Word ' for accelleration mapping (multiplier) - default = 16 ' should autoregulate (multiplier for accel values) Dim CC79 As Word ' 0 = enable radar system ' > 0 = disable radar system and interactivity ' meta variables for the durations of the embedded compositions: Dim Durations[Last_Piece + 1] As Word ' added 02.11.2017 ' variables for RadaAeio Dim Nt[NrNotes] As Byte ' mapping hammers Dim eNt[96] As Byte ' mapping ebowed strings Dim nidx As Word Dim RA_beaterscaler As Word ' for pitch mapping (divider) on beater notes ' should be autoregulating Dim RA_stringscaler As Word ' for pitch mapping (divider) on ebow notes ' should be autoregulating Dim noot As Byte ' note for interactive mode Dim oldnoot As Byte Dim ebnoot As Byte ' note for ebow in interactive mode Dim oldebnoot As Byte Dim veel As Byte ' velocity byte for RadaAeio Dim lites As Word Dim Blue As lites.0 ' on/off flags Dim Red As lites.1 Dim YellowL As lites.2 Dim YellowR As lites.3 Dim ritme As Word Dim tg As ritme.0 ' beaters toggle bit for composition code Dim ebtg As ritme.1 ' ebow toggle bit for composition code Dim lbtg As ritme.2 ' toggle for blue and red lights Dim aval As SWord ' limited accelleration value must be signed bipolar! ' integer rescaled value for accel. aval = accel * CC78 Dim IApiece As Word ' set with prog.change to select an interactive mapping. ' this way it is possible to embed different compositions. ' Variables for AeioRising (piece 2): [IApiece = 1] ' also used for AeioSinking Dim Qm As Float ' quantity of movement: dS * accel Dim sens As Word ' sensitivity for trigger Dim duur As Dword Dim interval As Word Dim interval_divider As Word ' initialised to value 1 ' dim QmMax as word ' 0 on init ' Variables for Aeio's Response: Dim AR_Idx As Word Dim AR_Count As Word Dim AR_Speed As Word ' could this overflow? ' Variable for automated time scheduling of the embedded compositions. Dim Klok As Word ' if we increment this variable on each change of TIM3.8 ' it has a pace of 71", or a bit over a minute Dim Kltg As ritme.8 Dim start As Word Dim halt As Word ' stop is a reserved statement, hence we use halt Dim Dur2[128] As Word ' durations lookup for tasks Dim Dur[128] As Word ' chromatic mapping ' for peak detection: Dim Smax As Word Dim Smaxtmp As Word Dim Vmax As Word Dim Vmaxtmp As Word Dim test As Byte ' for debugging Dim condition As Word ' for aeiorising and aeiosinking Variable_Inits: Clear IApiece ' so we start with the piece numbered 0 ' RadaAeio = 0 ' AeioRising = 1 ' Xtof = 2 ' AeioSinking = 3 ' Aeio's Respons = 4 Clear Init ' force initialisation GoSub Dur_Lookup1 GoSub Dur_Lookup2 GoSub Note_Lookup Set coldboot ' reset after initialisation Clear RCBuffer ' Rx Clear RCIdxIn ' Clear the buffer internal pointer Clear RCIdxOut ' Clear the buffer external pointer Clear time Clear TXBuffer ' Tx Clear TXIdxIn Clear TXIdxOut Set TimVals ' array Clear velflags ' flags Clear DataBuffer ' ADC - surface data Clear DataInIdx Clear DataOutIdx ' not used Clear Speedbuffer ' speeddata - buffer Clear SpeedInIdx Clear Spd ' period buffer Clear SpdInIdx Clear SpdOutIdx minval = 127 ' for CC74 noise autoregulator ' must be set to max. on initialisation. ' CC74 can never be smaller than minval Durations[RadaAeio_piece] = RadaAeio_duration ' set to the symbolic constants on cold boot. Durations[AeioRising_piece] = AeioRising_duration Durations[Xof_piece] = Xof_duration Durations[AeioSinking_piece] = AeioSinking_duration Durations[Aeio_Respons_piece] = AeioRespons_duration ' variables for peak detection of the radar signals: Clear Smax Clear Smaxtmp Clear Vmax Clear Vmaxtmp CC79 = CC79_default ' enable radar $ifndef Radar4 Low green_led Low yellow_led Low orange_led $else HexDis (15) ' blank hex display $endif ' initialise data acquisition system: (this is allways ON even when interactivity is disabled) Set IEC0.0 ' enable external INT0 IRQ for speed measurement Set IEC0bits_T1IE ' start Timer1 IRQ Set IEC0.13 ' enable ADC IRQ Clear IFS0.13 ' clear ADC IRQ flag $ifdef Radar3 PDC1 = 0 ' no change of radar frequency required $endif Clear AD1CON1.0 ' clear done bit ADC Set AD1CON1.1 ' start sampling ' start timer 5 as sampling rate generator for the ADC: PR5 = 288 ' without prescaler we had 58500 '14606 Clear IFS1.12 ' clear irq flag Set IEC1bits_T5IE ' set IEC1.12 ' start IRQ ' same for timer 4, sampling speed and accelleration: PR4 = 1000 'without prescaler 64000 Clear IFS1bits_T4IF ' clear interrupt flag Set IEC1bits_T4IE ' enable interrupt oldsample = DC_Offset_Init ' set to halfway, or 1.65V accel = 0 ' bipolar float! aval = 0 ' sword Clear lites Clear ritme CC70 = CC70_default ' 48 '64 '10 ' dt for derivative of speed ' CC70 = 48 is a reasonable default. (dt = 205 ms) ' the midi value is thus 24 CC71 = CC71_default ' 164 '64 '36 ' dt for derivative of surface ' CC71 = 164 gives dt = 202 ms ' the midi value is thus 82 CC73 = CC73_default ' sensit. for AeioRising radar3 CC74 = CC74_default ' 1 ' noise floor for surface data ' was 5, but should now be autoregulating RA_stringscaler = 1 ' pitch mapping divider for ebow notes RA_beaterscaler = 1 ' pitch mapping sensitivity (divider) for beater notes ' 15.04.2017: autoregulating now. ' the controller can be set to reset the value. CC78 = CC78_default ' 16 ' accelleration mapping multiplier ' this corresponds to midi value 15 ' as we add 1 in the controller procedure CC79 = CC79_default ' radar enabled interval_divider = 1 ' autoregulating 8 '16 ' init for aeio-rising GoSub Init_RadaAeio ' this will clear coldboot once GoTo MAIN ' jump over interrupt handlers Interrupt_handling: ' ------------------- Isr- INT0Interrupt ' external interrupt ' used to measure period of radar doppler frequency ' this interrupt is received on a low going edge of the comparator signal. ' timer1 is started here for period measurement ' in this version the INT0 stays always enabled ' 20.04.2017: overflow counter added such that we can measure very slow speeds as well ' In principle it is impossible that the input signal stays low ' With the change of comparator circuit, we are now measuring full ' periods, no longer half periods. ' If the doppler frequency for a movement of 1 m/s is 70Hz the period is 14.28 ms ' This is equivalent to a count of 3354 units ' Taking 5 m/s as maximum possible speed of movement, the minimum valid count becomes 670 ' Taking 1cm/s as slowest possible speed, the maximum count becomes 335400 units. ' Inverting the periods to speed or frequency values gives us a range of 0 to 500 Clear IFS0.0 ' clear interrupt flag t1val.Word0 = TMR1 ' 16 bit t1val.Word1 = T1overflow ' aantal timer1 overflows, so 279 ms units. Clear TMR1 ' reset timer Clear T1overflow If t1val > t0val + 670 Then Clear t0val 'If t1val > 335400 Then t1val = 335400 ' low limit Inc SpdInIdx Spd[SpdInIdx] = 335400 / t1val ' 0 to 500 - in frequency units Clear Period_Invalid_Flag Else ' in this case we had glitches on the input ' or non-human movement of some kind. ' input glitches can be caused by movement too close to the radar. Set Period_Invalid_Flag t0val = t1val ' or t0val = t0val + t1val ??? EndIf EndIsr- Isr- T1Interrupt ' timer1 interrupt ' happens on timer1 overflow (279 ms) - 4.25us resolution ' here to be used for period measurement triggered with INT0 ' if this interrupt happens, we have a timer overflow. Clear IFS0bits_T1IF ' Reset the Timer1 interrupt flag Clear TMR1 ' this is required as we always start the chrono from 0 ' Clear IEC0bits_T1IE ' disable timer 1 interrupt (stop timer, it is started in INT0) Inc T1overflow ' increment timer overflow counter ' each unit is 279 ms Clear T1overflow.15 ' added 04.11.2017 to limit value if there is no movement. So 2h30' becomes max. period. 'Toggle green_led ' this works EndIsr- Isr- T3Interrupt Clear IFS0bits_T3IF ' 32-bit value reached (T2/T3 combined) ' this is our main timer! ' this interrupt should never happen... EndIsr- Isr- T4Interrupt ' sampler for movement speed ' used for maintenance of a speed databuffer ' this is a periodic timer set to 234 S/s Clear IFS1bits_T4IF ' 16-bit value reached , clear interrupt flag ' Clear IEC1bits_T4IE ' disable interrupt Clear TMR4 ' average available speed measurements acquired in the INT0 ISR: ' 03.11.2017 - new coding: If SpdOutIdx = SpdInIdx Then ' niks - Avspeed stays whatever it was... AvSpeed = Spd[SpdOutIdx] Else ' average available speed measurements acquired in the INT0 ISR: Clear AvSpeed Clear j While SpdOutIdx <> SpdInIdx Inc SpdOutIdx Inc j AvSpeed = AvSpeed + Spd[SpdOutIdx] ' so range should still be 1 - 500 Wend AvSpeed = AvSpeed / j ' j is always > 0 now EndIf TimVals[4] = time + 200 ' enable the integrator task for speed data Set resort_flag ' toggle yellow_led ' 09.04.2017: 117Hz or sampling rate = 234 S/s EndIsr- Isr- T5Interrupt ' used as sampling rate clock source for the ADC ' for rodo-radar we set it at 2048 S/s in a first experiment. ' this is about twice the highest possible frequency in the input signal (ca. 1kHz) ' thus meeting the Nyquist law. ' 08.04.2017: set to 1024 S/s ' 09.04.2017: Prescaler set to :256 Clear IFS1bits_T5IF ' 32-bit value reached if T4/T5 operation ib 32 bits ' 16-bit value reached if operated alone. Clear TMR5 Clear AD1CON1.1 ' start conversion of the automatically acquired sample 'Toggle yellow_led ' for debug, measurement of sampling rate ' 09.04.2017: 406Hz, so 812 S/s EndIsr- Isr- U1RXInterrupt ' UART receive IRQ - midi receiver Clear IFS0.11 ' reset UART1 receive irq flag 'Inc RCIdxIn ' Move up the buffer index (0-255) ' if we make the buffer larger, we need to AND ' the index with the size of the buffer -1. RCIdxIn = (RCIdxIn + 1) & RCBufSize RCBuffer[RCIdxIn] = U1RXREG 'Toggle midi_led 'debug EndIsr- Isr- U1ErrInterrupt ' this irq is generated on UART1 receive errors ' this interrupt is enabled by setting IEC4.1 ' error handling: Clear IFS4.1 ' clear interrupt flag If U1STA.2 = 1 Then 'Set framing_error_led ' no longer happening EndIf If U1STA.1 = 1 Then ' = overrun error 'Set overrun_error_led ' not happening Clear U1STA.1 EndIf EndIsr- Isr- U1TXInterrupt ' UART send IRQ Clear IFS0bits_U1TXIF ' reset UART1 transmit IRQ flag $ifndef Radar4 Toggle green_led ' transmit monitor $endif EndIsr- Isr- AD1Interrupt ' this irq happens after every ADC conversion ' the sampling rate is controlled by timer 5 , here 2048 S/s ' use of floats here crashes the compiler. ' even using a multiply seems impossible ' 08.04.2017: sampling rate down to 1024 S/s Clear IFS0.13 ' clear AD1 interrupt flag Clear AD1CON1.0 ' clear the conversion-done flag sample = ADC1BUF0 ' 12-bit value format 0000 xxxx xxxx xxxx ' differenciator version with rectification: If sample > oldsample Then recn = sample - oldsample Else recn = oldsample - sample ' rec now 0 --> 2048 EndIf rec = recn + recp ' minimal integration 0 --> 4096 recp = recn oldsample = sample ' now we use a one shot timer to perform integration using floats ' thus integration will be synchronous with the sampling rate ' there can be jitter! TimVals[3] = time + 120 Set resort_flag ' for sorttimers ' Toggle orange_Led ' for testing sampling rate. Sampling rate is this frequency * 2 EndIsr- Isr- PWM1Interrupt Clear IFS5.14 EndIsr- Isr- PWM2Interrupt Clear IFS5.15 EndIsr Isr- PWM3Interrupt Clear IFS6.0 EndIsr- GetMidi: If RCIdxIn <> RCIdxOut Then RCIdxOut = (RCIdxOut + 1) & RCBufSize Bytein = RCBuffer[RCIdxOut] Else Set Bytein EndIf Return 'GetADC: ' here we can perform data extraction and signal conditioning ' the data-buffer has 256 words ' as we sample at 2048 S/s this covers 125 ms 'Return Proc mPlay (stat_byte As Byte, not_byte As Byte, vel_byte As Byte) ' can be used for all 3-byte midi messages TXIdxIn = (TXIdxIn + 1) & TXBufSize ' overflow at 1023 TXBuffer[TXIdxIn] = stat_byte TXIdxIn = (TXIdxIn + 1) & TXBufSize TXBuffer[TXIdxIn] = not_byte & 127 TXIdxIn = (TXIdxIn + 1) & TXBufSize TXBuffer[TXIdxIn] = vel_byte & 127 EndProc Proc mOut (stat_byte As Byte, dat_byte As Byte) ' can be used for all 2-byte midi messages TXIdxIn = (TXIdxIn + 1) & TXBufSize ' overflow at 1023 TXBuffer[TXIdxIn] = stat_byte TXIdxIn = (TXIdxIn + 1) & TXBufSize TXBuffer[TXIdxIn] = dat_byte & 127 EndProc Proc HexDis (dat_byte As Byte) ' displays a number on the Radar4 display $ifdef Radar4 PORTB.5 = dat_byte.0 ' a-input PORTB.0 = dat_Byte.1 ' b-input PORTB.1 = dat_Byte.2 ' c-input PORTA.1 = dat_Byte.3 ' d-input PORTA.4 = ~dat_Byte.4 ' right dot - overflow dot. ' this bit needed an inversion (05.11.2017) 'PortB.4 = dat_Byte.5 ' left dot - not implemented on the display IC $endif EndProc MAIN: DelayMS 1500 ' wait time to make sure the parser board is ready before we start here... TimVals[0] = time + 157753 ' peak detector on, should be every 666ms While ' timer23 version: ' overflows after 5 hours. time.Word0 = TMR2 ' time is a dword var time.Word1 = TMR3HLD ' resolution is 4.224 us If velflags.0 = 0 Then TimVals[0] = time + 157753 ' peak detector on, should be every 666ms Set velflags.0 EndIf $ifdef Enable_UART_RX ' if receiver is enabled GoSub GetMidi ' Read data from the serial buffer ' Start the midi parser. ' bytes can come in at a maximum rate of 300us each Midi_Parse: If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in. Else Clear statusbyte 'reset the status byte EndIf GoTo Midi_Parse_done 'throw away... EndIf If StBit =1 Then 'should be faster than If Bytein > 127 Then 'status byte received, bit 7 is set Clear statusbyte 'if on another channel, the statusbyte needs a reset Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit 'reset value. Cannot be 0 !!! Set release '0 is a valid midi note! Case NoteOn_Status statusbyte = Bytein Set noteAan Set velo Case Keypres_Status statusbyte = Bytein Set notePres Set pres Case Control_Status ' controllers and switches statusbyte = Bytein Set Ctrl Set value Case ProgChange_Status ' tuning and piece selection statusbyte = Bytein Set prog ' Case Aftertouch_Status ' used by Radar 1 to send messages to Radar 2 ' statusbyte = Bytein ' not implemented here ' Set aft ' Case Pitchbend_Status ' statusbyte = Bytein ' Set pblsb ' Set pbmsb EndSelect Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel GoTo Midi_Parse_done 'disregard Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... Select noteUit Case 0 To 6 mPlay (NoteOff_Status, noteUit, 0) Case 36 To 126 ' relay to the midi transmit buffer mPlay (NoteOff_Status, noteUit, release) EndSelect Set noteUit 'reset EndIf Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then ' note off via velo=0 Select noteAan Case 0 To 6 mPlay (NoteOn_Status, noteAan, 0) Case 36 To 126 ' transmit Tx mPlay (NoteOn_Status, noteAan, 0) EndSelect Else Select noteAan Case 0 To 6 mPlay (NoteOn_Status, noteAan, velo) Case 24 To 126 ' transmit TX mPlay (NoteOn_Status, noteAan,velo) EndSelect EndIf Set noteAan EndIf Case Keypres_Status If notePres = 255 Then notePres = Bytein Else pres = Bytein Select notePres Case 0 To 6 mPlay (Keypres_Status, notePres, pres) Case 36 To 126 ' transmit TX mPlay (Keypres_Status, notePres, pres) EndSelect Set notePres EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller ' midi TX handled in procedure EndIf Case ProgChange_Status If prog = 255 Then 'single byte message prog = Bytein Select prog Case 0 To 3 ' ' transmit TX mOut (ProgChange_Status, prog) Case 16 To 19 ' for radar3 ' so in the midi implementation pieces are selected with ' prog. change 16, 17, 18, 19, 20 ... prog = prog - 16 ' 0, 1, 2, 3, 4 Clear Init Clear CC79 ' enable radar system ' so this counts from 0 to 128 - 16 ' this can only done in a flexible way by using codepointers... $ifdef Radar3 Select prog Case RadaAeio_piece GoSub Init_RadaAeio Case AeioRising_piece GoSub Init_AeioRising Case Xof_piece GoSub Init_AeioXof Case AeioSinking_piece GoSub Init_AeioSinking Case Aeio_Respons_piece GoSub Init_AeioRespons EndSelect $endif $ifdef Radar4 Select prog Case RadaAeio_piece GoSub Init_RadaAeio Case AeioRising_piece GoSub Init_AeioRising Case Xof_piece GoSub Init_AeioXof Case AeioSinking_piece GoSub Init_AeioSinking Case Aeio_Respons_piece GoSub Init_AeioRespons EndSelect HexDis (prog) $endif EndSelect Set prog EndIf ' Case Aftertouch_Status ' If aft = 255 Then ' aft = Bytein ' Set aft ' EndIf ' Case Pitchbend_Status ' If pblsb = 255 Then ' pblsb = Bytein ' Else ' pbmsb = Bytein ' Set pblsb ' EndIf EndSelect EndIf $endif Midi_Parse_done: ' interactivity code: ' ' here we can select a piece/mapping depending on the value of IApiece (0-63) ' this has to be activated when we get other composers to write ' interactive mappings for . ' It is also possible to embed midi files if we decide on an appropriate format. ' This may require some extra tasks for timing. ' for timing: If TMR3.8 <> Kltg Then ' slow timer Kltg = TMR3.8 Inc Klok ' time units are ca. 71", so a bit more than minutes EndIf ' IApiece = 2 'temporary set to 2 for debugging: start with xof piece - if e do it here we're sure.. ' This can now be done by changing the constants (symbols) If CC79 = 0 Then ' run this only if interactivity is ON Select IApiece Case RadaAeio_piece ' 0 If halt > Klok Then ' so halt must be set on entry GoSub RadaAeio Else Clear Klok Clear Init ' this should cause the init procedure to be called GoSub Init_AeioRising IApiece = AeioRising_piece ' 1 EndIf Case AeioRising_piece If halt > Klok Then GoSub AeioRising Else Clear Klok Clear Init GoSub Init_AeioXof IApiece = Xof_piece EndIf Case Xof_piece If halt > Klok Then GoSub AeioXof Else Clear Klok Clear Init GoSub Init_AeioSinking IApiece = AeioSinking_piece EndIf Case AeioSinking_piece If halt > Klok Then GoSub AeioSinking Else Clear Klok Clear Init GoSub Init_AeioRespons IApiece = Aeio_Respons_piece EndIf Case Aeio_Respons_piece If halt > Klok Then GoSub Aeio_Respons Else Clear Klok Clear Init GoSub Init_RadaAeio IApiece = RadaAeio_piece EndIf EndSelect EndIf If resort_flag = 1 Then GoSub SortTimers EndIf Check_Timers: If idx < NrTasks Then ' we moeten alleen checken wanneer er een timer loopt If time >= Nxt Then ' nagaan of de eerstvolgende timer afgelopen is... ' in dit geval is de eerste timer afgelopen en moeten we de juiste aktie ondernemen: Set Nxt.31 ' timer reset, is immers afgelopen ' aan de hand van idx weten we welke timer dit is Select idx Case 0 ' used for peak detection on the radar Smax = Smaxtmp Clear Smaxtmp Vmax = Vmaxtmp Clear Vmaxtmp TimVals[0] = time + 157753 ' should be every 666ms - this maybe too slow $ifdef Radar3 Toggle orange_led ' for debug , looks like ca. 666ms. $endif Case 1 ' ebow task this is a one-shot for note-off If oldebnoot > 0 Then mPlay (NoteOff_Status, oldebnoot, 0) Clear oldebnoot EndIf Set TimVals[1] Case 2 ' not used as yet Set TimVals[2] Case 3 ' integration task for ADC data, used to keep float operations outside the ' interrupt handlers. ' This task is started from within the ADC interupt handler 'ADfloat = (ADfloat * 0.995) + (rec * 0.005) ' 12 bit 0-4095 - works but integrates too much 'ADfloat = (ADfloat * 0.95) + (rec * 0.05) ' 06.05.2017 'ADfloat = (ADfloat * 0.90) + (rec * 0.10) ' 03.11.2017 ADfloat = (ADfloat * 0.925) + (rec * 0.075) ' 04.11.2017 - this puts fc at 10Hz. Inc DataInIdx ' best sqr mapping so far... ' DataBuffer[DataInIdx] = Sqr(ADfloat * 2) ' 0-90.5 ' DataBuffer[DataInIdx] = DataBuffer[DataInIdx] * (0.5 + (ADfloat/ 56)) ' try log mapping: ' DataBuffer[DataInIdx] = 15.26 * log(ADfloat) ' no good ' DataBuffer[DataInIdx] = ADfloat ^ 0.582 ' makes 0 - 127 ' no good DataBuffer[DataInIdx] = ADfloat / 32 ' 0-127 - linear 'dS = DataBuffer[DataInIdx] - DataBuffer[DataInIdx - CC71] ' CC71: derivative time interval ' physicaly speaking we should calculate dS as: ' dS = (DataBuffer[DataInIdx] - DataBuffer[DataInIdx - CC71]) / CC71 dS = (DataBuffer[DataInIdx] - DataBuffer[DataInIdx - CC71]) / CC71 ' dS is now a float ' duration of one sample in the buffer = 1/812 = 1.2315ms ' as fc = 10Hz, dt should be larger than 100ms / 1.2315ms = 82 ' so we set the default at 164, twice this value ' the range can not exceed -254 to + 254, physically impossible values. PDC3 = DataBuffer[DataInIdx] << 5 ' 0-4095 - white LED If DataBuffer[DataInIdx] > Smaxtmp Then Smaxtmp = DataBuffer[DataInIdx] ' peak detector for surface ' Smaxtmp is reset in tasktimer 0 Set TimVals[3] ' cancel tasktimer Set NewData ' cleared in the main loop. Used for CC74 noise calculation. 'Toggle Yellow_led ' for sampling rate measurement - 09.04.2017: 406Hz or SR = 812 S/s o.k. Case 4 ' integration task for speed ' task started from within the interrupt handler 'T4float = (T4float * 0.95) + (AvSpeed * 0.05) ' Avspeed is 0-500 ' fc = 2Hz , SR = 234Hz T4float = (T4float * 0.75) + (AvSpeed * 0.25) ' low pass filter, fc = 10Hz, SR = 234 ' store speed data in a buffer: ' this buffer has a length of 250ms Inc SpeedInIdx ' move up the buffer index - must be a byte variable! 'Speedbuffer[SpeedInIdx] = T4float ' calculate the first derivative, or acceleration: ' accel = T4float - Speedbuffer[SpeedInIdx - CC70] ' CC70 sets the derivative time interval: 1- 255 ' physicaly speaking we should calculate accel as: ' accel = (T4float - Speedbuffer[SpeedInIdx - CC70]) / CC70 If DataBuffer[DataInIdx] >= CC74 Then Speedbuffer[SpeedInIdx] = T4float accel = (T4float - Speedbuffer[SpeedInIdx - CC70]) / CC70 ' CC70 should be > 24 (dt = 102.48 ms) as fc = 10Hs ' CC70 = 48 is a reasonable default. (dt = 205 ms) ' the range cannot exceed -500 to + 500, physically impossible values aval = accel * CC78 ' sword -128 to +127 when CC78 = 16 Else 'Speedbuffer[SpeedInIdx] = 0 'accel = 0 'aval = 0 ' if we perform the code as above, we risk to get strange values for accel later on, as ' there will be sudden zeros in the buffer. To smooth this out we better do: Speedbuffer[SpeedInIdx] = Speedbuffer[speedInIdx-1] >> 1 accel = (Speedbuffer[SpeedInIdx] - Speedbuffer[SpeedInIdx - CC70]) / CC70 aval = accel * CC78 EndIf 'Toggle yellow_led ' for sampling rate measurement. - gives 117Hz, so sampling rate is now 234 S/s If Speedbuffer[SpeedInIdx] < 128 Then PDC2 = Speedbuffer[SpeedInIdx] << 5 ' blue LED - speed monitor 0 - 4096 Else PDC1 = 4095 ' overflow EndIf ' for debug and range checking: [ to be chacked again now!!! 03.11.2017 !!!] ' If ABS(accel) > 4 then ' > 64 is impossible. > 50 happens but not often > 30 ok > 5 tested o.k. ' set Orange_led ' so we can safely multiply the value by 2 to get a range of -64 to + 63 ' else ' Clear Orange_led ' endif If Speedbuffer[SpeedInIdx] > Vmaxtmp Then Vmaxtmp = Speedbuffer[SpeedInIdx] ' peak detector for speed ' Vmaxtmp is reset in TaskTimer 0 ' note that range is 0 to 500, exceeding a byte! Set TimVals[4] Case 5 ' used for AeioRising - speeltempo in funktie van bewegingssnelheid ' also used in AeioSinking Clear velflags.5 Set TimVals[5] Case 6 ' not yet used. Clear velflags.6 Set TimVals[6] 'Case Else ' ' in dit geval is idx geset ' GoTo jumpout EndSelect GoSub SortTimers ' find a new nxt and idx EndIf ' beveiliging tegen overflow crashes... ' we never saw this happening. If maxtim = 1 Then Clear TMR2 Clear TMR3HLD Clear time Set TimVals $ifdef Radar4 HexDis (14) ' t displayed $endif ' reboot: Clear coldboot Clear IApiece GoTo MAIN EndIf Else ' no timers running, so to avoid overflows, we can safely reset the loop timer ' not sure whether this can ever happen with this code, as we always have timers active. ' verified: it does happen! (06.05.2017) If maxtim = 1 Then Clear TMR2 Clear TMR3HLD ' this resets maxtim ' ' for debug: ' $ifdef Radar4 ' Hexdis (14) ' t displayed ' $endif EndIf EndIf $ifdef Enable_UART_TX Midi_OutPut: ' the internal buffer is only 4 bytes large! ' should we check for U1STA.9 to be 0? If this bit is 1, the buffer is full. If TXIdxOut <> TXIdxIn Then ' in dit geval is er een byte te versturen If IFS0bits_U1TXIF = 0 Then ' interrupt flag is reset ' added 06.05.2017: - this should make sequencing midi out unneeded. If U1STA.8 = 1 Then ' checking U1STA.9 =0 does not work TXIdxOut = (TXIdxOut + 1) & TXBufSize ' circular buffer U1TXREG = TXBuffer[TXIdxOut] DelayUS 320 ' pacing, calculated this should be >= 317 us EndIf EndIf EndIf $endif $ifndef Radar4 Toggle loopcnt ' for loopspeed measurement: ' 02.11.2017: 165kHz down to 95kHz, so cycles range from 5us to 3us $endif $ifdef Radar4 Toggle PORTB.4 ' loopspeed measurement , on not-connected left dot on display. $endif watchdog_led = time.16 ' this is the red LED on each PIC board by us. ' autoregulator for noise level: ' added 01.11.2017 gwr ' we could save machine cycles by only running this only if the DataInIdx had changed, ' hence the introduction of the NewData flag, set whenever DataInIdx is changed. If NewData = 1 Then If DataBuffer[DataInIdx] < minval Then minval = DataBuffer[DataInIdx] EndIf If CC74 < minval + 1 Then CC74 = minval + 1 Clear NewData ' $IFdef Radar4 ' ' for debugging and range checking only: ' If dS > 0 then ' if test < ABS(dS) then ' test = Abs(ds) ' Hexdis (test) ' endif ' endif ' $endif EndIf Wend '-------------------------- end of the main program loop SortTimers: 'look up the next smallest timer value in the Timvals array ' zoek de de volgende kleinste timer waarde: Set idx ' makes it 255 Set Nxt.31 ' nxt is set on entry. - for speed, we just set the highest bit Clear i Repeat If TimVals[i] < Nxt Then Nxt = TimVals[i] idx = i EndIf Inc i Until i = NrTasks ' after the Proton manual, the repeat construction should be faster than the ' construction using a for next loop Clear resort_flag Return ' ************************************************************************************** ' procedures for midi receiver: Controller: ' here we have to transmit all controllers implemented on Select Ctrl Case 7 ' pass through for volume controller: CC7 = value mPlay (Control_Status, 7, value) Case 23 mPlay (Control_Status, 23, value) Case 30 To 41 mPlay (Control_Status, Ctrl, value) Case 50 To 61 mPlay (Control_Status, Ctrl, value) Case 64, 65 mPlay (Control_Status, Ctrl, value) Case 66 mPlay (Control_Status, 66, value) ' this causes all notes off on 'on/off for the robot If value = 0 Then ' power down For i = 0 To LastTask Set TimVals[i] 'this stops the data acquisition... Clear velflags Next i Set resort_flag Clear Init ' so on restart, the controllers will be sent again. CC70 = CC70_default CC71 = CC71_default CC73 = CC73_default ' sensit. for AeioRising/AeioSinking radar3 CC74 = CC74_default ' 1 ' noise floor for surface data RA_stringscaler = 1 ' pitch mapping divider for ebow notes RA_beaterscaler = 1 ' pitch mapping sensitivity (divider) for beater notes CC78 = CC78_default ' 16 ' accelleration mapping multiplier CC79 = 127 'CC79_default ' radar disabled interval_divider = 1 ' autoregulating 8 '16 ' init for aeio-rising EndIf Case 70 ' controller 70-80 are reserved for parameter control ' in interactive modes of operation. ' time interval dt for accelleration calculation in accel CC70 = value + value + 1 '1 to 255 with a sampling rate of 234 S/s 'this range for dt becomes 4.27ms to 1088ms ' values < 24 are absurd, as fc = 10Hz Case 71 ' time interval dt for dS1, differential of surface CC71 = value + value + 1 ' 1 to 255 ' with a sampling rate of 812 S/s the range becomes ' dt 1.2315ms to 314ms ' values < 82 are absurd, as fc = 10Hz Case 73 ' sensitivity for Qm (Quantity of movement used in Aeiorising) CC73 = value Case 74 ' set noise level for surface data ' init value to be determined from experiments.[ 5 on init] ' the minimum setting is autoregulating upwards if the value set here is lower than ' the actual noise level. CC74 = value ' 0-127 ' Case 75 ' Case 76 Case 77 ' 03.11.2017: multiplier for dS values for scaling ' the range for dS being =56 to + 96, one has to be carefull using this. ' by default CC77 = 1 CC77 = value + 1 Case 78 ' 10/04/2017: multiplier for accelleration values in RadaAeio ' 15/04/2017: autoregulation implemented. ' 03.11.2017: aval = accel * CC78 ' accel has a range of -8 to +8 maximum ' so a default setting should be 16 ' to get a range -128 to + 127 CC78 = value + 1 Case 79 ' 0 = enable radar system ' > 0 = disable radar interactivity CC79 = value If CC79 > 0 Then mPlay (Control_Status, 123, 0) ' all notes off EndIf Case 80 To 91 mPlay (Control_Status, Ctrl, value) Case 100 To 111 mPlay (Control_Status, Ctrl, value) Case 112 ' FM modulation for radar3 and radar4 If value < 127 Then PDC1 = value << 5 ' make 12-bits Else PDC1 = 4095 EndIf Case 114 Durations[RadaAeio_piece] = value ' RadaAeio_duration ' set to the symbolic constants on cold boot. ' 1 unit is 71" ' if value = 0, the piece will be skipped. ' value = 2 equals 1'22" ' value = 3 equals 3'33" ' value = 127 equals 2h30' Case 115 Durations[AeioRising_piece] = value ' AeioRising_duration Case 116 Durations[Xof_piece] = value ' Xof_duration Case 117 Durations[AeioSinking_piece] = value ' AeioSinking_duration Case 118 Durations[Aeio_Respons_piece] = value ' AeioRespons_duration Case 123 ' just pass it through mPlay (Control_Status, 123, 0) EndSelect Set Ctrl 'mandatory reset Return '---- EMBEDDED COMPOSITION CODE STARTS HERE--------------------------------------------------- Embedded_Pieces: Init_RadaAeio: ' this procedure sends all controllers required to start the RadaAeio piece. ' this is embedded piece nr.1 (IApiece = RadaAeio_piece) ' coding for mPlay (Control_Status, 66, 64) ' power ON command - this ought to switch all notes off mPlay (Control_Status, 64, 0) ' sustain off, so the dampers will work If CC7 <> CC7_default Then mPlay (Control_Status, 7, CC7_default) CC7 = CC7_default EndIf Set Init RA_stringscaler = 1 ' pitch mapping divider for ebow notes RA_beaterscaler = 1 ' pitch mapping sensitivity (divider) for beater notes IApiece = RadaAeio_piece ' for time scheduling of embedded compositions start = Klok 'duration = 5 ' would be 5 x 71" = 355" = ca. 6' ' should become an array durations[Last_Piece + 1] halt = start + Durations[RadaAeio_piece] ' if the duration is set to 0 ' the piece will be skipped. ' in the loop, we should now compare klok with halt and ' as soon as klok > halt, change the piece. Clear coldboot ' added 05.05.2017 $ifdef Radar4 HexDis (RadaAeio_piece) $endif Return Init_AeioRising: ' for : ' embedded piece nr.2 (IApiece = 1) mPlay (Control_Status, 123, 0) ' all notes off mPlay (Control_Status, 64, 64) ' we should have sustain on here. mPlay (Control_Status, 7, 127) CC7 = 127 Set Init IApiece = AeioRising_piece interval_divider = 1 ' reset this on every run. start = Klok 'duration = 5 ' would be 5 x 71" = 355" = ca. 6' halt = start + Durations[AeioRising_piece] ' in the loop, we should now compare klok with halt and ' as soon as klok > halt, change the piece. ' If CC73 < CC74 << 2 Then ' CC73 = CC74 << 2 ' to be checked. ' EndIf $ifdef Radar4 HexDis (AeioRising_piece) $endif Return Init_AeioSinking: ' for : embedded piece nr.4 (IApiece = 3) mPlay (Control_Status, 123, 0) ' all notes off mPlay (Control_Status, 64, 64) ' we should have sustain on here. mPlay (Control_Status, 7, 127) CC7 = 127 Set Init IApiece = AeioSinking_piece interval_divider = 1 ' reset this on every run. start = Klok halt = start + Durations[AeioSinking_piece] nidx = Last5note ' in the loop, we should now compare klok with halt and ' as soon as klok > halt, change the piece. ' If CC73 < CC74 << 2 Then ' CC73 = CC74 << 2 ' to be checked. ' EndIf $ifdef Radar4 HexDis (AeioSinking_piece) $endif Return RadaAeio: ' first interactive piece for Rodo : IApiece = 0 If Init = 0 Then GoSub Init_RadaAeio ' should be done on cold boot EndIf If time.19 <> tg Then ' slow for aeio - task.freq = 0.45Hz, or 2.2" period tg = time.19 ' using the mapping table: ' 15.04.2017: changed to implemenent autoregulation: ' on cold boot, and reset, we now set RA_beaterscaler = 1 ' 20.04.2017: The theoretical range for the values in Speedbuffer[] are 0 to 500. ' This range corresponds to movement speeds of 1cm/s to 5m/s nidx = Speedbuffer[SpeedInIdx] / RA_beaterscaler If nidx > LastNote Then Inc RA_beaterscaler ' 1, 2, 3 .... nidx = LastNote EndIf noot = Nt[nidx] ' apply lookup table - hammers veel = DataBuffer[DataInIdx] ' 0-127 , mapped on amplitude If veel > CC74 Then ' CC74 = noise floor If noot <> oldnoot Then ' avoiding too many repeats of the same note... mPlay (NoteOn_Status, noot, veel) oldnoot = noot EndIf If accel < 0 Then ' speedup/slowdown property If Red = 1 Then mPlay (NoteOff_Status, RedLite, 0) ' at slowdown, the red light will dim Clear Red EndIf EndIf Else ' else for veel > cc74 condition ' note off condition if we are below the noise level If oldnoot > 0 Then 'sending note-off is not required for Aeio-hammers ' but without it, the dampers will not work mPlay (NoteOff_Status, oldnoot, 0) Clear oldnoot EndIf If Red = 0 Then mPlay (NoteOn_Status, RedLite, 127) ' red light on if no movement Set Red EndIf EndIf If Period_Invalid_Flag = 1 Then ' this is a shaky condition ' 29.10.2017: not happening on Aeio now ' this flag is set when the period counter on INT0 glitches ' this means either the movement is too fast or below detection threshold. If YellowL = 0 Then mPlay (NoteOn_Status, YellowLiteL, 127) Set YellowL EndIf If YellowR = 0 Then mPlay (NoteOn_Status, YellowLiteR, 127) Set YellowR EndIf Else If YellowL = 1 Then mPlay (NoteOff_Status, YellowLiteL, 0) Clear YellowL EndIf If YellowR =1 Then mPlay (NoteOff_Status, YellowLiteR, 0) Clear YellowR EndIf EndIf EndIf ' do some lightshow... ' to be really responsive, this should happen at least 10 times a second. If time.18 <> lbtg Then lbtg = time.18 ' this is task.freq = 0.9 Hz ' lets try a mapping on dS: ' so on increasing movement quantity, the blue light will go on ' the dt for dS can be set with CC71 If dS > 1 Then ' ds is -56 to + 96, measured 04.11.2017 ' this is the explode property If Blue = 0 Then mPlay (NoteOn_Status, BlueLite, 127) Set Blue EndIf Else If Blue = 1 Then mPlay (NoteOff_Status, BlueLite, 0) Clear Blue EndIf EndIf ' $IFdef Radar4 ' 'test = ABS(Accel) ' 8 is the highest value we obtain on radar4 ' ' checked again 06.11.2017 ' 'test = ABS(aval) ' aval = accel * CC78 ' 'test = ABS(dS) >> 3 ' :8 ' geeft 12 als maximum, dus dS <= 96 ' if dS > 0 then ' IF test > Abs(dS) then ' test = Abs(dS) ' Hexdis (Test) ' endif ' 'test = abs(dS) >> 1 ' >>2 = :4 geeft 14, dus negative range for dS is >= -56 ' ' >>1 = :2 geeft 12, dus negative range dor dS is >= - 24 (06.11.2017) ' ' with dS>0 condition: positive range up to 30 (06.11.2017) ' endif ' 'Hexdis (test) ' $endif EndIf ' we also do the strings, 2 times slower: If time.20 <> ebtg Then ebtg = time.20 ' this is task.freq = 0.45 Hz, or every 2.2" * 2 now.= 4.4", 0.22 Hz ' using the mapping table for ebow notes: ' autoregulation added using RA_stringscaler nidx = Speedbuffer[SpeedInIdx] / RA_stringscaler If nidx > LastEnote Then Inc RA_stringscaler ' autoregulator nidx = LastEnote ' to play safe... EndIf ebnoot = eNt[nidx] veel = DataBuffer[DataInIdx] ' 0-127 If veel > CC74 Then ' CC74 = noise floor ' play noot If ebnoot <> oldebnoot Then ' zoniet laten we de noot gewoon hangen If oldebnoot > 0 Then mPlay (NoteOff_Status, oldebnoot, 0) EndIf veel = veel >> 1 ' 0-63 veel = veel + 64 If veel > 127 Then veel = 127 ' safety, though it cannot happen. mPlay (NoteOn_Status, ebnoot, veel) oldebnoot = ebnoot Else ' use keypressure to modulate the level veel = veel >> 1 veel = 64 + veel mPlay (Keypres_Status, ebnoot, veel) EndIf $ifndef Radar4 Set yellow_led ' indicate ebnoot playing $endif Else ' else for veel > CC74 ' noteoff If oldebnoot > 0 Then mPlay (NoteOff_Status, oldebnoot, 0) Clear oldebnoot $ifndef Radar4 Clear yellow_led $endif EndIf EndIf EndIf ' endif for ebow time-toggle ebtg Return ' return for the RadaAeio piece '------------------------------------------------------------------------------- AeioRising: ' original coding for a second interactive piece for Rodo ' extensively adapted to work on october-november 2017 ' we get here only if IApiece = AeioRising_Piece If Init = 0 Then GoSub Init_AeioRising EndIf If velflags.5 = 0 Then ' if the task is free to run... ' Qm = impulse, quantity of movement ' Qm range can be max. 96 X 8 = 768 If dS > 0 And accel > 0 Then ' -56 CC73 and Databuf[DataInIdx] > CC74 then not compiling... ' 07.11.2017: explanation: typo Databuf must be DataBuffer... Clear condition If Qm > CC73 Then ' CC73 bepaalt hoeveel noten gaan overlappen ' bij kleine waarden krijgen we veel overlappingen, bij grote veel minder ' bij CC73 = 12 krijgen we weinig overlapping en grote sprongen condition = 1 Else condition = 0 EndIf If DataBuffer[DataInIdx] > CC74 Then Inc condition If condition = 2 Then ' autoregulation code: interval = Qm / interval_divider ' we should start with interval_divider = 1 If interval > 12 Then Inc interval_divider interval = 12 ' make interval jump maximum an octave EndIf If interval < 1 Then interval = 1 ' we could drop this to avoid scales... nidx = nidx + interval If nidx > LastEnote Then Clear nidx ' reset at end of range ebnoot = eNt[nidx] ' apply lookup table veel = 64 + (Smax / 2) ' 03.11.2017 - better now. ' if ebnoot <> oldEbnoot then ' cannot happen if interval = 1 mPlay (NoteOn_Status, ebnoot, veel) ' else ' mPlay (KeyPres_Status, ebnoot, veel) ' endif oldebnoot = ebnoot Set velflags.5 ' so tempo will depend on movement speed i = Vmax ' are we sure this never exceeds 127? ' it does exceed a byte! (range 0-500!) If i > 127 Then i = 127 ' safety limit. duur = Dur2[i] << 4 ' dword TimVals[5] = time + duur Set resort_flag Else If oldebnoot > 0 Then ' it could be more that one string is sounding at this point ' as this is the case we do an all notes off... mPlay (Control_Status, 123, 0) Clear oldebnoot Else If YellowL = 0 Then mPlay (NoteOn_Status, YellowLiteL, Smax) Set YellowL EndIf EndIf EndIf 'endif Else ' task busy If YellowL = 1 Then mPlay (NoteOff_Status, YellowLiteL, 0) Clear YellowL EndIf EndIf ' endif for task free to run Return '------------------------------------------------------------------------------- AeioSinking: ' we get here only if IApiece = AeioSinking_Piece If Init = 0 Then GoSub Init_AeioSinking EndIf If velflags.5 = 0 Then ' if the task is free to run... ' Qm = impulse, quantity of movement ' Qm range can be max. 96 X 8 = 768 If dS > 0 And accel > 0 Then ' -56 CC73 and DataBuffer[DataInIdx] > CC74 Then ' not compiling... ??? Clear condition If Qm > CC73 Then condition = 1 Else Clear condition EndIf If DataBuffer[DataInIdx] > CC74 Then Inc condition If condition = 2 Then ' autoregulation code: interval = Qm / interval_divider ' we should start with interval_divider = 1 If interval > 12 Then Inc interval_divider interval = 12 ' make interval jump maximum an octave EndIf If interval < 1 Then interval = 1 ' we could drop this to avoid scales... If interval <= nidx Then nidx = nidx - interval ' descending intervals Else nidx = Last5note ' reset at top of range - 5 octaves here! EndIf ebnoot = eNt[nidx] ' apply lookup table veel = 64 + (Smax / 2) ' 03.11.2017 - better now. ' if ebnoot <> oldEbnoot then mPlay (NoteOn_Status, ebnoot, veel) ' else ' mPlay (KeyPres_Status, ebnoot, veel) ' endif oldebnoot = ebnoot Set velflags.5 ' so tempo will depend on movement speed i = Vmax ' are we sure this never exceeds 127? ' it does exceed a byte! (range 0-500!) If i > 127 Then i = 127 ' safety limit. duur = Dur2[i] << 4 ' dword TimVals[5] = time + duur Set resort_flag Else If oldebnoot > 0 Then ' it could be more that one string is sounding at this point ' as this is the case we do an all notes off... mPlay (Control_Status, 123, 0) Clear oldebnoot Else If YellowR = 0 Then mPlay (NoteOn_Status, YellowLiteR, Smax) Set YellowR EndIf EndIf EndIf Else If YellowR = 1 Then mPlay (NoteOff_Status, YellowLiteR, 0) Clear YellowR EndIf EndIf Return Aeio_Respons: ' 06.11.2017 - 08.11.2017 gwr ' x-lates the speedup property ' this mapping uses ebow, hammers and dampers If Init = 0 Then GoSub Init_AeioRespons tg = time.16 EndIf If time.16 <> tg Then tg = time.16 ' ca. 0.25 or 4Hz ' place action here, using AR_Speed AR_Speed = AR_Speed / AR_Count ' are we sure AR_Count is allways > 0? ' AR_speed is calculated as long as tg = time.16 Clear AR_Count If DataBuffer[DataInIdx] > CC74 Then ' must be above noise If accel > 0 Then ' accel is float - range -8 to +8 If AR_Speed <> nidx Then nidx = AR_Speed ' average speed - can go up to 500 If nidx > last6note Then nidx = Last5note + (nidx // 12 ) ' wide range ebnoot = eNt[nidx >> 1] ' apply lookup table If oldebnoot <> ebnoot Then If oldebnoot > 0 Then mPlay (NoteOff_Status, oldebnoot, 1) ' sustain off here - we use the dampers EndIf oldebnoot = ebnoot veel = 64 + (Smax / 2) mPlay (NoteOn_Status, ebnoot, veel) ' do also hammers: noot = 24 + (ebnoot // 12) ' Nt[nidx // 12] mPlay (NoteOn_Status, noot, DataBuffer[DataInIdx]) EndIf Else ' noot aanhouden If Red = 1 Then mPlay (NoteOff_Status, RedLite, 0) ' red light off Clear Red EndIf EndIf Else If accel <= -1 Then If oldebnoot > 0 Then mPlay (NoteOff_Status, oldebnoot, 1) Clear oldebnoot EndIf If Red = 0 Then mPlay (NoteOn_Status, RedLite, DataBuffer[DataInIdx]) ' red light on if no movement Set Red EndIf EndIf EndIf Else If oldebnoot > 0 Then mPlay (Control_Status, 123, 0) Clear oldebnoot EndIf EndIf Clear AR_Speed ' reset! If Blue = 1 Then mPlay (NoteOff_Status, BlueLite, 0) Clear Blue EndIf Else ' average speed between calls - so the averaging time is ca. 250ms If AR_Idx <> SpeedInIdx Then AR_Speed = AR_Speed + Speedbuffer[SpeedInIdx] ' should never overflow a word var AR_Idx = SpeedInIdx Inc AR_Count ' reset on time toggle EndIf ' blue light on: If Blue = 0 Then mPlay (NoteOn_Status, BlueLite, 64) ' flashing Set Blue EndIf EndIf Return Init_AeioRespons: mPlay (Control_Status, 123, 0) ' all notes off mPlay (Control_Status, 64, 0) ' we should have sustain off here. If CC7 <> 127 Then mPlay (Control_Status, 7, 127) CC7 = 127 EndIf Set Init Clear nidx IApiece = Aeio_Respons_piece start = Klok halt = start + Durations[Aeio_Respons_piece] AR_Count = 1 ' avoid divide by 0 bug Clear AR_Idx Clear AR_Speed $ifdef Radar4 HexDis (Aeio_Respons_piece) $endif Return ' ------------------------------------------------------------------------------------- ' xofs first attempt to make a piece Init_AeioXof: mPlay (Control_Status, 123, 0) ' all notes off mPlay (Control_Status, 64, 127) ' we should have sustain on here. If CC7 <> 127 Then mPlay (Control_Status, 7, 127) CC7 = 127 EndIf Set Init IApiece = Xof_piece start = Klok RA_stringscaler = 1 ' pitch mapping divider for ebow notes RA_beaterscaler = 1 ' pitch mapping sensitivity (divider) for beater notes 'duration = 5 would be 5 x 71" = 355" = ca. 6' halt = start + Durations[Xof_piece] $ifdef Radar4 HexDis (Xof_piece) $endif Return AeioXof: 'simple test for now.. RadaAeio als voorbeeld gebruikt, dus zonder timer.. If Init = 0 Then GoSub Init_AeioXof ' should be done on cold boot EndIf 'If time.17 <> tg Then ' = TMR3.0 ' tg = time.17 ' this is task.freq = 1.8Hz or 0.55" period. If time.15 <> tg Then ' faster speed tg = time.15 ' using the mapping table: ' 20.04.2017: The theoretical range for the values in Speedbuffer[] are 1 to 500. ' This range corresponds to movement speeds of 1cm/s to 5m/s nidx = Speedbuffer[SpeedInIdx] / RA_stringscaler If nidx > LastEnote Then Inc RA_stringscaler ' 1, 2, 3 .... nidx = LastEnote EndIf ebnoot = eNt[nidx] ' apply lookup table - ebow veel = DataBuffer[DataInIdx] ' 0-127 , mapped on amplitude If veel > CC74 Then ' CC74 = noise floor If ebnoot <> oldebnoot Then ' avoiding too many repeats of the same note... 'wrong place to put cc64, but for debug as aeio doesn't listen to the one in the init proc 'and indeed here it works, so our init is either not called or overruled later on.. 'mPlay (Control_Status, 64, 127) mPlay (NoteOff_Status, oldebnoot, 0) veel = veel >> 1 ' 0-63 veel = veel + 64 mPlay (NoteOn_Status, ebnoot, veel) oldebnoot = ebnoot If aval > 100 Then 'hamer enkel bij hoge acceleratie (gwr) mPlay(NoteOn_Status, Nt[nidx // 12], aval & 127) ' // = MOD EndIf EndIf Else ' else for veel > cc74 condition ' note off condition if we are below the noise level If oldebnoot > 0 Then 'sending note-off is not required for Aeio-hammers ' but without it, the dampers will not work mPlay (NoteOff_Status, oldebnoot, 0) Clear oldebnoot EndIf If Red = 0 Then mPlay (NoteOn_Status, RedLite, 127) Set Red EndIf EndIf EndIf ' do some lightshow... borrowed from RadarAeio If time.16 <> lbtg Then lbtg = time.16 ' lets try a mapping on dS: ' so on increasing movement quantity, the blue light will go on ' the sensitivity for dS can be set with CC71 If dS > 2 Then ' ds is -127 to + 127 If Blue = 0 Then mPlay (NoteOn_Status, BlueLite, 127) Set Blue EndIf Else If Blue = 1 Then mPlay (NoteOff_Status, BlueLite, 0) Clear Blue EndIf EndIf EndIf Return '--- END OF EMBEDDED COMPOSITIONS CODE ------------------------------------------ '-------------------------------------------------------------------------------- Dur_Lookup1: ' in chromatic steps. Changed 17.04.2017 Set Dur[0] ' = 65536 = 0.276 " Dur[1] = 61857 Dur[2] = 58385 Dur[3] = 55108 Dur[4] = 52015 Dur[5] = 49095 Dur[6] = 46339 Dur[7] = 43738 Dur[8] = 41283 Dur[9] = 38966 Dur[10] = 36779 Dur[11] = 34714 For i = 12 To 23 Dur[i] = Dur[i-12] >> 1 ' 32767 ... Next i For i = 24 To 35 Dur[i] = Dur[i-24] >> 2 ' 16383 ... Next i For i = 36 To 47 Dur[i] = Dur[i-36] >> 3 ' 8192 ... Next i For i = 48 To 59 Dur[i] = Dur[i-48] >> 4 ' 4095 ... this should be the limit. Next i For i = 60 To 71 Dur[i] = Dur[i-60] >> 5 ' 2047 ... Next i For i = 72 To 83 Dur[i] = Dur[i-72] >> 6 ' 1023 ... Next i ' higher values are absurd here. ' we keep the old values just as placeholders. Dur[84]= 6048 ' freq= 8.26719576719577 Dur[85]= 5951 ' freq= 8.40194925222652 Dur[86]= 5855 ' freq= 8.5397096498719 Dur[87]= 5760 ' freq= 8.68055555555555 Dur[88]= 5668 ' freq= 8.82145377558222 Dur[89]= 5576 ' freq= 8.96700143472023 Dur[90]= 5486 ' freq= 9.11410864017499 Dur[91]= 5398 ' freq= 9.26268988514264 Dur[92]= 5311 ' freq= 9.41442289587648 Dur[93]= 5225 ' freq= 9.56937799043062 Dur[94]= 5141 ' freq= 9.72573429293912 Dur[95]= 5058 ' freq= 9.88533017002768 Dur[96]= 4977 ' freq= 10.0462125778581 Dur[97]= 4897 ' freq= 10.2103328568511 Dur[98]= 4818 ' freq= 10.3777501037775 Dur[99]= 4740 ' freq= 10.548523206751 Dur[100]= 4664 ' freq= 10.7204116638079 Dur[101]= 4589 ' freq= 10.8956199607758 Dur[102]= 4515 ' freq= 11.0741971207087 Dur[103]= 4442 ' freq= 11.2561909049977 Dur[104]= 4370 ' freq= 11.441647597254 Dur[105]= 4300 ' freq= 11.6279069767442 Dur[106]= 4231 ' freq= 11.8175372252422 Dur[107]= 4162 ' freq= 12.013455069678 Dur[108]= 4095 ' freq= 12.2100122100122 Dur[109]= 4029 ' freq= 12.4100273020601 Dur[110]= 3964 ' freq= 12.6135216952573 Dur[111]= 3901 ' freq= 12.8172263522174 Dur[112]= 3838 ' freq= 13.0276185513288 Dur[113]= 3776 ' freq= 13.2415254237288 Dur[114]= 3715 ' freq= 13.4589502018842 Dur[115]= 3655 ' freq= 13.6798905608755 Dur[116]= 3596 ' freq= 13.9043381535039 Dur[117]= 3538 ' freq= 14.1322781232335 Dur[118]= 3481 ' freq= 14.3636885952312 Dur[119]= 3425 ' freq= 14.5985401459854 Dur[120]= 3370 ' freq= 14.8367952522255 Dur[121]= 3316 ' freq= 15.0784077201448 Dur[122]= 3262 ' freq= 15.3280196198651 Dur[123]= 3210 ' freq= 15.5763239875389 Dur[124]= 3158 ' freq= 15.8328055731476 Dur[125]= 3107 ' freq= 16.0926939169617 Dur[126]= 3057 ' freq= 16.3559044815178 = 38.3365Hz 07.08.2016 Dur[127]= 3008 ' 04.08.2016: 8.35ms - 59.5Hz Return Dur_Lookup2: 'using timer23, 1 dur unit is 4.224 us 'used for note durations in 'Set Dur2[0] Dur2[0] = 26000 Dur2[1]= 23674 ' 07.08.2016: 2x100ms = 200ms full period --> 5Hz [o.k.14.08.2016] Dur2[2]= 22917 ' freq= 2.18178644674259 Dur2[3]= 22548 ' freq= 2.21749157353202 Dur2[4]= 22185 ' freq= 2.25377507324769 Dur2[5]= 21827 ' freq= 2.29074082558299 Dur2[6]= 21475 ' freq= 2.32828870779977 Dur2[7]= 21129 ' freq= 2.36641582658905 Dur2[8]= 20789 ' freq= 2.40511809129828 Dur2[9]= 20454 ' freq= 2.44450963136795 Dur2[10]= 20124 ' freq= 2.48459550785132 Dur2[11]= 19800 ' freq= 2.52525252525252 Dur2[12]= 19481 ' freq= 2.56660335711719 Dur2[13]= 19167 ' freq= 2.60865028434288 Dur2[14]= 18858 ' freq= 2.65139463357726 Dur2[15]= 18554 ' freq= 2.69483669289641 Dur2[16]= 18255 ' freq= 2.73897562311695 Dur2[17]= 17961 ' freq= 2.7838093647347 Dur2[18]= 17672 ' freq= 2.82933454051607 Dur2[19]= 17387 ' freq= 2.87571173865532 Dur2[20]= 17107 ' freq= 2.92278014847723 Dur2[21]= 16831 ' freq= 2.97070881112233 Dur2[22]= 16560 ' freq= 3.01932367149758 Dur2[23]= 16293 ' freq= 3.06880255324372 Dur2[24]= 16030 ' freq= 3.11915159076731 Dur2[25]= 15772 ' freq= 3.17017499365965 Dur2[26]= 15518 ' freq= 3.22206469905916 Dur2[27]= 15268 ' freq= 3.27482315954938 Dur2[28]= 15022 ' freq= 3.32845160431367 Dur2[29]= 14780 ' freq= 3.382949932341 Dur2[30]= 14542 ' freq= 3.43831660019254 Dur2[31]= 14307 ' freq= 3.4947927587894 Dur2[32]= 14077 ' freq= 3.55189315905378 Dur2[33]= 13850 ' freq= 3.6101083032491 Dur2[34]= 13627 ' freq= 3.66918617450649 Dur2[35]= 13407 ' freq= 3.72939509211606 Dur2[36]= 13191 ' freq= 3.79046319460238 Dur2[37]= 12978 ' freq= 3.85267375558638 Dur2[38]= 12769 ' freq= 3.91573341686898 Dur2[39]= 12564 ' freq= 3.97962432346386 Dur2[40]= 12361 ' freq= 4.04498017959712 Dur2[41]= 12162 ' freq= 4.1111659266568 Dur2[42]= 11966 ' freq= 4.17850576633796 Dur2[43]= 11773 ' freq= 4.24700586086809 Dur2[44]= 11583 ' 07.08.2016: geeft 10.1177 Hz Dur2[45]= 11397 ' freq= 4.38711941739054 Dur2[46]= 11213 ' freq= 4.45910996165165 Dur2[47]= 11032 ' freq= 4.53226976069616 Dur2[48]= 10855 ' freq= 4.60617227084293 Dur2[49]= 10680 ' freq= 4.6816479400749 Dur2[50]= 10508 ' freq= 4.75827940616673 Dur2[51]= 10338 ' freq= 4.83652544012381 Dur2[52]= 10172 ' freq= 4.91545418796697 Dur2[53]= 10008 ' freq= 4.99600319744204 Dur2[54]= 9846 ' freq= 5.07820434694292 Dur2[55]= 9688 ' freq= 5.16102394715111 Dur2[56]= 9532 ' freq= 5.24548887956357 Dur2[57]= 9378 ' freq= 5.33162721262529 Dur2[58]= 9227 ' freq= 5.4188793757451 Dur2[59]= 9078 ' freq= 5.50782110597048 Dur2[60]= 8932 ' freq= 5.59785042543663 Dur2[61]= 8788 ' freq= 5.68957669549385 Dur2[62]= 8646 ' freq= 5.78302105019662 Dur2[63]= 8507 ' 04.08.2016: 21Hz pulse duur = 23.8ms Dur2[64]= 8370 ' geeft nu 20ms pulsen freq= 25Hz 03.08.2016 ' 14.0017Hz 07.08.2016 Dur2[65]= 8235 ' freq= 6.07164541590771 Dur2[66]= 8102 ' freq= 6.17131572451246 Dur2[67]= 7972 ' freq= 6.27195183140993 Dur2[68]= 7843 ' freq= 6.37511156445238 Dur2[69]= 7717 ' freq= 6.47920176234288 Dur2[70]= 7593 ' freq= 6.58501251152377 Dur2[71]= 7470 ' freq= 6.69344042838019 Dur2[72]= 7350 ' freq= 6.80272108843537 Dur2[73]= 7231 ' freq= 6.91467293597013 Dur2[74]= 7115 ' freq= 7.02740688685875 Dur2[75]= 7000 ' freq= 7.14285714285714 Dur2[76]= 6888 ' freq= 7.25900116144018 Dur2[77]= 6777 ' freq= 7.37789582411096 Dur2[78]= 6667 ' freq= 7.49962501874906 Dur2[79]= 6560 ' freq= 7.62195121951219 Dur2[80]= 6454 ' freq= 7.74713356058258 Dur2[81]= 6350 ' freq= 7.8740157480315 Dur2[82]= 6248 ' freq= 8.00256081946223 Dur2[83]= 6147 ' freq= 8.13404912965674 Dur2[84]= 6048 ' freq= 8.26719576719577 Dur2[85]= 5951 ' freq= 8.40194925222652 Dur2[86]= 5855 ' freq= 8.5397096498719 Dur2[87]= 5760 ' freq= 8.68055555555555 Dur2[88]= 5668 ' freq= 8.82145377558222 Dur2[89]= 5576 ' freq= 8.96700143472023 Dur2[90]= 5486 ' freq= 9.11410864017499 Dur2[91]= 5398 ' freq= 9.26268988514264 Dur2[92]= 5311 ' freq= 9.41442289587648 Dur2[93]= 5225 ' freq= 9.56937799043062 Dur2[94]= 5141 ' freq= 9.72573429293912 Dur2[95]= 5058 ' freq= 9.88533017002768 Dur2[96]= 4977 ' freq= 10.0462125778581 Dur2[97]= 4897 ' freq= 10.2103328568511 Dur2[98]= 4818 ' freq= 10.3777501037775 Dur2[99]= 4740 ' freq= 10.548523206751 Dur2[100]= 4664 ' freq= 10.7204116638079 Dur2[101]= 4589 ' freq= 10.8956199607758 Dur2[102]= 4515 ' freq= 11.0741971207087 Dur2[103]= 4442 ' freq= 11.2561909049977 Dur2[104]= 4370 ' freq= 11.441647597254 Dur2[105]= 4300 ' freq= 11.6279069767442 Dur2[106]= 4231 ' freq= 11.8175372252422 Dur2[107]= 4162 ' freq= 12.013455069678 Dur2[108]= 4095 ' freq= 12.2100122100122 Dur2[109]= 4029 ' freq= 12.4100273020601 Dur2[110]= 3964 ' freq= 12.6135216952573 Dur2[111]= 3901 ' freq= 12.8172263522174 Dur2[112]= 3838 ' freq= 13.0276185513288 Dur2[113]= 3776 ' freq= 13.2415254237288 Dur2[114]= 3715 ' freq= 13.4589502018842 Dur2[115]= 3655 ' freq= 13.6798905608755 Dur2[116]= 3596 ' freq= 13.9043381535039 Dur2[117]= 3538 ' freq= 14.1322781232335 Dur2[118]= 3481 ' freq= 14.3636885952312 Dur2[119]= 3425 ' freq= 14.5985401459854 Dur2[120]= 3370 ' freq= 14.8367952522255 Dur2[121]= 3316 ' freq= 15.0784077201448 Dur2[122]= 3262 ' freq= 15.3280196198651 Dur2[123]= 3210 ' freq= 15.5763239875389 Dur2[124]= 3158 ' freq= 15.8328055731476 Dur2[125]= 3107 ' freq= 16.0926939169617 Dur2[126]= 3057 ' freq= 16.3559044815178 = 38.3365Hz 07.08.2016 Dur2[127]= 3008 ' 04.08.2016: 8.35ms - 59.5Hz Return Note_Lookup: 'note mapping for Nt[0] = 24 ' hammers on Aeio Nt[1] = 25 Nt[2] = 26 Nt[3] = 27 Nt[4] = 28 Nt[5] = 29 Nt[6] = 30 Nt[7] = 31 Nt[8] = 32 Nt[9] = 33 Nt[10] = 34 Nt[11] = 35 ' NrNotes = 12 = declared symbol ' lookuptable for the ebow-string notes ' NrEnotes = 48 = declared symbol for range 36 - 83 ' Nr5notes = 60 ' Nr6notes = 72 For i = 36 To 126 '83 ' could go up to 127... eNt[i-36] = i Next i Return '[EOF]