'**************************************************************************** '* * '* This is a framework that implements the main features of the chip * '* as well as the software framework we typically used on 8 bit chips * '* used for our musical robots: a realtime multitasker * '* HYBRLO_22_24 * '* HYBRLO_25_27 * '* HYBRLO_28_30 * '* HYBRLO_31_33 * '* Version 2.0 - 2020 * ' *************************************************************************** ' 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. '01.08.2016: Test and debug board designed, etched and soldered. ' Programming requires the PiCkit3 programmer. PicKit2 does not work! '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. '09.08.2016: Further coding. adsr not yet operational. - version saved as 007 '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. ' PCB made for this app. '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 ' There is a lot of jitter on the main loop, so we must be operating close to ' the maximum performance for this chip. ' 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. ' Coding started. ' 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. ' PCB dsign started for an evaluation board for this synth. '20.08.2016: This design could be used for '23.08.2016: Evaluation board finished. This works o.k. ' bug removed in the duty cycle control: cannot be zero! ' Start work on the coding for ' 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. '29.08.2016: Two boards made with active filters. ' Hub board made as well: this should also filter midi for the note-boards. ' HybrLo channel decided to become 8 '31.08.2016: Recoding for the new controller implementation. ' The PCB's for all notes are ready now. '01.09.2016: GMT testcode adapted such that we can test this code... ' This firmware copied and renamed as HybrLo_25_27.bas for the second board. '07.09.2016: Mute logic inverted in the code for all boards. '11.09.2016: First tests on the assembled robot. ' Mute logic appears to be wrong... '12.09.2016: Seems working fine now, but we do have intermittent failures. '13.09.2016: Controller 15 added for global waveshape control. '20.09.2016: Looks like release is no longer working now... ' We could try to make 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 ' Program Change command implemented now. Needs further investigations. ' 09.10.2016: All pipes mounted on the instrument... ' Further research into the origins of the glitches. ' PWM freq lowered to 29kHz ' try to give UART lower priority, to avoid glitches ' 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... ' Programming under high fever conditions... ' extending with yet one more octave... ' Could we add pitch insecurity in a simple way? ' versie 002: 11.10.2016: 40dB dynamiek, maar werkend in de onderste 13 bits ' 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 ' 14.10.2016: Presets modified. ' 07.12.2020: Timer3 reading bug killed. Upload to be done. ' 14.12.2020: Considering to change the ADSR system as done for ,,, ' however, we would need 3 ADSR timers in this case... ' Setting PTPER to 4096 and using 16-bit lookups, now looks like a bug we had... ' Did we have a reason to do that? ' Trying 16 bit and PWM freq. 1.8kHz. See how much leakthrough we get after our ' filter in the hardware... ' Controller 100 implemented for dynamic scale lookups. ' 15.12.2020: crash condition discovered, with 3 notes active, ADSR-system lands in the land of no return. ' Idea: we can still use the new adsr system with a fixed sampling rate, if we use three ' different counters in timer2. ' Start new implementation version 2.0. We may drop all note-individual adsr controllers ' Assembler error encountered... __T3Interrupt is already defined ???? isr_end- , hyphen vergeten! ' Ctrl100 back to Ctrl80, for compatibility with many other robots. ' Seems to work fine now. ' Testkode in GMT to be adapted now! ' Webpage documentation to be updated as well! ' There is place in fact for more tuning lookup tables now ' so, we can implement CC20 for tuning quite easily. ' It looks like even vibrato would be possible... ' For some reason, the ADSR system is not working anymore now... ' 16.12.2020: Searching the bug causing the ADSR system to refuse... ' got it to work again, but couldn't really trace the failure. ' processor load is quite high: loopspeed ca. 155kHz ' experimenting with the priority settings... ' 17.12.2020: amplitude modulation for sounding notes should be possible again. ' sustain1 etc... reintroduced. ' check for a series of 12 controllers not conflicting with Hybr. ' sus1, sus2, sus3 now on ctrl's 94-105 ' Order of priorities is of utmost importance for this code to work. ' Now we have: ' Timer1 5 ' Timer2 6 adsr ' Timer3 1 ' Timer4 4 ' Timer5 3 ' UARTRX 2 ' Metingen ADSR systeem: ' bij CC15 @ 127 en release @ 127 en sustain @ 127, duurt de uitsterftijd 1.28 sekonden. ' CC15 @ 32 en idem 320 ms ' om kompatibel te zijn met de V1.0 implementatie, waarbij release max. 512 ms was, ' moet CC15 = 51 zijn. ' de default waarden voor Attack en Decay moet wel gehalveerd worden t.o.v. versie 1.0, aangezien ' daar de max. periode 256 ms bedroeg. ' Berekende waarden: bij CC15 @ 127 is Timer2=ADSR_period= 112 + ((127+1) <<4) = 2160 ==> 9.1238 ms ' bij aan adsr-setting van 127. geeft dit een ADSR-sektie duur van 1.1678 s ' minima: bij CC15 = 0 is Timer2=ADSR_period = 112 + 16 = 128 ==> 0.54 ms ' bij adsr set to 127, geeft dit een ADSR-sektie duur van 69 ms ' Note: the ncd command can be used to calculate log2 of a value, if we do: ' a = ncd value ' decr a ' a now is the log2 of value. ' 17u30: opnieuw crash... line 282 was the cullprit: ' Symbol PWM_Range_Shift = 16 - (Ncd PWM_Range) ' 0 voor 16 bit. ' 19u30: solved. ' 18.12.2020: PIC's programmed and tested on HybrLo. ' 19.12.2020: Small bug found and cured. Ont[127] was set to 2^16 instead of 2^16 -1 in the 30dB scale. ' An issue that has risen now, whilst checking out some existing files using this robot, is that ' it is not possible now to perform a crescendo using controller 7. ' At first sight there are folloing options to solve this: ' 1.- use the sustain controllers 94-105. This is difficult is you want a crescendo on a chord... ' 2.- use a series of overlapping note-on's, with velo = cc7 and adsr-values = 0 ' 3.- implement channel aftertouch to do this? (requires modifications in this firmware) ' Question: was this possible in version 1.0 ??? ' Decided to solve the problem by implementing channel aftertouch. ' TO DO: ' implement tuning '------------------------------------------------------------------------------------------------------------- ' 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 ' port-assignments: '****************** Symbol poweron_led PORTA.4 ' orange LED Symbol watchdog_led PORTB.4 ' orange LED Symbol mute PORTB.5 ' this is pin 14 Symbol loopcnt PORTB.6 ' pin15 - only for loopspeed measurement. ' added for debugging the ADSR system: Symbol A_Led PORTA.0 Symbol D_Led PORTA.1 Symbol S_Led PORTB.0 Symbol R_Led PORTB.1 High mute ' avoiding artefacts on startup Config FPOR = ALTI2C1_OFF, ALTI2C2_OFF ' unsure about this 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 Declare Stack_Size = 120 ' higher than the default 60. This increases the amount of variable bytes used. $define Enable_UART_RX ' midi-in '$define Enable_UART_TX ' midi-out '$define Enable_ADC12bit ' precompiler instructions $define Enable_PWM ' precompiler instructions $define Enable_Timer1 ' precompiler instructions - 16 bit timer $define Enable_Timer2 ' adsr timer $define Enable_Timer3 ' watchdog 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 '$define ADSR_Debug ' for debugging only '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 'constant initialisations for the midi input parser: Symbol Midichannel = 8 ' HybrLo_Channel 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 CC80_default = 1 ' 0= 20dB, 1=30dB, 2= 40dB, 3=50dB, 4=60dB (14.12.2020) Symbol PWM_Range = 65535 ' was 4096 before 14.12.2020. - 12 bits ' but even for 12 bits it should have been 4095. ' if this is changed, the lookups will adapt automatically. Symbol PWM_Range_Shift = 0 ' 16 - (Ncd PWM_Range) ' 0 voor 16 bit. ' this must be wrong, as it crashes the adsr system. 'Symbol ADSR_shift = 9 ' value << ADSR_shift = value * 1024 ' ' 13.10.2016: Changed from 10 to 9 'Symbol Release_Shift = 10 ' release back to 512 ms Symbol CC15_default = 51 ' for 512 ms max. period. Symbol ADSR_period_default = CC15_default << 4 ' 816 ' change these for other boards and compilations: '$define Board22_24 $define Board25_27 '$define Board28_30 '$define Board31_33 $ifdef Board22_24 Symbol note1 = 22 ' introduced 10.10.2016 Symbol note2 = 23 Symbol note3 = 24 Symbol note1o = note1 + 12 ' 34 Symbol note2o = note2 + 12 ' 35 Symbol note3o = note3 + 12 ' 36 Symbol note1o2 = note1 + 24 ' 46 Symbol note2o2 = note2 + 24 ' 47 Symbol note3o2 = note3 + 24 ' 48 Symbol note1o3 = note1 + 36 ' 58 Symbol note2o3 = note2 + 36 ' 59 Symbol note3o3 = note3 + 36 ' 60 Symbol note1_period = 64355 Symbol note2_period = 60743 Symbol note3_period = 57334 Symbol note1o_period = 32178 Symbol note2o_period = 30372 Symbol note3o_period = 28667 Symbol note1o2_period = 64355 / 4 Symbol note2o2_period = 60743 / 4 Symbol note3o2_period = 57334 / 4 Symbol note1o3_period = 64355 / 8 Symbol note2o3_period = 60743 / 8 Symbol note3o3_period = 57334 / 8 Symbol sus1 = 94 ' 17.12.2020 Symbol sus2 = 95 Symbol sus3 = 96 Symbol NoteName1 = note1 // 12 ' in Proton Basic // is equivalent to MOD in standard basic. Symbol NoteName2 = note2 // 12 ' so here we get 0,1,2,3,4,5,6,7,8,9,10,11. Symbol NoteName3 = note3 // 12 $endif $ifdef Board25_27 Symbol note1 = 25 ' introduced 10.10.2016 Symbol note2 = 26 Symbol note3 = 27 Symbol note1o = note1 + 12 ' 37 Symbol note2o = note2 + 12 ' 38 Symbol note3o = note3 + 12 ' 39 Symbol note1o2 = note1 + 24 ' 49 Symbol note2o2 = note2 + 24 ' 50 Symbol note3o2 = note3 + 24 ' 51 Symbol note1o3 = note1 + 36 ' 61 Symbol note2o3 = note2 + 36 ' 62 Symbol note3o3 = note3 + 36 ' 63 Symbol note1_period = 54116 Symbol note2_period = 51079 Symbol note3_period = 48212 Symbol note1o_period = 27058 Symbol note2o_period = 25539 Symbol note3o_period = 24106 Symbol note1o2_period = 54116 / 4 Symbol note2o2_period = 51079 / 4 Symbol note3o2_period = 48212 / 4 Symbol note1o3_period = 54116 / 8 Symbol note2o3_period = 51079 / 8 Symbol note3o3_period = 48212 / 8 Symbol sus1 = 97 ' 17.12.2020 Symbol sus2 = 98 Symbol sus3 = 99 Symbol NoteName1 = note1 // 12 ' in Proton Basic // is equivalent to MOD in standard basic. Symbol NoteName2 = note2 // 12 Symbol NoteName3 = note3 // 12 $endif $ifdef Board28_30 Symbol note1 = 28 ' introduced 10.10.2016 Symbol note2 = 29 Symbol note3 = 30 Symbol note1o = note1 + 12 '40 Symbol note2o = note2 + 12 '41 Symbol note3o = note3 + 12 '42 Symbol note1o2 = note1 + 24 '52 Symbol note2o2 = note2 + 24 '53 Symbol note3o2 = note3 + 24 '54 Symbol note1o3 = note1 + 36 '64 Symbol note2o3 = note2 + 36 '65 Symbol note3o3 = note3 + 36 '66 Symbol note1_period = 45506 Symbol note2_period = 42952 Symbol note3_period = 40541 Symbol note1o_period = 22753 Symbol note2o_period = 21476 Symbol note3o_period = 20271 Symbol note1o2_period = 45506 / 4 Symbol note2o2_period = 42952 / 4 Symbol note3o2_period = 40541 / 4 Symbol note1o3_period = 45506 / 8 Symbol note2o3_period = 42952 / 8 Symbol note3o3_period = 40541 / 8 Symbol sus1 = 100 ' 17.12.2020 Symbol sus2 = 101 Symbol sus3 = 102 Symbol NoteName1 = note1 // 12 ' in Proton Basic // is equivalent to MOD in standard basic. Symbol NoteName2 = note2 // 12 Symbol NoteName3 = note3 // 12 $endif $ifdef Board31_33 Symbol note1 = 31 ' introduced 10.10.2016 Symbol note2 = 32 Symbol note3 = 33 Symbol note1o = note1 + 12 '43 Symbol note2o = note2 + 12 '44 Symbol note3o = note3 + 12 '45 Symbol note1o2 = note1 + 24 '55 Symbol note2o2 = note2 + 24 '56 Symbol note3o2 = note3 + 24 '57 Symbol note1o3 = note1 + 36 '67 Symbol note2o3 = note2 + 36 '68 Symbol note3o3 = note3 + 36 '69 Symbol note1_period = 38266 Symbol note2_period = 36118 Symbol note3_period = 34091 Symbol note1o_period = 19133 Symbol note2o_period = 18059 Symbol note3o_period = 17045 Symbol note1o2_period = 38266 / 4 Symbol note2o2_period = 36118 / 4 Symbol note3o2_period = 34091 / 4 Symbol note1o3_period = 38266 / 8 Symbol note2o3_period = 36118 / 8 Symbol note3o3_period = 34091 / 8 Symbol sus1 = 103 ' 17.12.2020 Symbol sus2 = 104 Symbol sus3 = 105 Symbol NoteName1 = note1 // 12 ' in Proton Basic // is equivalent to MOD in standard basic. Symbol NoteName2 = note2 // 12 Symbol NoteName3 = note3 // 12 $endif '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. 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) ' 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 adsr 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. ' pwm1H, pwm2H, pwm3H used as ADSR outputs ' we configure the L outputs as normal ports for frequency generator outputs ' the timers 1,4 and 5 are used as frequency generators. TRISA = %100000 ' set to output - we dont use these ports TRISB = %0101011100000000 'TRISB = %0000001100000000 ' 15.12.2020 - no difference... Output mute Output poweron_led Output watchdog_led Output A_Led Output D_Led Output S_Led Output R_Led High mute ' already done before clock config. Low poweron_led $ifdef Enable_Timer1 ' used as tone generator IPC0bits_T1IP0 = 1 ' set priority - this is very critical! IPC0bits_T1IP1 = 0 ' was set to 5 in version 1.0 IPC0bits_T1IP2 = 1 ' 6 = 011 , back to 5 now Clear TMR1 ' clear the count PR1 = 65535 ' load Timer1 period - just arbitrary start-up value here T1CON.5 = 1 ' set prescaler to :8 = 01 , :64 = 10 , :256 = 11 T1CON.4 = 0 ' prescaler = 1 = 00 (00 does not work: it freezes the PIC) IFS0bits_T1IF = 0 ' clear Timer1 interrupt flag IEC0bits_T1IE = 1 ' Enable the Timer1 interrupt Clear T1CONbits_TON ' stop on startup = T1CON.15 $endif $ifdef Enable_Timer2 ' determines amplitude sampling rate for the ADSR T2CONbits_TSIDL = 0 T2CONBITs_T32 = 0 ' 16 bits timer T2CONbits_TCS = 0 ' internal clock T2CON.5 = 1 ' pre-scale 256 T2CON.4 = 1 Clear TMR2 PR2 = ADSR_period_default ' ADSR_Period IFS0bits_T2IF = 0 ' clear IRQ flag IPC1bits_T2IP0 = 0 ' set priority to 3 IPC1bits_T2IP1 = 1 ' try 6 IPC1bits_T2IP2 = 1 IEC0bits_T2IE = 1 ' enable timer 2 interrupt Clear T2CONbits_TON ' stop timer for now! $endif $ifdef Enable_Timer3 ' only used as watchdog here, in both compilations T3CONbits_TSIDL = 0 T3CONbits_TCS = 0 ' internal clock T3CON.5 = 1 ' pre-scale 256 T3CON.4 = 1 IPC2bits_T3IP0 = 1 ' set priority to 1 - lowest IPC2bits_T3IP1 = 0 IPC2bits_T3IP2 = 0 Clear TMR3 Set PR3 '= 65535 IFS0bits_T3IF = 0 ' clear IRQ flag IEC0bits_T3IE = 1 ' enable timer 3 interrupt T3CONbits_TON = 1 ' start timer $endif ' $ifdef Enable_Timer23 ' 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 ' PR2 = 65535 ' PR3 = 65535 ' IPC2bits_T3IP0 = 1 ' set priority to 1 ' 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 'T4CON.15 = 1 ' start timer in 16 bit mode T4CON.13 = 0 T4CON.6 = 0 T4CON.5 = 1 ' prescaler set to :64 T4CON.4 = 0 ' 00 = :1, 01 = :8 , 10 = :64, 11 = :256 T4CON.3 = 0 ' operate as 16 bit timer T4CON.1 = 0 ' internal clock Clear TMR4 '= 0 Set PR4 '= 65535 IPC6bits_T4IP0 = 0 ' set priority to 4 IPC6bits_T4IP1 = 0 IPC6bits_T4IP2 = 1 Clear IFS1.11 ' clear interrupt flag Set IEC1.11 ' enable interrupt Clear T4CONbits_TON ' stop timer for now $endif $ifdef Enable_Timer5 'T5CON.15 = 1 ' start timer in 16 bit mode T5CON.13 = 0 T5CON.6 = 0 T5CON.5 = 1 ' prescaler set to :64 T5CON.4 = 0 ' id. T5CON.1 = 0 ' internal clock Clear TMR5 '= 0 Set PR5 '= 65535 ' preset counter 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 Clear T5CONbits_TON ' stop timer on init $endif $ifdef Enable_UART_RX ' init UART1-receiver: 31250 Baud ' should generate 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 for receiver IPC2.13 = 1 ' 1 IPC2.14 = 0 ' tested with change to 4, 1 step lower then the note timers now...[09.10.2016] ' back to 6 on 10.10.2016, as this was not the cause for the glitches. ' 15.12.2020: try setting it to 3, as midi-in is buffered anyway... ' try 2 ??? - no dif. 16.12.2020 IEC0.11 = 1 ' enable IRQ for receiver IEC4.1 = 1 ' enable IRQ for error trapping on receiver $endif $ifdef Enable_UART_TX U1STA.15 = 0 'interrupt generated when character transferred to tx buffer and buffer is empty U1STA.15 = 0 U1STA.10 = 1 ' transmit enable bit U1STA.11 = 0 Clear IFS0.12 ' clear transmit interrupt flag Set IEC0.12 ' enable interrupt IPC3.0 = 1 IPC3.1 = 1 IPC3.2 = 0 ' set priority to 3 $endif $ifdef Enable_ADC12bit ' init for ADC system: try 12 bit ADC (500kS/s) 'SMPI1. ADDMAEN = 0 AD1CON1.15 = 1 ' adc module ON AD1CON1.10 = 1 ' select 12-bit mode AD1CON1.9 = 0 ' conversion to right alligned integer 0000 dddd dddd dddd AD1CON1.8 = 0 ' id. AD1CON1.7 = 1 ' auto-convert mode AD1CON1.6 = 1 ' id. AD1CON1.5 = 1 ' id AD1CON1.4 = 0 ' SSRCG AD1CON1.2 = 1 ' sampling immediately after last conversion. SAMP bit it autoset. AD1CON2.15 = 0 ' ref AvDD and AsSS AD1CON2.14 = 0 AD1CON2.13 = 0 AD1CON2.10 = 0 ' no scan ' bits 6-2 = 0 ==> generates interrupt after every sample conversion AD1CON2.1 = 0 ' always fill buffer from the start adres AD1CON2.0 = 0 ' use channel input selects for sample MUXA AD1CON3.0 = 0 ' clock derived from system 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 ' ADCS ADC1 conversion clock select bits (sampling rate) AD1CON4.8 = 0 ' no DMA - results stored in ADC1BUF0 to ADC1BUFF registers AD1CHS0 = 0 ' clear complete register. AN0 is input channel ' now we have to enable the interrupt and find out how to transfer data to an array IEC0.13 = 1 ' enable IRQ 'IPC3 <6:4> set the priority level IFS0.13 = 0 ' clear interrupt flag ' --------------------------------------------------------------------------------- $endif $ifdef Enable_PWM ' PWM channel initialisation ------------------------------------------------------ 'CNPD1 ' enable internal pull down resistor to reset the FLT32 flag on init ' disable 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 Case 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 ' 09.10.2016 experiment: try this 'PTPER = 4096 ' it gives 29kHz base freq. for PWM - resolution is 12 bits ' 14.12.2020: try again with 16 bit resolution - frequency is 1831.16 Hz ' if we go back to 12-bits, the frequency is 29kHz and all Ont[] lookups ' have to be shifted >> 4. PTPER = PWM_Range 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 ' make the pwmL port free for general I/O: (note_Ports) 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 ' 0xA800 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 the timer-tone generators: 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: Dim inByte As Byte Dim IndexIn As Byte ' Pointer to the next empty location in the buffer Dim IndexOut As Byte ' Pointer to the location of the oldest character in the buffer Dim Ringbuffer[256] As Byte ' Array for holding received characters in the uart 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 Dim i As Byte Dim j As Word Dim playingnote1 As Byte Dim playingnote2 As Byte Dim playingnote3 As Byte Dim Dur[128] As Word $ifdef Enable_ADC12bit Dim Dur5[128] As Word Dim DataBuffer[256] As Word ' adc databuffer Dim DataInIdx As Byte Dim DataOutIdx As Byte $endif ' 16 bit variables and floats for the PWM system ' Dim dutcy1 As Float ' Dim dutcy2 As Float ' Dim dutcy3 As Float ' for integer coding of the duty cycle ctrl. [10.10.2016] Dim bdutcy1 As Byte ' 1-128 Dim bdutcy2 As Byte Dim bdutcy3 As Byte Dim Period[128] As Word ' midi note lookup table ' variables for the ADSR system: Dim Attack1_level As Word ' derived from velo, with a log-map via Ont[] Dim Attack2_level As Word ' derived from velo, with a log-map Dim Attack3_level As Word ' derived from velo, with a log-map ' 15.12.2020: variables for the new ADSR system: Dim CC15 As Word ' ADSR_period controller common for all notes Dim ADSR_period As Word ' = (CC15 + 1) << 4 Dim CC16 As Byte ' attack time controller ' Dim CC17 As Byte base setting for attack level - no longer used Dim CC18 As Byte ' decay time Dim CC19 As Byte ' release time controller value Dim amplitude As Dword Dim Volume As amplitude.Byte0 ' log map - controller #7 Dim CC7 As Volume ' alias Dim sustain1 As amplitude.Byte1 ' = Volume Dim sustain2 As amplitude.Byte2 ' = Volume Dim sustain3 As amplitude.Byte3 ' = Volume Dim Dyna As Word Dim CC80_old As Dyna.Byte1 Dim CC80 As Dyna.Byte0 Dim ADSR1_DW As Dword Dim ADSR1_clock As ADSR1_DW.Word0 ' for enveloppe sampler version with tmr2 Dim AD1cnt As ADSR1_DW.Word1 Dim ADSR2_DW As Dword Dim ADSR2_clock As ADSR2_DW.Word0 ' for enveloppe sampler version with tmr2 Dim AD2cnt As ADSR2_DW.Word1 Dim ADSR3_DW As Dword Dim ADSR3_clock As ADSR3_DW.Word0 ' for enveloppe sampler version with tmr2 Dim AD3cnt As ADSR3_DW.Word1 Dim ADSR_flags As Dword Dim ADSR1_flags As ADSR_flags.Byte0 Dim Attack1_flag As ADSR1_flags.0 ' 15.12.2020 Dim Decay1_flag As ADSR1_flags.1 Dim Release1_flag As ADSR1_flags.2 Dim ADSR2_flags As ADSR_flags.Byte1 Dim Attack2_flag As ADSR2_flags.0 ' 15.12.2020 Dim Decay2_flag As ADSR2_flags.1 Dim Release2_flag As ADSR2_flags.2 Dim ADSR3_flags As ADSR_flags.Byte2 Dim Attack3_flag As ADSR3_flags.0 ' 15.12.2020 Dim Decay3_flag As ADSR3_flags.1 Dim Release3_flag As ADSR3_flags.2 Dim cnt1 As Float 'Byte 'Word Dim Astepval1 As Float 'Word Dim Dstepval1 As Float 'Word Dim Rstepval1 As Float 'Word Dim cnt2 As Float 'Byte Dim Astepval2 As Float 'Word Dim Dstepval2 As Float 'Word Dim Rstepval2 As Float 'Word Dim cnt3 As Float 'Byte Dim Astepval3 As Float 'Word Dim Dstepval3 As Float 'Word Dim Rstepval3 As Float 'Word Dim Ont[128] As Word ' on-time lookup for pwm ' Dim Oft[128] As Word ' off-time lookup for pwm - not used in this coding. Dim On1 As Word ' for timer1 --> note1 Dim Of1 As Word Dim On2 As Word ' for timer4 --> note2 Dim Of2 As Word Dim On3 As Word ' for timer5 --> note3 Dim Of3 As Word Dim C1bit As Byte ' 13.10.2016 Dim C1val As Word 'byte ' controller #1 0-127 Dim jitter As SWord ' random byte -128 -> 127, changed to word 13.10.2016 Variable_Inits: Clear Ringbuffer ' Rx Clear IndexIn ' Clear the buffer internal pointer Clear IndexOut ' Clear the buffer external pointer GoSub Dur_Lookup GoSub Period_Lookup_Table ADSR_period = ADSR_period_default CC80 = CC80_default CC80_old = CC80_default Select CC80 Case 0 GoSub PWM_Lookup_Table_20dB Case 1 GoSub PWM_Lookup_Table_30dB Case 2 GoSub PWM_Lookup_Table_40dB Case 3 GoSub PWM_Lookup_Table_50db Case 4 GoSub PWM_Lookup_Table_60dB EndSelect GoSub Controller_Init_Prog0 'default controller settings un startup: Low loopcnt Clear ADSR1_DW Clear ADSR2_DW Clear ADSR3_DW GoTo MAIN ' jump over irq handlers Interrupt_handling: ' ----------------- Isr- T1Interrupt ' timer1 interrupt Clear IFS0bits_T1IF ' Reset the Timer1 interrupt flag ' used for pitch generator1 Clear TMR1 ' this is required! If Note_Port1 = 0 Then PR1 = On1 Set Note_Port1 Else PR1 = Of1 - jitter Clear Note_Port1 EndIf EndIsr- ' exit the interrupt Isr- T2Interrupt ' ADSR sampling rate Clear IFS0bits_T2IF ' clear interrupt flag Clear TMR2 ' seems required here PR2 = ADSR_period ' changed in real time with CC15 If ADSR1_flags > 0 Then Inc ADSR1_clock ' adsr-clocks for all three note generators If ADSR2_flags > 0 Then Inc ADSR2_clock If ADSR3_flags > 0 Then Inc ADSR3_clock 'toggle A_Led ' for measurement only EndIsr- Isr- T3Interrupt ' watchdog - enabled in all compilations. Clear IFS0bits_T3IF ' clear interrupt flag Toggle watchdog_led ' led freq = 1.8Hz EndIsr- ' Isr- T3Interrupt ' Clear IFS0bits_T3IF ' 32-bit value reached (T2/T3 combined) ' ' this was our main timer! ' EndIsr- Isr- T4Interrupt Clear IFS1bits_T4IF '16-bit value reached Clear TMR4 If Note_Port2 = 0 Then PR4 = On2 Set Note_Port2 Else PR4 = Of2 - jitter Clear Note_Port2 EndIf EndIsr- Isr- T5Interrupt Clear IFS1bits_T5IF ' 32-bit value reached if T4/T5 operation in 32 bits ' 16-bit value reached if operated alone. Clear TMR5 If Note_Port3 = 0 Then PR5 = On3 Set Note_Port3 Else PR5 = Of3 - jitter Clear Note_Port3 EndIf EndIsr- Isr- U1RXInterrupt ' UART receive IRQ - midi receiver Clear IFS0.11 ' reset UART1 receive irq flag Inc IndexIn ' Move up the buffer index (0-255) Ringbuffer[IndexIn] = 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 'Toggle midi_led ' transmit monitor EndIsr- Isr- AD1Interrupt ' this irq happens after every ADC conversion Clear IFS0.13 ' clear interrupt flag ' Inc DataInIdx ' move up the buffer index ' DataBuffer[DataInIdx] = ADC1BUF0 ' loopt tot ADC1BUFF -so 16 words deep ' Toggle PORTA.1 ' for testing sampling rate - 04.08.2016: gives 58.82 kHz ' this means 8.5 us for each conversion EndIsr- Isr- PWM1Interrupt Clear IFS5.14 EndIsr- Isr- PWM2Interrupt Clear IFS5.15 EndIsr- Isr- PWM3Interrupt Clear IFS6.0 EndIsr- GetMidi: If IndexIn <> IndexOut Then Inc IndexOut Bytein = Ringbuffer[IndexOut] Else Set Bytein EndIf Return GetADC: ' here we can perform data extraction and signal conditioning ' the data-buffer has 256 words and covers 2.176ms of time. Return MAIN: While GoSub GetMidi ' Read data from the serial buffer ' Start the midi parser. Midi_Parse: If Bytein > Aftertouch_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 Check_Timers '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 ' could be used for different lookup tables statusbyte = Bytein Set prog Case Aftertouch_Status ' used for global amplitude modulation statusbyte = Bytein 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 Check_Timers 'disregard Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein + 1 ' message complete, so we can do the action... Select noteUit // 12 ' we can do this, because the midi-hub and parser board ' blocks all notes that are out of range. ' coding with 3 ADSR's and fixed pwm channels Case NoteName1 ' note1, note1o, note1o2, note1o3 ' =22, 34 ... ADSR1_flags = 4 ' should do the same... ' cnt1 = Volume ' integer becomes float. ' Rstepval1 = cnt1 / release 'volume / release ' PDC1 = Ont[Volume] ' required here??? 16.12.2020 ' changed 17.12.2020 to: cnt1 = sustain1 Rstepval1 = cnt1 / release PDC1 = Ont[sustain1] Clear ADSR1_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer Case NoteName2 ' note2, note2o, note2o2, note2o3 ' =23, 35 ADSR2_flags = 4 cnt2 = sustain2 'Volume Rstepval2 = cnt2 / release PDC2 = Ont[sustain2] ' Ont[Volume] Clear ADSR2_DW Set T2CONbits_Ton ' start timer Case NoteName3 'note3, note3o, note3o2, note3o3 ' =24, 36 , 48 , 60 ADSR3_flags = 4 cnt3 = sustain3 ' Volume Rstepval3 = cnt3 / release PDC3 = Ont[sustain3] ' Ont[Volume] Clear ADSR3_DW Set T2CONbits_Ton ' start timer 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 // 12 Case NoteName1 'note1, note1o, note1o2, note1o3 ' =22, 34 ADSR1_flags = 4 cnt1 = sustain1 ' Volume Rstepval1 = cnt1 / CC19 PDC1 = Ont[sustain1] ' Ont[Volume] Clear ADSR1_DW Set T2CONbits_Ton ' start timer Case NoteName2 'note2, note2o, note2o2, note2o3 '= 23 , 35 ADSR2_flags = 4 cnt2 = sustain2 ' Volume Rstepval2 = cnt2 / CC19 PDC2 = Ont[sustain2] ' Ont[Volume] Clear ADSR2_DW Set T2CONbits_Ton ' start timer Case NoteName3 'note3, note3o, note3o2, note3o3 '= 24, 36 ADSR3_flags = 4 cnt3 = sustain3 ' Volume Rstepval3 = cnt3 / CC19 PDC3 = Ont[sustain3] ' Ont[Volume] Clear ADSR3_DW Set T2CONbits_Ton ' start timer EndSelect Else Select noteAan Case note1 playingnote1 = noteAan Attack1_level = velo ADSR1_flags = 1 Clear cnt1 ' start volume from zero Clear PDC1 ' start from zero Astepval1 = Attack1_level / CC16 ' to be used as increment for Cnt Clear ADSR1_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer1 as frequency generator On1 = note1_period.Byte1 * bdutcy1 Of1 = note1_period - On1 Clear Note_Port1 ' start with 0 Clear IFS0bits_T1IF ' clear irq flag Set IEC0bits_T1IE ' enable timer1 interrupt Set T1CONbits_TON ' start timer1 Case note2 playingnote2 = noteAan Attack2_level = velo ADSR2_flags = 1 Clear cnt2 ' start volume from zero Clear PDC2 ' start from zero Astepval2 = Attack2_level / CC16 ' to be used as increment for Cnt Clear ADSR2_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer4 as frequency generator On2 = note2_period.Byte1 * bdutcy2 Of2 = note2_period - On2 Clear Note_Port2 Clear IFS1bits_T4IF ' clear irq flag Set IEC1bits_T4IE ' enable timer4 interrupt Set T4CONbits_TON Case note3 playingnote3 = noteAan Attack3_level = velo 'Clear ADSR3_flags ADSR3_flags = 1 Clear cnt3 ' start volume from zero Clear PDC3 ' start from zero 'Set Attack3_flag ' = 1 Astepval3 = Attack3_level / CC16 ' to be used as increment for Cnt 'Clear ADSR3_clock 'Clear AD3cnt Clear ADSR3_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer5 as frequency generator On3 = note3_period.Byte1 * bdutcy3 Of3 = note3_period - On3 Clear Note_Port3 Clear IFS1bits_T5IF ' clear irq flag Set IEC1bits_T5IE ' enable timer5 interrupt Set T5Conbits_TON Case note1o playingnote1 = noteAan Attack1_level = velo 'Clear ADSR1_flags ADSR1_flags = 1 Clear cnt1 ' start volume from zero Clear PDC1 ' start from zero 'Set Attack1_flag ' = 1 Astepval1 = Attack1_level / CC16 ' to be used as increment for Cnt 'Clear ADSR1_clock 'Clear AD1cnt Clear ADSR1_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer1 as frequency generator On1 = note1o_period.Byte1 * bdutcy1 Of1 = note1o_period - On1 Clear Note_Port1 Clear IFS0bits_T1IF ' clear irq flag Set IEC0bits_T1IE ' enable timer1 interrupt Set T1Conbits_TON Case note2o playingnote2 = noteAan Attack2_level = velo 'Clear ADSR2_flags ADSR2_flags = 1 Clear cnt2 ' start volume from zero Clear PDC2 ' start from zero 'Set Attack2_flag ' = 1 Astepval2 = Attack2_level / CC16 ' to be used as increment for Cnt 'Clear ADSR2_clock 'Clear AD2cnt Clear ADSR2_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer4 as frequency generator On2 = note2o_period.Byte1 * bdutcy2 Of2 = note2o_period - On2 Clear Note_Port2 Clear IFS1bits_T4IF ' clear irq flag Set IEC1bits_T4IE ' enable timer4 interrupt Set T4CONbits_TON Case note3o playingnote3 = noteAan Attack3_level = velo 'Clear ADSR3_flags ADSR3_flags = 1 Clear cnt3 ' start volume from zero Clear PDC3 ' start from zero 'Set Attack3_flag ' = 1 Astepval3 = Attack3_level / CC16 ' to be used as increment for Cnt 'Clear ADSR3_clock 'Clear AD3cnt Clear ADSR3_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer5 as frequency generator On3 = note3o_period.Byte1 * bdutcy3 Of3 = note3o_period - On3 Clear Note_Port3 Clear IFS1bits_T5IF ' clear irq flag Set IEC1bits_T5IE ' enable timer5 interrupt Set T5CONbits_TON Case note1o2 playingnote1 = noteAan Attack1_level = velo 'Clear ADSR1_flags ADSR1_flags = 1 Clear cnt1 ' start volume from zero Clear PDC1 ' start from zero 'Set Attack1_flag ' = 1 Astepval1 = Attack1_level / CC16 ' to be used as increment for Cnt 'Clear ADSR1_clock 'Clear AD1cnt Clear ADSR1_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer1 as frequency generator On1 = note1o2_period.Byte1 * bdutcy1 Of1 = note1o2_period - On1 Clear Note_Port1 Clear IFS0bits_T1IF ' clear irq flag Set IEC0bits_T1IE ' enable timer1 interrupt Set T1CONbits_TON Case note2o2 playingnote2 = noteAan Attack2_level = velo 'Clear ADSR2_flags ADSR2_flags = 1 Clear cnt2 ' start volume from zero Clear PDC2 ' start from zero 'Set Attack2_flag ' = 1 Astepval2 = Attack2_level / CC16 ' to be used as increment for Cnt 'Clear ADSR2_clock 'Clear AD2cnt Clear ADSR2_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer4 as frequency generator On2 = note2o2_period.Byte1 * bdutcy2 Of2 = note2o2_period - On2 Clear Note_Port2 Clear IFS1bits_T4IF ' clear irq flag Set IEC1bits_T4IE ' enable timer4 interrupt Set T4CONbits_TON Case note3o2 playingnote3 = noteAan Attack3_level = velo 'Clear ADSR3_flags ADSR3_flags = 1 Clear cnt3 ' start volume from zero Clear PDC3 ' start from zero 'Set Attack3_flag ' = 1 Astepval3 = Attack3_level / CC16 ' to be used as increment for Cnt 'Clear ADSR3_clock 'Clear AD3cnt Clear ADSR3_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer5 as frequency generator On3 = note3o2_period.Byte1 * bdutcy3 Of3 = note3o2_period - On3 Clear Note_Port3 Clear IFS1bits_T5IF ' clear irq flag Set IEC1bits_T5IE ' enable timer5 interrupt Set T5CONbits_TON Case note1o3 playingnote1 = noteAan Attack1_level = velo 'Clear ADSR1_flags ADSR1_flags = 1 Clear cnt1 ' start volume from zero Clear PDC1 ' start from zero 'Set Attack1_flag ' = 1 Astepval1 = Attack1_level / CC16 ' to be used as increment for Cnt 'Clear ADSR1_clock 'Clear AD1cnt Clear ADSR1_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer1 as frequency generator On1 = note1o3_period.Byte1 * bdutcy1 Of1 = note1o3_period - On1 Clear Note_Port1 Clear IFS0bits_T1IF ' clear irq flag Set IEC0bits_T1IE ' enable timer1 interrupt Set T1CONbits_TON Case note2o3 playingnote2 = noteAan Attack2_level = velo 'Clear ADSR2_flags ADSR2_flags = 1 Clear cnt2 ' start volume from zero Clear PDC2 ' start from zero 'Set Attack2_flag ' = 1 Astepval2 = Attack2_level / CC16 ' to be used as increment for Cnt 'Clear ADSR2_clock 'Clear AD2cnt Clear ADSR2_DW 'If T2CONbits_Ton = 0 Then Set T2CONbits_Ton ' start timer Set T2CONbits_Ton ' start timer ' program timer4 as frequency generator On2 = note2o3_period.Byte1 * bdutcy2 Of2 = note2o3_period - On2 Clear Note_Port2 Clear IFS1bits_T4IF ' clear irq flag Set IEC1bits_T4IE ' enable timer4 interrupt Set T4CONbits_TON Case note3o3 playingnote3 = noteAan Attack3_level = velo ADSR3_flags = 1 'Set Attack3_flag ' = 1 Clear cnt3 ' start volume from zero Clear PDC3 ' start from zero Astepval3 = Attack3_level / CC16 ' to be used as increment for Cnt Clear ADSR3_DW Set T2CONbits_Ton ' start timer ' program timer5 as frequency generator On3 = note3o3_period.Byte1 * bdutcy3 Of3 = note3o3_period - On3 Clear Note_Port3 Clear IFS1bits_T5IF ' clear irq flag Set IEC1bits_T5IE ' enable timer5 interrupt Set T5CONbits_TON EndSelect Set noteAan EndIf EndIf Case Keypres_Status If notePres = 255 Then notePres = Bytein Else pres = Bytein GoSub KeyPres EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf Case ProgChange_Status If prog = 255 Then 'single byte message prog = Bytein GoSub ProgChange EndIf Case Aftertouch_Status If aft = 255 Then aft = Bytein GoSub Aftertouch EndIf Case Pitchbend_Status If pblsb = 255 Then pblsb = Bytein Else pbmsb = Bytein GoSub Pitchbend EndIf EndSelect EndIf Check_Timers: If ADSR_flags = 0 Then ' check the DWORD, combining all 3 envelope channels If T2CONbits_TON = 1 Then Clear T2CONbits_TON ' stop timer2 Clear ADSR1_DW Clear ADSR2_DW Clear ADSR3_DW EndIf GoTo jit_algo EndIf ' now we have 3 ADSR's to be checked here... Check_ADSR1: Select ADSR1_flags Case 0 GoTo Check_ADSR2 ' niks voor deze noot Case 1 If AD1cnt < ADSR1_clock Then Inc AD1cnt If cnt1 < Attack1_level Then ' note that attack1_level = velo here. cnt1 = cnt1 + Astepval1 If cnt1 > Attack1_level Then ' attack time is verstreken cnt1 = Attack1_level PDC1 = Ont[Attack1_level] ' set level ' calculate decay phase Dstepval1 = Volume - Attack1_level ' <0 ==> we have to reduce volume Dstepval1 = Dstepval1 / CC18 ' >0 ==> we have to further increase volume Select Dstepval1 Case 0 PDC1= Ont[Volume] Clear ADSR1_flags Clear ADSR1_DW ' we cannot stop timer2 here, as it may be required for other notes!!! ' so dont do: clear T2CONbits_Ton Case Else ADSR1_flags = 2 Clear ADSR1_DW Set T2CONbits_Ton ' start timer EndSelect Else i = cnt1 PDC1 = Ont[i] EndIf EndIf EndIf Case 2 ' note: we decay always to the value set with volume, as the ' individual settings for sustain1 can only be applied ' during the sustain phase of the envelope. ' 17.12.2020. If AD1cnt < ADSR1_clock Then Inc AD1cnt cnt1 = cnt1 + Dstepval1 ' bipolar! If cnt1 < 0 Then cnt1 = 0 Select Dstepval1 ' Dstepval = 0 kan zich niet voordoen Case < 0 ' decrease volume If cnt1 > Volume Then i = cnt1 PDC1 = Ont[i] 'If T2CONbits_TON = 0 Then Set T2CONbits_TON Set T2CONbits_Ton ' start timer Else PDC1 = Ont[Volume] Clear ADSR1_flags Clear ADSR1_DW EndIf Case > 0 ' increase volume If cnt1 < Volume Then i = cnt1 PDC1 = Ont[i] 'If T2CONbits_TON = 0 Then Set T2CONbits_TON Set T2CONbits_Ton ' start timer Else PDC1 = Ont[Volume] Clear ADSR1_flags Clear ADSR1_DW EndIf EndSelect EndIf Case 4 If AD1cnt < ADSR1_clock Then Inc AD1cnt ' release phase - Cnt must have been set = Sustain_level in the noteoff cnt1 = cnt1 - Rstepval1 Select cnt1 Case <= 0 Clear ADSR1_flags Clear PDC1 Clear ADSR1_DW Clear playingnote1 ' stop pitch generator: Clear IEC0bits_T1IE ' disable timer1 interrupt - tone generator Clear IFS0bits_T1IF ' clear irq flag Clear T1CONbits_TON ' stop timer1 Clear Note_Port1 ' zero out Case Else i = cnt1 PDC1 = Ont[i] EndSelect EndIf EndSelect Check_ADSR2: Select ADSR2_flags Case 0 GoTo Check_ADSR3 ' niks Case 1 If AD2cnt < ADSR2_clock Then Inc AD2cnt If cnt2 <= Attack2_level Then cnt2 = cnt2 + Astepval2 If cnt2 > Attack2_level Then ' attack time is verstreken cnt2 = Attack2_level PDC2 = Ont[Attack2_level] ' set level ' calculate decay phase Dstepval2 = Volume - Attack2_level ' <0 ==> we have to reduce volume Dstepval2 = Dstepval2 / CC18 ' >0 ==> we have to further increase volume Select Dstepval2 Case 0 PDC2= Ont[Volume] Clear ADSR2_flags Clear ADSR2_DW Case Else ADSR2_flags = 2 Clear ADSR2_DW Set T2CONbits_TON EndSelect Else i = cnt2 PDC2 = Ont[i] EndIf EndIf EndIf Case 2 If AD2cnt < ADSR2_clock Then Inc AD2cnt cnt2 = cnt2 + Dstepval2 ' bipolar! If cnt2 < 0 Then cnt2 = 0 Select Dstepval2 ' Dstepval = 0 kan zich niet voordoen Case < 0 ' decrease volume If cnt2 > Volume Then i = cnt2 PDC2 = Ont[i] 'If T2CONbits_TON = 0 Then Set T2CONbits_TON Else PDC2 = Ont[Volume] Clear ADSR2_flags Clear ADSR2_DW EndIf Case > 0 ' increase volume If cnt2 < Volume Then i = cnt2 PDC2 = Ont[i] 'If T2CONbits_TON = 0 Then Set T2CONbits_TON Else PDC2 = Ont[Volume] Clear ADSR2_flags Clear ADSR2_DW EndIf EndSelect EndIf Case 4 If AD2cnt < ADSR2_clock Then Inc AD2cnt ' release phase - Cnt must have been set = Sustain_level in the noteoff cnt2 = cnt2 - Rstepval2 Select cnt2 Case <= 0 Clear ADSR2_flags Clear PDC2 Clear playingnote2 Clear ADSR2_DW ' stop pitch generator: Clear IEC1bits_T4IE ' disable timer4 interrupt Clear IFS1bits_T4IF ' clear interrupt flag Clear T4CONbits_TON ' timer off Clear Note_Port2 ' zero out Case Else i = cnt2 PDC2 = Ont[i] EndSelect EndIf EndSelect Check_ADSR3: Select ADSR3_flags Case 0 GoTo jit_algo ' niks Case 1 If AD3cnt < ADSR3_clock Then Inc AD3cnt If cnt3 <= Attack3_level Then cnt3 = cnt3 + Astepval3 If cnt3 > Attack3_level Then ' attack time is verstreken cnt3 = Attack3_level PDC3 = Ont[Attack3_level] ' set level ' calculate decay phase Dstepval3 = Volume - Attack3_level ' <0 ==> we have to reduce volume Dstepval3 = Dstepval3 / CC18 ' >0 ==> we have to further increase volume Select Dstepval3 Case 0 PDC3= Ont[Volume] Clear ADSR3_flags Clear ADSR3_DW Case Else ADSR3_flags = 2 Clear ADSR3_DW 'If T2CONbits_TON = 0 Then Set T2CONbits_TON ' start timer Set T2CONbits_TON EndSelect Else i = cnt3 PDC3 = Ont[i] EndIf EndIf EndIf Case 2 If AD3cnt < ADSR3_clock Then Inc AD3cnt cnt3 = cnt3 + Dstepval3 ' bipolar! If cnt3 < 0 Then cnt3 = 0 Select Dstepval3 ' Dstepval = 0 kan zich niet voordoen Case < 0 ' decrease volume If cnt3 > Volume Then i = cnt3 PDC3 = Ont[i] 'If T2CONbits_TON = 0 Then Set T2CONbits_TON Else PDC3 = Ont[Volume] Clear ADSR3_flags Clear ADSR3_DW EndIf Case > 0 ' increase volume If cnt3 < Volume Then i = cnt3 PDC3 = Ont[i] 'If T2CONbits_TON = 0 Then Set T2CONbits_TON Else PDC3 = Ont[Volume] Clear ADSR3_flags Clear ADSR3_DW EndIf EndSelect EndIf Case 4 If AD3cnt < ADSR3_clock Then Inc AD3cnt ' release phase - Cnt3 must have been set = sustain3 in the noteoff cnt3 = cnt3 - Rstepval3 Select cnt3 Case <= 0 Clear ADSR3_flags Clear PDC3 Clear playingnote3 Clear ADSR3_DW ' stop pitch generator: Clear IEC1bits_T5IE ' disable timer5 interrupt Clear IFS1bits_T5IF ' clear interrupt flag Clear T5CONbits_TON ' stop timer5 Clear Note_Port3 ' zero out Case Else i = cnt3 PDC3 = Ont[i] EndSelect EndIf EndSelect $ifdef Enable_UART_TX ' not defined in this code Midi_OutPut: If OutIdxOut <> OutIdxIn Then ' in dit geval is er een byte te versturen If IFS0bits_U1TXIF = 0 Then Inc OutIdxOut U1TXREG = Outbuffer[OutIdxOut] EndIf EndIf $endif jit_algo: ' for Ctrl#1 implementation in HybrLo j = Random & C1val ' 0 - 254, with mask so range will be 0 - C1val ' now 0 - 1023 jitter = (C1val >> 1) - j ' make it bipolar - 512 -> + 511 ' -128 -> 127 $ifdef ADSR_Debug ' for debugging - adsr channel 1 A_Led = Attack1_flag ' works ok D_Led = Decay1_flag ' works ok R_Led = Release1_flag ' works ok If ADSR1_flags = 0 Then If playingnote1 > 0 Then Set S_Led ' yellow Else Clear S_Led EndIf Else Clear S_Led EndIf $endif ' Toggle loopcnt ' for loopspeed measurement: 1.3us now ' 10.08.2016: 366kHz met alle taken aan, 440kHz onbelast ' 17.12.2020: 150kHz onder full load and with debug code.No load: 242kHz ' --> worst case 3.3 us per loop, so still faster than the timer resolution at 4.2 us. Wend KeyPres: ' can be used to modulate the wave shape ' 10.10.2016: rewritten avoiding floats... ' 15.12.2020: can remain here without changes. ' could go faster by selecting on notepres MOD 12 ' versus cases notename1... calculated as constants as ' note1 mod 12 etc... '... does not work, as the periods are different for the octaves. Select notePres Case note1 bdutcy1 = pres + 1 On1 = note1_period.Byte1 * bdutcy1 Of1 = note1_period - On1 Case note2 bdutcy2 = pres + 1 On2 = note2_period.Byte1 * bdutcy2 Of2 = note2_period - On2 Case note3 bdutcy3 = pres + 1 On3 = note3_period.Byte1 * bdutcy3 Of3 = note3_period - On3 Case note1o bdutcy1 = pres + 1 On1 = note1o_period.Byte1 * bdutcy1 Of1 = note1o_period - On1 Case note2o bdutcy2 = pres + 1 On2 = note2o_period.Byte1 * bdutcy2 Of2 = note2o_period - On2 Case note3o bdutcy3 = pres + 1 On3 = note3o_period.Byte1 * bdutcy3 Of3 = note3o_period - On3 Case note1o2 bdutcy1 = pres + 1 On1 = note1o2_period.Byte1 * bdutcy1 Of1 = note1o2_period - On1 Case note2o2 bdutcy2 = pres + 1 On2 = note2o2_period.Byte1 * bdutcy2 Of2 = note2o2_period - On2 Case note3o2 bdutcy3 = pres + 1 On3 = note3o2_period.Byte1 * bdutcy3 Of3 = note3o2_period - On3 Case note1o3 bdutcy1 = pres + 1 On1 = note1o3_period.Byte1 * bdutcy1 Of1 = note1o3_period - On1 Case note2o3 bdutcy2 = pres + 1 On2 = note2o3_period.Byte1 * bdutcy2 Of2 = note2o3_period - On2 Case note3o3 bdutcy3 = pres + 1 On3 = note3o3_period.Byte1 * bdutcy3 Of3 = note3o3_period - On3 EndSelect Set notePres Return ProgChange: ' could be implemented to enable or disable common notes with ' or for adding presets. ' make sure the code in the hub firmware, also sends the program change command! ' Presets would also be possible to change the tuning... Select prog Case 0 'reset controllers to cold boot values GoSub Controller_Init_Prog0 Case 1 ' place for many more presets GoSub Preset1 Case 2 GoSub Preset2 Case 3 GoSub Preset3 Case 4 GoSub Preset4 Case 5 GoSub Preset5 Case 6 GoSub Preset6 Case 7 GoSub Preset7 EndSelect Set prog '= 255 Return Pitchbend: ' not implemented Set pblsb Set pbmsb Return Aftertouch: ' 19.12.2020: 'this is the channel aftertouch, affecting any playing note 'used to make global amplitude modulation possible... 'This requires an upgrade of the firmware on the midi-hub and parser board! If playingnote1 > 0 Then PDC1 = Ont[aft] EndIf If playingnote2 > 0 Then PDC2 = Ont[aft] EndIf If playingnote3 > 0 Then PDC3 = Ont[aft] EndIf Set aft ' reset Return Controller: Select Ctrl Case 1 'C1bit, C1val - introduced 13.10.2016 C1val = value << 3 ' 0- 1023 '0-254 C1bit = Ncd value ' returns 0-8 'Priority encoder of a 16-bit or 32-bit value. Ncd takes a value, finds the highest bit containing a '1 and returns the bit position plus one (1 through 32). If no bit is set, the input value is 0. Ncd 'returns 0. Ncd is a fast way to get an answer to the question "what is the largest power of two 'that this value is greater than or equal to?" The answer that Ncd returns will be that power, plus 'one. '? Isn't this the same as Log2. Case 7 ' global volume controller (in fact, sustain controller) Volume = value ' needs remapping on a 16-bit log scale using Ont[value] ' CC7 is an alias for volume sustain1 = Volume ' so this overrides the controllers sus1, sus2, sus3 sustain2 = Volume sustain3 = Volume Case 14 ' global waveform control - also done for individual notes with keypres ' note that using this controller it is not possible to change the waveform whilst the note is sounding. ' If that is required, use the key pressure commands. Inc value ' 0 crashes the system... bdutcy1 = value ' 1-128 bdutcy2 = value bdutcy3 = value Case 15 ' new in HybrLo since 15.12.2020: CC15 = value ADSR_period = (CC15 + 1) << 4 ' 16 - 2048 << 4 = x16 '2048 = 8.65ms/step ot Sample rate = 116Hz ' 16 would be 14880 S/s, way too fast so we better do: ADSR_period = ADSR_period + 112 ' so the fastest S/s would become 1860 Hz Case 16 ' was not implemented in version 1 ' new 15.12.2020: CC16 = value + 1 ' attack_time - this was CC17 in version 1 ' Case 17 ' does not have a function anymore now... 'CC17 = value + 1 ' is attack level in monophonic robots ,,,, ' in this coding, attack level is controlled with the velocity byte. Case 18 CC18 = value + 1 ' global decay time control Case 19 CC19 = value + 1 ' global release time control 'Case 20 ' should be tuning Case 66 'on/off for the robot If value = 0 Then ' power down GoSub PowerDown ' should reset controllers Set mute ' mutes the amps Else Clear mute Set poweron_led ' ok - yellow LED EndIf Case 80 ' use for dynamic scalings... ' can be used to change the dynamic curves used CC80 = value + 1 ' 1-128 CC80 = CC80 >> 5 ' 0 - 1 - 2 - 3 - 4 5-lookups since 14.12.2020 ' >> 5 is equivalent to / 32. If CC80 <> CC80_old Then Select CC80 Case 0 ' -20dB range GoSub PWM_Lookup_Table_20dB Case 1 ' -30dB range GoSub PWM_Lookup_Table_30dB Case 2 ' -40dB range GoSub PWM_Lookup_Table_40dB Case 3 ' -50dB range GoSub PWM_Lookup_Table_50db Case 4 ' - 60dB range - default on HybrLo, for compatibility with earlier ' applications. GoSub PWM_Lookup_Table_60dB EndSelect CC80_old = CC80 EndIf Case 90 ' range limiter. Implemented on the Hub-board!!! ' in case this is received whilst we have a note playing, we must issue an ' allnotes-off. Otherwize we risk a sticking note... ' this is a lot of code that will very likely never need to perform... If playingnote1 > 0 Then Clear PDC1 ' note1 volume down Clear ADSR1_flags Clear IEC0bits_T1IE ' disable the Timer1 interrupt Clear Note_Port1 Clear playingnote1 Clear ADSR1_DW EndIf If playingnote2 > 0 Then Clear PDC2 ' note2 volume down Clear ADSR2_flags Clear IEC1bits_T4IE ' disable timer4 Clear Note_Port2 Clear playingnote2 Clear ADSR2_DW EndIf If playingnote3 > 0 Then Clear PDC3 ' note3 volume down Clear IEC1bits_T5IE ' disable timer5 Clear ADSR3_flags Clear Note_Port3 Clear playingnote3 Clear ADSR3_DW EndIf If ADSR_flags = 0 Then ' check the dword Clear T2CONbits_TON ' stop timer2 EndIf Case sus1 ' sustain level modulator for note1 ' if we want to allow modulation during the sounding of a note, ' we have to proceed as follows: ' HybrLo, version 1.0: ' If IEC0bits_T1IE = 1 Then ' tone generator works ' in a new version, test playingnote1 here. ' If ADSR1_flags = 0 Then ' we must be in the sustain phase! ' PDC1 = Ont[value] ' EndIf ' EndIf ' ' version 2.0: If playingnote1 > 0 Then If ADSR1_flags = 0 Then ' we must be in the sustain phase! PDC1 = Ont[value] sustain1 = value ' overriding volume setting... EndIf Else sustain1 = Volume ' reset EndIf Case sus2 If playingnote2 > 0 Then If ADSR2_flags = 0 Then PDC2 = Ont[value] sustain2 = value EndIf Else sustain2 = Volume EndIf Case sus3 If playingnote3 > 0 Then If ADSR3_flags = 0 Then PDC3 = Ont[value] sustain3 = value EndIf Else sustain3 = Volume EndIf Case 123 ' all notes off - no controller resets Clear PDC1 ' note1 volume down Clear PDC2 ' note2 volume down Clear PDC3 ' note3 volume down Clear ADSR_flags ' clear the dword: ADSR1_flags, ADSR2_flags and ADSR3_flags Clear T2CONbits_TON ' stop timer2 Clear IEC0bits_T1IE ' disable the Timer1 interrupt Clear IEC1bits_T4IE ' disable timer4 Clear IEC1bits_T5IE ' disable timer5 ' wouldn't it be better to stop the timer? Clear Note_Port1 Clear Note_Port2 Clear Note_Port3 Clear playingnote1 Clear playingnote2 Clear playingnote3 Clear ADSR1_DW ' clears both AD1cnt and ADSR1_clock Clear ADSR2_DW Clear ADSR3_DW EndSelect Set Ctrl 'mandatory reset Return PowerDown: Clear PDC1 Clear PDC2 Clear PDC3 Set mute Clear poweron_led Clear ADSR_flags Clear T2CONbits_TON ' stop timer2 Clear IEC0bits_T1IE ' disable the Timer1 interrupt Clear IEC1bits_T4IE ' disable Timer4 irq Clear IEC1bits_T5IE ' disable Timer5 irq Low Note_Port1 Low Note_Port2 Low Note_Port3 Clear playingnote1 Clear playingnote2 Clear playingnote3 Clear ADSR1_DW Clear ADSR2_DW Clear ADSR3_DW ' reset conrollers: ADSR_period = (CC15_default + 1) << 4 GoSub Controller_Init_Prog0 ' set the defaults CC80 = CC80_default Select CC80 Case 0 ' -20dB range GoSub PWM_Lookup_Table_20dB Case 1 ' -30dB range GoSub PWM_Lookup_Table_30dB Case 2 ' -40dB range GoSub PWM_Lookup_Table_40dB Case 3 ' -50dB range GoSub PWM_Lookup_Table_50db Case 4 ' - 60dB range - default on HybrLo, for compatibility with earlier ' applications. GoSub PWM_Lookup_Table_60dB EndSelect Return Controller_Init_Prog0: ' reset controllers to default start-up values: CC16 = 8 ' should be ca. 32ms . 64=250ms CC18 = 6 Volume = 86 ' set with CC7 sustain1 = Volume sustain2 = Volume sustain3 = Volume CC19 = 10 bdutcy1 = 128 ' 50% duty cycle bdutcy2 = 128 bdutcy3 = 128 Clear C1val ' reset ctrl#1 (0-1024) Return Preset1: ' should give pizz CC16 = 2 CC18 = 1 Volume = 28 sustain1 = Volume sustain2 = Volume sustain3 = Volume CC19 = 30 bdutcy1 = 11 ' dutcy1 = 0.086 bdutcy2 = 11 ' dutcy2 = 0.086 bdutcy3 = 11 ' dutcy3 = 0.086 C1val = 100 ' a bit rough! - ca. 10% jitter Return Preset2: ' should give nasal sound with slow attack CC16 = 25 CC18 = 10 Volume = 120 ' set with CC7 sustain1 = Volume sustain2 = Volume sustain3 = Volume CC19 = 50 ' set with release byte or ctrl bdutcy1 = 3 ' dutcy1 = 0.018 bdutcy2 = 3 bdutcy3 = 3 C1val = 150 ' 15% jitter Return Preset3: ' round organ register CC16 = 8 CC18 = 2 Volume = 100 ' set with CC7 sustain1 = Volume sustain2 = Volume sustain3 = Volume CC19 = 10 ' set with release byte or ctrl bdutcy1 = 80 '47 'dutcy1 = 0.37 bdutcy2 = 80 '47 'dutcy2 = 0.37 bdutcy3 = 80 '47 'dutcy3 = 0.37 C1val = 10 ' small jitter (= midi value 1) Return Preset4: ' should be short sharp sound CC16 = 1 CC18 = 1 Volume = 127 sustain1 = Volume sustain2 = Volume sustain3 = Volume CC19 = 20 ' set with release byte or ctrl bdutcy1 = 3 'dutcy1 = 0.012 bdutcy2 = 3 'dutcy2 = 0.012 bdutcy3 = 3 'dutcy3 = 0.012 C1val = 500 ' midi value = 63 Return Preset5: ' to do Return Preset6: ' to do Return Preset7: ' to do Return Dur_Lookup: 'lookup for experiment. 1 dur unit is now 2.3us with loopcounter 'using timer23, 1 dur unit is 4.224 us Set Dur[0] Dur[1]= 23674 ' 03.08.2016: 56ms ' 04.08/2016: 66.2ms - 7.55 Hz ' 07.08.2016: 2x100ms = 200ms full period --> 5Hz [o.k.14.08.2016] Dur[2]= 22917 ' freq= 2.18178644674259 Dur[3]= 22548 ' freq= 2.21749157353202 Dur[4]= 22185 ' freq= 2.25377507324769 Dur[5]= 21827 ' freq= 2.29074082558299 Dur[6]= 21475 ' freq= 2.32828870779977 Dur[7]= 21129 ' freq= 2.36641582658905 Dur[8]= 20789 ' freq= 2.40511809129828 Dur[9]= 20454 ' freq= 2.44450963136795 Dur[10]= 20124 ' freq= 2.48459550785132 Dur[11]= 19800 ' freq= 2.52525252525252 Dur[12]= 19481 ' freq= 2.56660335711719 Dur[13]= 19167 ' freq= 2.60865028434288 Dur[14]= 18858 ' freq= 2.65139463357726 Dur[15]= 18554 ' freq= 2.69483669289641 Dur[16]= 18255 ' freq= 2.73897562311695 Dur[17]= 17961 ' freq= 2.7838093647347 Dur[18]= 17672 ' freq= 2.82933454051607 Dur[19]= 17387 ' freq= 2.87571173865532 Dur[20]= 17107 ' freq= 2.92278014847723 Dur[21]= 16831 ' freq= 2.97070881112233 Dur[22]= 16560 ' freq= 3.01932367149758 Dur[23]= 16293 ' freq= 3.06880255324372 Dur[24]= 16030 ' freq= 3.11915159076731 Dur[25]= 15772 ' freq= 3.17017499365965 Dur[26]= 15518 ' freq= 3.22206469905916 Dur[27]= 15268 ' freq= 3.27482315954938 Dur[28]= 15022 ' freq= 3.32845160431367 Dur[29]= 14780 ' freq= 3.382949932341 Dur[30]= 14542 ' freq= 3.43831660019254 Dur[31]= 14307 ' freq= 3.4947927587894 Dur[32]= 14077 ' freq= 3.55189315905378 Dur[33]= 13850 ' freq= 3.6101083032491 Dur[34]= 13627 ' freq= 3.66918617450649 Dur[35]= 13407 ' freq= 3.72939509211606 Dur[36]= 13191 ' freq= 3.79046319460238 Dur[37]= 12978 ' freq= 3.85267375558638 Dur[38]= 12769 ' freq= 3.91573341686898 Dur[39]= 12564 ' freq= 3.97962432346386 Dur[40]= 12361 ' freq= 4.04498017959712 Dur[41]= 12162 ' freq= 4.1111659266568 Dur[42]= 11966 ' freq= 4.17850576633796 Dur[43]= 11773 ' freq= 4.24700586086809 Dur[44]= 11583 ' 07.08.2016: geeft 10.1177 Hz Dur[45]= 11397 ' freq= 4.38711941739054 Dur[46]= 11213 ' freq= 4.45910996165165 Dur[47]= 11032 ' freq= 4.53226976069616 Dur[48]= 10855 ' freq= 4.60617227084293 Dur[49]= 10680 ' freq= 4.6816479400749 Dur[50]= 10508 ' freq= 4.75827940616673 Dur[51]= 10338 ' freq= 4.83652544012381 Dur[52]= 10172 ' freq= 4.91545418796697 Dur[53]= 10008 ' freq= 4.99600319744204 Dur[54]= 9846 ' freq= 5.07820434694292 Dur[55]= 9688 ' freq= 5.16102394715111 Dur[56]= 9532 ' freq= 5.24548887956357 Dur[57]= 9378 ' freq= 5.33162721262529 Dur[58]= 9227 ' freq= 5.4188793757451 Dur[59]= 9078 ' freq= 5.50782110597048 Dur[60]= 8932 ' freq= 5.59785042543663 Dur[61]= 8788 ' freq= 5.68957669549385 Dur[62]= 8646 ' freq= 5.78302105019662 Dur[63]= 8507 ' 04.08.2016: 21Hz pulse duur = 23.8ms Dur[64]= 8370 ' geeft nu 20ms pulsen freq= 25Hz 03.08.2016 ' 14.0017Hz 07.08.2016 Dur[65]= 8235 ' freq= 6.07164541590771 Dur[66]= 8102 ' freq= 6.17131572451246 Dur[67]= 7972 ' freq= 6.27195183140993 Dur[68]= 7843 ' freq= 6.37511156445238 Dur[69]= 7717 ' freq= 6.47920176234288 Dur[70]= 7593 ' freq= 6.58501251152377 Dur[71]= 7470 ' freq= 6.69344042838019 Dur[72]= 7350 ' freq= 6.80272108843537 Dur[73]= 7231 ' freq= 6.91467293597013 Dur[74]= 7115 ' freq= 7.02740688685875 Dur[75]= 7000 ' freq= 7.14285714285714 Dur[76]= 6888 ' freq= 7.25900116144018 Dur[77]= 6777 ' freq= 7.37789582411096 Dur[78]= 6667 ' freq= 7.49962501874906 Dur[79]= 6560 ' freq= 7.62195121951219 Dur[80]= 6454 ' freq= 7.74713356058258 Dur[81]= 6350 ' freq= 7.8740157480315 Dur[82]= 6248 ' freq= 8.00256081946223 Dur[83]= 6147 ' freq= 8.13404912965674 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 ' 03.08.2016: 6.9ms nu = 144Hz ' 04.08.2016: 8.35ms - 59.5Hz 'Set Dur5[0] ' not used 'Dur5[1]= 41667 ' freq= .999992000063999 'Dur5[2]= 39494 ' freq= 1.0550125757499 'Dur5[3]= 38450 ' freq= 1.08365843086259 'Dur5[4]= 37434 ' freq= 1.11307011451265 'Dur5[5]= 36445 ' freq= 1.14327525495038 'Dur5[6]= 35482 ' freq= 1.17430434210774 'Dur5[7]= 34544 ' freq= 1.20619113787247 'Dur5[8]= 33631 ' freq= 1.23893629885126 'Dur5[9]= 32743 ' freq= 1.27253662360403 'Dur5[10]= 31877 ' freq= 1.30710752789367 'Dur5[11]= 31035 ' freq= 1.34257021642232 'Dur5[12]= 30215 ' freq= 1.37900601246621 'Dur5[13]= 29416 ' freq= 1.41646269603844 'Dur5[14]= 28639 ' freq= 1.45489251254117 'Dur5[15]= 27882 ' freq= 1.49439303732396 'Dur5[16]= 27146 ' freq= 1.53490999287802 'Dur5[17]= 26428 ' freq= 1.57661066545583 'Dur5[18]= 25730 ' freq= 1.61938074880166 'Dur5[19]= 25050 ' freq= 1.66333998669328 'Dur5[20]= 24388 ' freq= 1.70849051446066 'Dur5[21]= 23743 ' freq= 1.75490319953951 'Dur5[22]= 23116 ' freq= 1.8025033166061 'Dur5[23]= 22505 ' freq= 1.85144042064726 'Dur5[24]= 21910 ' freq= 1.90171915411532 'Dur5[25]= 21331 ' freq= 1.95333864641445 'Dur5[26]= 20768 ' freq= 2.006291730868 'Dur5[27]= 20219 ' freq= 2.06076792455941 'Dur5[28]= 19685 ' freq= 2.11667090000847 'Dur5[29]= 19164 ' freq= 2.17421554303207 'Dur5[30]= 18658 ' freq= 2.23317969057062 'Dur5[31]= 18165 ' freq= 2.29378842095605 'Dur5[32]= 17685 ' freq= 2.35604561304307 'Dur5[33]= 17218 ' freq= 2.41994811631239 'Dur5[34]= 16763 ' freq= 2.48563304102289 'Dur5[35]= 16320 ' freq= 2.5531045751634 'Dur5[36]= 15888 ' freq= 2.62252433702585 'Dur5[37]= 15469 ' freq= 2.69355916133342 'Dur5[38]= 15060 ' freq= 2.76671093404161 'Dur5[39]= 14662 ' freq= 2.84181330423316 'Dur5[40]= 14274 ' freq= 2.91906029610948 'Dur5[41]= 13897 ' freq= 2.99824902257082 'Dur5[42]= 13530 ' freq= 3.07957625030796 'Dur5[43]= 13172 ' freq= 3.16327563518575 'Dur5[44]= 12824 ' freq= 3.24911624038262 'Dur5[45]= 12485 ' freq= 3.33733813910025 'Dur5[46]= 12155 ' freq= 3.42794460441519 'Dur5[47]= 11834 ' freq= 3.52092839840009 'Dur5[48]= 11522 ' freq= 3.61627032343922 'Dur5[49]= 11217 ' freq= 3.71459986330272 'Dur5[50]= 10921 ' freq= 3.81527943106553 'Dur5[51]= 10632 ' freq= 3.91898670679709 'Dur5[52]= 10351 ' freq= 4.02537597011561 'Dur5[53]= 10078 ' freq= 4.13441820467024 'Dur5[54]= 9811 ' freq= 4.24693371385859 'Dur5[55]= 9552 ' freq= 4.36208821887214 'Dur5[56]= 9300 ' freq= 4.48028673835125 'Dur5[57]= 9054 ' freq= 4.60201752448273 'Dur5[58]= 8815 ' freq= 4.72679145396105 'Dur5[59]= 8582 ' freq= 4.85512312592247 'Dur5[60]= 8355 ' freq= 4.9870337123479 'Dur5[61]= 8134 ' freq= 5.12253094008688 'Dur5[62]= 7919 ' freq= 5.26160710527423 'Dur5[63]= 7710 ' freq= 5.40423692174665 'Dur5[64]= 7506 ' freq= 5.5511146638245 'Dur5[65]= 7308 ' freq= 5.70151432220398 'Dur5[66]= 7115 ' freq= 5.85617240571562 'Dur5[67]= 6927 ' freq= 6.01510995621 'Dur5[68]= 6744 ' freq= 6.1783313562673 'Dur5[69]= 6565 ' freq= 6.34678852500635 'Dur5[70]= 6392 ' freq= 6.51856487275761 'Dur5[71]= 6223 ' freq= 6.69559162247576 'Dur5[72]= 6059 ' freq= 6.87682235792485 'Dur5[73]= 5898 ' freq= 7.06454165253758 'Dur5[74]= 5743 ' freq= 7.25520924023449 'Dur5[75]= 5591 ' freq= 7.45245334764204 'Dur5[76]= 5443 ' freq= 7.65509216730969 'Dur5[77]= 5299 ' freq= 7.86311882745172 'Dur5[78]= 5159 ' freq= 8.07650061381405 'Dur5[79]= 5023 ' freq= 8.29517552591413 'Dur5[80]= 4890 ' freq= 8.52079072937969 'Dur5[81]= 4761 ' freq= 8.75166281593503 'Dur5[82]= 4635 ' freq= 8.98957209636821 'Dur5[83]= 4513 ' freq= 9.23258734027624 'Dur5[84]= 4393 ' freq= 9.48478640261021 'Dur5[85]= 4277 ' freq= 9.74203101862676 'Dur5[86]= 4164 ' freq= 10.0064040986231 'Dur5[87]= 4054 ' freq= 10.277914816642 'Dur5[88]= 3947 ' freq= 10.5565408326999 'Dur5[89]= 3843 ' freq= 10.842223956978 'Dur5[90]= 3741 ' freq= 11.1378419317473 'Dur5[91]= 3642 ' freq= 11.4406004027091 'Dur5[92]= 3546 ' freq= 11.7503290092122 'Dur5[93]= 3452 ' freq= 12.0702974121282 'Dur5[94]= 3361 ' freq= 12.3971040364971 'Dur5[95]= 3272 ' freq= 12.7343113284434 'Dur5[96]= 3186 ' freq= 13.0780498012136 'Dur5[97]= 3102 ' freq= 13.4321942832581 'Dur5[98]= 3020 ' freq= 13.7969094922737 'Dur5[99]= 2940 ' freq= 14.172335600907 'Dur5[100]= 2862 ' freq= 14.5585837409737 'Dur5[101]= 2787 ' freq= 14.9503647889008 'Dur5[102]= 2713 ' freq= 15.3581521071385 'Dur5[103]= 2641 ' freq= 15.7768522024486 'Dur5[104]= 2571 ' freq= 16.2064047711656 'Dur5[105]= 2504 ' freq= 16.640042598509 'Dur5[106]= 2437 ' freq= 17.0975242784845 'Dur5[107]= 2373 ' freq= 17.5586458772299 'Dur5[108]= 2310 ' freq= 18.037518037518 'Dur5[109]= 2249 ' freq= 18.5267526307989 'Dur5[110]= 2190 ' freq= 19.0258751902588 'Dur5[111]= 2132 ' freq= 19.5434646654159 'Dur5[112]= 2076 ' freq= 20.0706486833654 'Dur5[113]= 2021 ' freq= 20.616856341745 'Dur5[114]= 1967 ' freq= 21.182850364345 'Dur5[115]= 1915 ' freq= 21.7580504786771 'Dur5[116]= 1865 ' freq= 22.3413762287757 'Dur5[117]= 1815 ' freq= 22.9568411386593 'Dur5[118]= 1767 ' freq= 23.5804565176382 'Dur5[119]= 1721 ' freq= 24.2107301956227 'Dur5[120]= 1675 ' freq= 24.8756218905473 'Dur5[121]= 1631 ' freq= 25.5466993664418 'Dur5[122]= 1588 ' freq= 26.2384550797649 'Dur5[123]= 1546 ' freq= 26.9512721000431 'Dur5[124]= 1505 ' freq= 27.6854928017719 'Dur5[125]= 1465 ' freq= 28.4414106939704 'Dur5[126]= 1427 ' freq= 29.1987853305302 'Dur5[127]= 1389 ' freq= 29.9976001919846 'For i = 0 To 127 ' Dur5[i] = Dur5[i] >> 3 'so range becomes 8Hz to 240Hz 'Next i Return ' midi-note to period lookup for PIC24 with 120MHz clock ' time_unit = 8.33333333333333E-9 ' divider set to = 64 ' lowest note = midi 22 (Sib) , freq = 29.1355235 Hz Period_Lookup_Table: Period[22]= 64355 ' soll frequency = 29.13523 real frequency = 29.13526 Period[23]= 60743 ' soll frequency = 30.86771 real frequency = 30.86775 Period[24]= 57334 ' soll frequency = 32.70319 real frequency = 32.70311 Period[25]= 54116 ' soll frequency = 34.64783 real frequency = 34.64779 Period[26]= 51079 ' soll frequency = 36.7081 real frequency = 36.70784 Period[27]= 48212 ' soll frequency = 38.89087 real frequency = 38.89073 Period[28]= 45506 ' soll frequency = 41.20344 real frequency = 41.20336 Period[29]= 42952 ' soll frequency = 43.65353 real frequency = 43.65338 Period[30]= 40541 ' soll frequency = 46.2493 real frequency = 46.24948 Period[31]= 38266 ' soll frequency = 48.99943 real frequency = 48.99911 Period[32]= 36118 ' soll frequency = 51.91308 real frequency = 51.91317 Period[33]= 34091 ' soll frequency = 55 real frequency = 54.99986 Period[34]= 32178 ' soll frequency = 58.27047 real frequency = 58.26963 Period[35]= 30372 ' soll frequency = 61.73541 real frequency = 61.73449 Period[36]= 28667 ' soll frequency = 65.40639 real frequency = 65.40622 Period[37]= 27058 ' soll frequency = 69.29565 real frequency = 69.29558 Period[38]= 25539 ' soll frequency = 73.41619 real frequency = 73.41713 Period[39]= 24106 ' soll frequency = 77.78174 real frequency = 77.78146 Period[40]= 22753 ' soll frequency = 82.40689 real frequency = 82.40672 Period[41]= 21476 ' soll frequency = 87.30706 real frequency = 87.30676 Period[42]= 20271 ' soll frequency = 92.4986 real frequency = 92.49667 Period[43]= 19133 ' soll frequency = 97.99886 real frequency = 97.99822 Period[44]= 18059 ' soll frequency = 103.8262 real frequency = 103.8263 Period[45]= 17045 ' soll frequency = 110 real frequency = 110.0029 Period[46]= 16089 ' soll frequency = 116.5409 real frequency = 116.5392 Period[47]= 15186 ' soll frequency = 123.4708 real frequency = 123.469 Period[48]= 14333 ' soll frequency = 130.8128 real frequency = 130.817 Period[49]= 13529 ' soll frequency = 138.5913 real frequency = 138.5912 Period[50]= 12770 ' soll frequency = 146.8324 real frequency = 146.8285 Period[51]= 12053 ' soll frequency = 155.5635 real frequency = 155.5629 Period[52]= 11376 ' soll frequency = 164.8138 real frequency = 164.8207 Period[53]= 10738 ' soll frequency = 174.6141 real frequency = 174.6135 Period[54]= 10135 ' soll frequency = 184.9972 real frequency = 185.0025 Period[55]= 9566 ' soll frequency = 195.9977 real frequency = 196.0067 Period[56]= 9030 ' soll frequency = 207.6523 real frequency = 207.6412 Period[57]= 8523 ' soll frequency = 220 real frequency = 219.993 Period[58]= 8044 ' soll frequency = 233.0819 real frequency = 233.093 Period[59]= 7593 ' soll frequency = 246.9416 real frequency = 246.938 Period[60]= 7167 ' soll frequency = 261.6255 real frequency = 261.6158 Period[61]= 6764 ' soll frequency = 277.1826 real frequency = 277.2028 Period[62]= 6385 ' soll frequency = 293.6648 real frequency = 293.657 Period[63]= 6026 ' soll frequency = 311.127 real frequency = 311.1517 Period[64]= 5688 ' soll frequency = 329.6276 real frequency = 329.6414 Period[65]= 5369 ' soll frequency = 349.2282 real frequency = 349.227 Period[66]= 5068 ' soll frequency = 369.9944 real frequency = 369.9684 Period[67]= 4783 ' soll frequency = 391.9954 real frequency = 392.0134 Period[68]= 4515 ' soll frequency = 415.3047 real frequency = 415.2824 Period[69]= 4261 ' soll frequency = 440 real frequency = 440.0375 Period[70]= 4022 ' soll frequency = 466.1638 real frequency = 466.186 Period[71]= 3796 ' soll frequency = 493.8833 real frequency = 493.941 Period[72]= 3583 ' soll frequency = 523.2511 real frequency = 523.3045 Period[73]= 3382 ' soll frequency = 554.3652 real frequency = 554.4057 Period[74]= 3192 ' soll frequency = 587.3295 real frequency = 587.406 Period[75]= 3013 ' soll frequency = 622.254 real frequency = 622.3033 Period[76]= 2844 ' soll frequency = 659.2551 real frequency = 659.2827 Period[77]= 2684 ' soll frequency = 698.4565 real frequency = 698.5842 Period[78]= 2534 ' soll frequency = 739.9888 real frequency = 739.9368 Period[79]= 2392 ' soll frequency = 783.9908 real frequency = 783.8628 Period[80]= 2257 ' soll frequency = 830.6094 real frequency = 830.7488 Period[81]= 2131 ' soll frequency = 880 real frequency = 879.8686 Period[82]= 2011 ' soll frequency = 932.3275 real frequency = 932.3719 Period[83]= 1898 ' soll frequency = 987.7666 real frequency = 987.882 Period[84]= 1792 ' soll frequency = 1046.502 real frequency = 1046.317 Period[85]= 1691 ' soll frequency = 1108.73 real frequency = 1108.811 Period[86]= 1596 ' soll frequency = 1174.659 real frequency = 1174.812 Period[87]= 1507 ' soll frequency = 1244.508 real frequency = 1244.194 Period[88]= 1422 ' soll frequency = 1318.51 real frequency = 1318.565 Period[89]= 1342 ' soll frequency = 1396.913 real frequency = 1397.168 Period[90]= 1267 ' soll frequency = 1479.978 real frequency = 1479.874 Period[91]= 1196 ' soll frequency = 1567.982 real frequency = 1567.726 Period[92]= 1129 ' soll frequency = 1661.219 real frequency = 1660.762 Period[93]= 1065 ' soll frequency = 1760 real frequency = 1760.563 Period[94]= 1006 ' soll frequency = 1864.655 real frequency = 1863.817 Period[95]= 949 ' soll frequency = 1975.533 real frequency = 1975.764 Period[96]= 896 ' soll frequency = 2093.004 real frequency = 2092.634 Period[97]= 846 ' soll frequency = 2217.461 real frequency = 2216.312 Period[98]= 798 ' soll frequency = 2349.318 real frequency = 2349.624 Period[99]= 753 ' soll frequency = 2489.016 real frequency = 2490.04 Period[100]= 711 ' soll frequency = 2637.02 real frequency = 2637.131 Period[101]= 671 ' soll frequency = 2793.826 real frequency = 2794.337 Period[102]= 633 ' soll frequency = 2959.955 real frequency = 2962.085 Period[103]= 598 ' soll frequency = 3135.963 real frequency = 3135.451 Period[104]= 564 ' soll frequency = 3322.438 real frequency = 3324.468 Period[105]= 533 ' soll frequency = 3520 real frequency = 3517.824 Period[106]= 503 ' soll frequency = 3729.31 real frequency = 3727.634 Period[107]= 475 ' soll frequency = 3951.066 real frequency = 3947.368 Period[108]= 448 ' soll frequency = 4186.009 real frequency = 4185.268 Period[109]= 423 ' soll frequency = 4434.922 real frequency = 4432.624 Period[110]= 399 ' soll frequency = 4698.636 real frequency = 4699.248 Period[111]= 377 ' soll frequency = 4978.032 real frequency = 4973.475 Period[112]= 356 ' soll frequency = 5274.041 real frequency = 5266.854 Period[113]= 336 ' soll frequency = 5587.652 real frequency = 5580.357 Period[114]= 317 ' soll frequency = 5919.911 real frequency = 5914.827 Period[115]= 299 ' soll frequency = 6271.927 real frequency = 6270.903 Period[116]= 282 ' soll frequency = 6644.875 real frequency = 6648.936 Period[117]= 266 ' soll frequency = 7040 real frequency = 7048.872 Period[118]= 251 ' soll frequency = 7458.62 real frequency = 7470.12 Period[119]= 237 ' soll frequency = 7902.133 real frequency = 7911.392 Period[120]= 224 ' soll frequency = 8372.018 real frequency = 8370.536 Period[121]= 211 ' soll frequency = 8869.844 real frequency = 8886.256 Period[122]= 200 ' soll frequency = 9397.272 real frequency = 9375 Period[123]= 188 ' soll frequency = 9956.063 real frequency = 9973.404 Period[124]= 178 ' soll frequency = 10548.08 real frequency = 10533.71 Period[125]= 168 ' soll frequency = 11175.3 real frequency = 11160.71 Period[126]= 158 ' soll frequency = 11839.82 real frequency = 11867.09 Period[127]= 149 ' soll frequency = 12543.85 real frequency = 12583.89 Return ' pwm on/off values for PIC24 with 120MHz clock ' time_unit = 8.33333333333333E-9 ' divider set to = 8 ' using a 16 bit timers (timer1, 4, 5) ' PWM base frequency = 15000 ' with divider set to 1 pwm base freq becomes 120kHz ' so with the 16-bit values below we would get an audible 915Hz pitch... ' divider set to 1 does not work, it freezes the PIC, ' so we must use :8 ' Note 09.10.2016: 60dB range is exagerated. ' would be better with a 40dB or even 34dB range. ' PWM base frequency can be halved as well... PWM_Lookup_Table_20dB: 'HybrLo volume scales 20dB 'for 16 bit PWM values - PWM Freq. 1.8kHz '------log-scale------ Ont[0]= 0 '6673 ' db= -19.84375 Ont[1]= 6794 ' db= -19.6875 Ont[2]= 6917 ' db= -19.53125 Ont[3]= 7043 ' db= -19.375 Ont[4]= 7170 ' db= -19.21875 Ont[5]= 7301 ' db= -19.0625 Ont[6]= 7433 ' db= -18.90625 Ont[7]= 7568 ' db= -18.75 Ont[8]= 7705 ' db= -18.59375 Ont[9]= 7845 ' db= -18.4375 Ont[10]= 7988 ' db= -18.28125 Ont[11]= 8133 ' db= -18.125 Ont[12]= 8280 ' db= -17.96875 Ont[13]= 8431 ' db= -17.8125 Ont[14]= 8584 ' db= -17.65625 Ont[15]= 8739 ' db= -17.5 Ont[16]= 8898 ' db= -17.34375 Ont[17]= 9060 ' db= -17.1875 Ont[18]= 9224 ' db= -17.03125 Ont[19]= 9391 ' db= -16.875 Ont[20]= 9562 ' db= -16.71875 Ont[21]= 9735 ' db= -16.5625 Ont[22]= 9912 ' db= -16.40625 Ont[23]= 10092 ' db= -16.25 Ont[24]= 10275 ' db= -16.09375 Ont[25]= 10462 ' db= -15.9375 Ont[26]= 10652 ' db= -15.78125 Ont[27]= 10845 ' db= -15.625 Ont[28]= 11042 ' db= -15.46875 Ont[29]= 11242 ' db= -15.3125 Ont[30]= 11446 ' db= -15.15625 Ont[31]= 11654 ' db= -15 Ont[32]= 11866 ' db= -14.84375 Ont[33]= 12081 ' db= -14.6875 Ont[34]= 12300 ' db= -14.53125 Ont[35]= 12524 ' db= -14.375 Ont[36]= 12751 ' db= -14.21875 Ont[37]= 12982 ' db= -14.0625 Ont[38]= 13218 ' db= -13.90625 Ont[39]= 13458 ' db= -13.75 Ont[40]= 13702 ' db= -13.59375 Ont[41]= 13951 ' db= -13.4375 Ont[42]= 14204 ' db= -13.28125 Ont[43]= 14462 ' db= -13.125 Ont[44]= 14725 ' db= -12.96875 Ont[45]= 14992 ' db= -12.8125 Ont[46]= 15264 ' db= -12.65625 Ont[47]= 15541 ' db= -12.5 Ont[48]= 15823 ' db= -12.34375 Ont[49]= 16110 ' db= -12.1875 Ont[50]= 16403 ' db= -12.03125 Ont[51]= 16701 ' db= -11.875 Ont[52]= 17004 ' db= -11.71875 Ont[53]= 17312 ' db= -11.5625 Ont[54]= 17627 ' db= -11.40625 Ont[55]= 17947 ' db= -11.25 Ont[56]= 18272 ' db= -11.09375 Ont[57]= 18604 ' db= -10.9375 Ont[58]= 18942 ' db= -10.78125 Ont[59]= 19285 ' db= -10.625 Ont[60]= 19636 ' db= -10.46875 Ont[61]= 19992 ' db= -10.3125 Ont[62]= 20355 ' db= -10.15625 Ont[63]= 20724 ' db= -10 Ont[64]= 21100 ' db= -9.84375 Ont[65]= 21483 ' db= -9.6875 Ont[66]= 21873 ' db= -9.53125 Ont[67]= 22270 ' db= -9.375 Ont[68]= 22675 ' db= -9.21875 Ont[69]= 23086 ' db= -9.0625 Ont[70]= 23505 ' db= -8.90625 Ont[71]= 23932 ' db= -8.75 Ont[72]= 24366 ' db= -8.59375 Ont[73]= 24809 ' db= -8.4375 Ont[74]= 25259 ' db= -8.28125 Ont[75]= 25718 ' db= -8.125 Ont[76]= 26184 ' db= -7.96875 Ont[77]= 26660 ' db= -7.8125 Ont[78]= 27144 ' db= -7.65625 Ont[79]= 27636 ' db= -7.5 Ont[80]= 28138 ' db= -7.34375 Ont[81]= 28649 ' db= -7.1875 Ont[82]= 29169 ' db= -7.03125 Ont[83]= 29698 ' db= -6.875 Ont[84]= 30237 ' db= -6.71875 Ont[85]= 30786 ' db= -6.5625 Ont[86]= 31345 ' db= -6.40625 Ont[87]= 31914 ' db= -6.25 Ont[88]= 32493 ' db= -6.09375 Ont[89]= 33083 ' db= -5.9375 Ont[90]= 33684 ' db= -5.78125 Ont[91]= 34295 ' db= -5.625 Ont[92]= 34917 ' db= -5.46875 Ont[93]= 35551 ' db= -5.3125 Ont[94]= 36197 ' db= -5.15625 Ont[95]= 36854 ' db= -5 Ont[96]= 37523 ' db= -4.84375 Ont[97]= 38204 ' db= -4.6875 Ont[98]= 38897 ' db= -4.53125 Ont[99]= 39603 ' db= -4.375 Ont[100]= 40322 ' db= -4.21875 Ont[101]= 41054 ' db= -4.0625 Ont[102]= 41799 ' db= -3.90625 Ont[103]= 42558 ' db= -3.75 Ont[104]= 43330 ' db= -3.59375 Ont[105]= 44117 ' db= -3.4375 Ont[106]= 44918 ' db= -3.28125 Ont[107]= 45733 ' db= -3.125 Ont[108]= 46563 ' db= -2.96875 Ont[109]= 47408 ' db= -2.8125 Ont[110]= 48269 ' db= -2.65625 Ont[111]= 49145 ' db= -2.5 Ont[112]= 50037 ' db= -2.34375 Ont[113]= 50945 ' db= -2.1875 Ont[114]= 51870 ' db= -2.03125 Ont[115]= 52812 ' db= -1.875 Ont[116]= 53770 ' db= -1.71875 Ont[117]= 54746 ' db= -1.5625 Ont[118]= 55740 ' db= -1.40625 Ont[119]= 56752 ' db= -1.25 Ont[120]= 57782 ' db= -1.09375 Ont[121]= 58831 ' db= -.9375 Ont[122]= 59899 ' db= -.78125 Ont[123]= 60986 ' db= -.625 Ont[124]= 62093 ' db= -.46875 Ont[125]= 63220 ' db= -.3125 Ont[126]= 64368 ' db= -.15625 Ont[127]= 65535 ' db= 0 If PWM_Range_Shift > 0 Then For i = 0 To 127 Ont[i] = Ont[i] >> PWM_Range_Shift Next i EndIf Return PWM_Lookup_Table_30dB: 'HybrLo volume scales 30dB 'for 16 bit PWM values '------log-scale------ Ont[0]= 0 ' 2129 ' db= -29.765625 Ont[1]= 2187 ' db= -29.53125 Ont[2]= 2247 ' db= -29.296875 Ont[3]= 2309 ' db= -29.0625 Ont[4]= 2372 ' db= -28.828125 Ont[5]= 2437 ' db= -28.59375 Ont[6]= 2503 ' db= -28.359375 Ont[7]= 2572 ' db= -28.125 Ont[8]= 2642 ' db= -27.890625 Ont[9]= 2714 ' db= -27.65625 Ont[10]= 2789 ' db= -27.421875 Ont[11]= 2865 ' db= -27.1875 Ont[12]= 2943 ' db= -26.953125 Ont[13]= 3024 ' db= -26.71875 Ont[14]= 3106 ' db= -26.484375 Ont[15]= 3191 ' db= -26.25 Ont[16]= 3279 ' db= -26.015625 Ont[17]= 3368 ' db= -25.78125 Ont[18]= 3460 ' db= -25.546875 Ont[19]= 3555 ' db= -25.3125 Ont[20]= 3652 ' db= -25.078125 Ont[21]= 3752 ' db= -24.84375 Ont[22]= 3855 ' db= -24.609375 Ont[23]= 3960 ' db= -24.375 Ont[24]= 4069 ' db= -24.140625 Ont[25]= 4180 ' db= -23.90625 Ont[26]= 4294 ' db= -23.671875 Ont[27]= 4412 ' db= -23.4375 Ont[28]= 4532 ' db= -23.203125 Ont[29]= 4656 ' db= -22.96875 Ont[30]= 4784 ' db= -22.734375 Ont[31]= 4915 ' db= -22.5 Ont[32]= 5049 ' db= -22.265625 Ont[33]= 5187 ' db= -22.03125 Ont[34]= 5329 ' db= -21.796875 Ont[35]= 5475 ' db= -21.5625 Ont[36]= 5624 ' db= -21.328125 Ont[37]= 5778 ' db= -21.09375 Ont[38]= 5936 ' db= -20.859375 Ont[39]= 6099 ' db= -20.625 Ont[40]= 6265 ' db= -20.390625 Ont[41]= 6437 ' db= -20.15625 Ont[42]= 6613 ' db= -19.921875 Ont[43]= 6794 ' db= -19.6875 Ont[44]= 6979 ' db= -19.453125 Ont[45]= 7170 ' db= -19.21875 Ont[46]= 7366 ' db= -18.984375 Ont[47]= 7568 ' db= -18.75 Ont[48]= 7775 ' db= -18.515625 Ont[49]= 7988 ' db= -18.28125 Ont[50]= 8206 ' db= -18.046875 Ont[51]= 8431 ' db= -17.8125 Ont[52]= 8661 ' db= -17.578125 Ont[53]= 8898 ' db= -17.34375 Ont[54]= 9141 ' db= -17.109375 Ont[55]= 9391 ' db= -16.875 Ont[56]= 9648 ' db= -16.640625 Ont[57]= 9912 ' db= -16.40625 Ont[58]= 10183 ' db= -16.171875 Ont[59]= 10462 ' db= -15.9375 Ont[60]= 10748 ' db= -15.703125 Ont[61]= 11042 ' db= -15.46875 Ont[62]= 11344 ' db= -15.234375 Ont[63]= 11654 ' db= -15 Ont[64]= 11973 ' db= -14.765625 Ont[65]= 12300 ' db= -14.53125 Ont[66]= 12637 ' db= -14.296875 Ont[67]= 12982 ' db= -14.0625 Ont[68]= 13337 ' db= -13.828125 Ont[69]= 13702 ' db= -13.59375 Ont[70]= 14077 ' db= -13.359375 Ont[71]= 14462 ' db= -13.125 Ont[72]= 14858 ' db= -12.890625 Ont[73]= 15264 ' db= -12.65625 Ont[74]= 15681 ' db= -12.421875 Ont[75]= 16110 ' db= -12.1875 Ont[76]= 16551 ' db= -11.953125 Ont[77]= 17004 ' db= -11.71875 Ont[78]= 17469 ' db= -11.484375 Ont[79]= 17947 ' db= -11.25 Ont[80]= 18437 ' db= -11.015625 Ont[81]= 18942 ' db= -10.78125 Ont[82]= 19460 ' db= -10.546875 Ont[83]= 19992 ' db= -10.3125 Ont[84]= 20539 ' db= -10.078125 Ont[85]= 21100 ' db= -9.84375 Ont[86]= 21678 ' db= -9.609375 Ont[87]= 22270 ' db= -9.375 Ont[88]= 22880 ' db= -9.140625 Ont[89]= 23505 ' db= -8.90625 Ont[90]= 24148 ' db= -8.671875 Ont[91]= 24809 ' db= -8.4375 Ont[92]= 25487 ' db= -8.203125 Ont[93]= 26184 ' db= -7.96875 Ont[94]= 26901 ' db= -7.734375 Ont[95]= 27636 ' db= -7.5 Ont[96]= 28392 ' db= -7.265625 Ont[97]= 29169 ' db= -7.03125 Ont[98]= 29967 ' db= -6.796875 Ont[99]= 30786 ' db= -6.5625 Ont[100]= 31628 ' db= -6.328125 Ont[101]= 32493 ' db= -6.09375 Ont[102]= 33382 ' db= -5.859375 Ont[103]= 34295 ' db= -5.625 Ont[104]= 35233 ' db= -5.390625 Ont[105]= 36197 ' db= -5.15625 Ont[106]= 37187 ' db= -4.921875 Ont[107]= 38204 ' db= -4.6875 Ont[108]= 39249 ' db= -4.453125 Ont[109]= 40322 ' db= -4.21875 Ont[110]= 41425 ' db= -3.984375 Ont[111]= 42558 ' db= -3.75 Ont[112]= 43722 ' db= -3.515625 Ont[113]= 44918 ' db= -3.28125 Ont[114]= 46146 ' db= -3.046875 Ont[115]= 47408 ' db= -2.8125 Ont[116]= 48705 ' db= -2.578125 Ont[117]= 50037 ' db= -2.34375 Ont[118]= 51406 ' db= -2.109375 Ont[119]= 52812 ' db= -1.875 Ont[120]= 54256 ' db= -1.640625 Ont[121]= 55740 ' db= -1.40625 Ont[122]= 57265 ' db= -1.171875 Ont[123]= 58831 ' db= -.9375 Ont[124]= 60440 ' db= -.703125 Ont[125]= 62093 ' db= -.46875 Ont[126]= 63791 ' db= -.234375 Ont[127]= 65535 ' db= 0 If PWM_Range_Shift > 0 Then For i = 0 To 127 Ont[i] = Ont[i] >> PWM_Range_Shift Next i EndIf Return PWM_Lookup_Table_40dB: 'HybrLo volume logscales 40dB 'for 16bit PWM values met volledige uitsturing 'PTPER must be set to 2^16 -1 range. '------log-scale------ Ont[0]= 0 '679 ' db= -39.6875 Ont[1]= 704 ' db= -39.375 Ont[2]= 730 ' db= -39.0625 Ont[3]= 757 ' db= -38.75 Ont[4]= 785 ' db= -38.4375 Ont[5]= 813 ' db= -38.125 Ont[6]= 843 ' db= -37.8125 Ont[7]= 874 ' db= -37.5 Ont[8]= 906 ' db= -37.1875 Ont[9]= 939 ' db= -36.875 Ont[10]= 974 ' db= -36.5625 Ont[11]= 1009 ' db= -36.25 Ont[12]= 1046 ' db= -35.9375 Ont[13]= 1085 ' db= -35.625 Ont[14]= 1124 ' db= -35.3125 Ont[15]= 1165 ' db= -35 Ont[16]= 1208 ' db= -34.6875 Ont[17]= 1252 ' db= -34.375 Ont[18]= 1298 ' db= -34.0625 Ont[19]= 1346 ' db= -33.75 Ont[20]= 1395 ' db= -33.4375 Ont[21]= 1446 ' db= -33.125 Ont[22]= 1499 ' db= -32.8125 Ont[23]= 1554 ' db= -32.5 Ont[24]= 1611 ' db= -32.1875 Ont[25]= 1670 ' db= -31.875 Ont[26]= 1731 ' db= -31.5625 Ont[27]= 1795 ' db= -31.25 Ont[28]= 1860 ' db= -30.9375 Ont[29]= 1929 ' db= -30.625 Ont[30]= 1999 ' db= -30.3125 Ont[31]= 2072 ' db= -30 Ont[32]= 2148 ' db= -29.6875 Ont[33]= 2227 ' db= -29.375 Ont[34]= 2309 ' db= -29.0625 Ont[35]= 2393 ' db= -28.75 Ont[36]= 2481 ' db= -28.4375 Ont[37]= 2572 ' db= -28.125 Ont[38]= 2666 ' db= -27.8125 Ont[39]= 2764 ' db= -27.5 Ont[40]= 2865 ' db= -27.1875 Ont[41]= 2970 ' db= -26.875 Ont[42]= 3079 ' db= -26.5625 Ont[43]= 3191 ' db= -26.25 Ont[44]= 3308 ' db= -25.9375 Ont[45]= 3429 ' db= -25.625 Ont[46]= 3555 ' db= -25.3125 Ont[47]= 3685 ' db= -25 Ont[48]= 3820 ' db= -24.6875 Ont[49]= 3960 ' db= -24.375 Ont[50]= 4105 ' db= -24.0625 Ont[51]= 4256 ' db= -23.75 Ont[52]= 4412 ' db= -23.4375 Ont[53]= 4573 ' db= -23.125 Ont[54]= 4741 ' db= -22.8125 Ont[55]= 4915 ' db= -22.5 Ont[56]= 5095 ' db= -22.1875 Ont[57]= 5281 ' db= -21.875 Ont[58]= 5475 ' db= -21.5625 Ont[59]= 5675 ' db= -21.25 Ont[60]= 5883 ' db= -20.9375 Ont[61]= 6099 ' db= -20.625 Ont[62]= 6322 ' db= -20.3125 Ont[63]= 6554 ' db= -20 Ont[64]= 6794 ' db= -19.6875 Ont[65]= 7043 ' db= -19.375 Ont[66]= 7301 ' db= -19.0625 Ont[67]= 7568 ' db= -18.75 Ont[68]= 7845 ' db= -18.4375 Ont[69]= 8133 ' db= -18.125 Ont[70]= 8431 ' db= -17.8125 Ont[71]= 8739 ' db= -17.5 Ont[72]= 9060 ' db= -17.1875 Ont[73]= 9391 ' db= -16.875 Ont[74]= 9735 ' db= -16.5625 Ont[75]= 10092 ' db= -16.25 Ont[76]= 10462 ' db= -15.9375 Ont[77]= 10845 ' db= -15.625 Ont[78]= 11242 ' db= -15.3125 Ont[79]= 11654 ' db= -15 Ont[80]= 12081 ' db= -14.6875 Ont[81]= 12524 ' db= -14.375 Ont[82]= 12982 ' db= -14.0625 Ont[83]= 13458 ' db= -13.75 Ont[84]= 13951 ' db= -13.4375 Ont[85]= 14462 ' db= -13.125 Ont[86]= 14992 ' db= -12.8125 Ont[87]= 15541 ' db= -12.5 Ont[88]= 16110 ' db= -12.1875 Ont[89]= 16701 ' db= -11.875 Ont[90]= 17312 ' db= -11.5625 Ont[91]= 17947 ' db= -11.25 Ont[92]= 18604 ' db= -10.9375 Ont[93]= 19285 ' db= -10.625 Ont[94]= 19992 ' db= -10.3125 Ont[95]= 20724 ' db= -10 Ont[96]= 21483 ' db= -9.6875 Ont[97]= 22270 ' db= -9.375 Ont[98]= 23086 ' db= -9.0625 Ont[99]= 23932 ' db= -8.75 Ont[100]= 24809 ' db= -8.4375 Ont[101]= 25718 ' db= -8.125 Ont[102]= 26660 ' db= -7.8125 Ont[103]= 27636 ' db= -7.5 Ont[104]= 28649 ' db= -7.1875 Ont[105]= 29698 ' db= -6.875 Ont[106]= 30786 ' db= -6.5625 Ont[107]= 31914 ' db= -6.25 Ont[108]= 33083 ' db= -5.9375 Ont[109]= 34295 ' db= -5.625 Ont[110]= 35551 ' db= -5.3125 Ont[111]= 36854 ' db= -5 Ont[112]= 38204 ' db= -4.6875 Ont[113]= 39603 ' db= -4.375 Ont[114]= 41054 ' db= -4.0625 Ont[115]= 42558 ' db= -3.75 Ont[116]= 44117 ' db= -3.4375 Ont[117]= 45733 ' db= -3.125 Ont[118]= 47408 ' db= -2.8125 Ont[119]= 49145 ' db= -2.5 Ont[120]= 50945 ' db= -2.1875 Ont[121]= 52812 ' db= -1.875 Ont[122]= 54746 ' db= -1.5625 Ont[123]= 56752 ' db= -1.25 Ont[124]= 58831 ' db= -.9375 Ont[125]= 60986 ' db= -.625 Ont[126]= 63220 ' db= -.3125 Ont[127]= 65535 ' db= 0 If PWM_Range_Shift > 0 Then For i = 0 To 127 Ont[i] = Ont[i] >> PWM_Range_Shift Next i EndIf Return PWM_Lookup_Table_50db: 'HybrLo volume scales 50dB 'for 16 bit PWM values '------log-scale------ Ont[0]= 0 '217 ' db= -49.609375 Ont[1]= 227 ' db= -49.21875 Ont[2]= 237 ' db= -48.828125 Ont[3]= 248 ' db= -48.4375 Ont[4]= 259 ' db= -48.046875 Ont[5]= 271 ' db= -47.65625 Ont[6]= 284 ' db= -47.265625 Ont[7]= 297 ' db= -46.875 Ont[8]= 311 ' db= -46.484375 Ont[9]= 325 ' db= -46.09375 Ont[10]= 340 ' db= -45.703125 Ont[11]= 356 ' db= -45.3125 Ont[12]= 372 ' db= -44.921875 Ont[13]= 389 ' db= -44.53125 Ont[14]= 407 ' db= -44.140625 Ont[15]= 426 ' db= -43.75 Ont[16]= 445 ' db= -43.359375 Ont[17]= 466 ' db= -42.96875 Ont[18]= 487 ' db= -42.578125 Ont[19]= 509 ' db= -42.1875 Ont[20]= 533 ' db= -41.796875 Ont[21]= 557 ' db= -41.40625 Ont[22]= 583 ' db= -41.015625 Ont[23]= 610 ' db= -40.625 Ont[24]= 638 ' db= -40.234375 Ont[25]= 667 ' db= -39.84375 Ont[26]= 698 ' db= -39.453125 Ont[27]= 730 ' db= -39.0625 Ont[28]= 764 ' db= -38.671875 Ont[29]= 799 ' db= -38.28125 Ont[30]= 836 ' db= -37.890625 Ont[31]= 874 ' db= -37.5 Ont[32]= 914 ' db= -37.109375 Ont[33]= 956 ' db= -36.71875 Ont[34]= 1000 ' db= -36.328125 Ont[35]= 1046 ' db= -35.9375 Ont[36]= 1094 ' db= -35.546875 Ont[37]= 1145 ' db= -35.15625 Ont[38]= 1197 ' db= -34.765625 Ont[39]= 1252 ' db= -34.375 Ont[40]= 1310 ' db= -33.984375 Ont[41]= 1370 ' db= -33.59375 Ont[42]= 1433 ' db= -33.203125 Ont[43]= 1499 ' db= -32.8125 Ont[44]= 1568 ' db= -32.421875 Ont[45]= 1640 ' db= -32.03125 Ont[46]= 1716 ' db= -31.640625 Ont[47]= 1795 ' db= -31.25 Ont[48]= 1877 ' db= -30.859375 Ont[49]= 1964 ' db= -30.46875 Ont[50]= 2054 ' db= -30.078125 Ont[51]= 2148 ' db= -29.6875 Ont[52]= 2247 ' db= -29.296875 Ont[53]= 2351 ' db= -28.90625 Ont[54]= 2459 ' db= -28.515625 Ont[55]= 2572 ' db= -28.125 Ont[56]= 2690 ' db= -27.734375 Ont[57]= 2814 ' db= -27.34375 Ont[58]= 2943 ' db= -26.953125 Ont[59]= 3079 ' db= -26.5625 Ont[60]= 3220 ' db= -26.171875 Ont[61]= 3368 ' db= -25.78125 Ont[62]= 3523 ' db= -25.390625 Ont[63]= 3685 ' db= -25 Ont[64]= 3855 ' db= -24.609375 Ont[65]= 4032 ' db= -24.21875 Ont[66]= 4218 ' db= -23.828125 Ont[67]= 4412 ' db= -23.4375 Ont[68]= 4615 ' db= -23.046875 Ont[69]= 4827 ' db= -22.65625 Ont[70]= 5049 ' db= -22.265625 Ont[71]= 5281 ' db= -21.875 Ont[72]= 5524 ' db= -21.484375 Ont[73]= 5778 ' db= -21.09375 Ont[74]= 6044 ' db= -20.703125 Ont[75]= 6322 ' db= -20.3125 Ont[76]= 6613 ' db= -19.921875 Ont[77]= 6917 ' db= -19.53125 Ont[78]= 7235 ' db= -19.140625 Ont[79]= 7568 ' db= -18.75 Ont[80]= 7916 ' db= -18.359375 Ont[81]= 8280 ' db= -17.96875 Ont[82]= 8661 ' db= -17.578125 Ont[83]= 9060 ' db= -17.1875 Ont[84]= 9476 ' db= -16.796875 Ont[85]= 9912 ' db= -16.40625 Ont[86]= 10368 ' db= -16.015625 Ont[87]= 10845 ' db= -15.625 Ont[88]= 11344 ' db= -15.234375 Ont[89]= 11866 ' db= -14.84375 Ont[90]= 12411 ' db= -14.453125 Ont[91]= 12982 ' db= -14.0625 Ont[92]= 13580 ' db= -13.671875 Ont[93]= 14204 ' db= -13.28125 Ont[94]= 14858 ' db= -12.890625 Ont[95]= 15541 ' db= -12.5 Ont[96]= 16256 ' db= -12.109375 Ont[97]= 17004 ' db= -11.71875 Ont[98]= 17786 ' db= -11.328125 Ont[99]= 18604 ' db= -10.9375 Ont[100]= 19460 ' db= -10.546875 Ont[101]= 20355 ' db= -10.15625 Ont[102]= 21291 ' db= -9.765625 Ont[103]= 22270 ' db= -9.375 Ont[104]= 23295 ' db= -8.984375 Ont[105]= 24366 ' db= -8.59375 Ont[106]= 25487 ' db= -8.203125 Ont[107]= 26660 ' db= -7.8125 Ont[108]= 27886 ' db= -7.421875 Ont[109]= 29169 ' db= -7.03125 Ont[110]= 30510 ' db= -6.640625 Ont[111]= 31914 ' db= -6.25 Ont[112]= 33382 ' db= -5.859375 Ont[113]= 34917 ' db= -5.46875 Ont[114]= 36524 ' db= -5.078125 Ont[115]= 38204 ' db= -4.6875 Ont[116]= 39961 ' db= -4.296875 Ont[117]= 41799 ' db= -3.90625 Ont[118]= 43722 ' db= -3.515625 Ont[119]= 45733 ' db= -3.125 Ont[120]= 47837 ' db= -2.734375 Ont[121]= 50037 ' db= -2.34375 Ont[122]= 52339 ' db= -1.953125 Ont[123]= 54746 ' db= -1.5625 Ont[124]= 57265 ' db= -1.171875 Ont[125]= 59899 ' db= -.78125 Ont[126]= 62654 ' db= -.390625 Ont[127]= 65535 ' db= 0 If PWM_Range_Shift > 0 Then For i = 0 To 127 Ont[i] = Ont[i] >> PWM_Range_Shift Next i EndIf Return PWM_Lookup_Table_60dB: 'HybrLo volume scales 60dB 'for 16 bit PWM values '-----log-scale------- Ont[0]= 0 '69 ' db= -59.53125 Ont[1]= 73 ' db= -59.0625 Ont[2]= 77 ' db= -58.59375 Ont[3]= 81 ' db= -58.125 Ont[4]= 86 ' db= -57.65625 Ont[5]= 91 ' db= -57.1875 Ont[6]= 96 ' db= -56.71875 Ont[7]= 101 ' db= -56.25 Ont[8]= 107 ' db= -55.78125 Ont[9]= 112 ' db= -55.3125 Ont[10]= 119 ' db= -54.84375 Ont[11]= 125 ' db= -54.375 Ont[12]= 132 ' db= -53.90625 Ont[13]= 140 ' db= -53.4375 Ont[14]= 147 ' db= -52.96875 Ont[15]= 155 ' db= -52.5 Ont[16]= 164 ' db= -52.03125 Ont[17]= 173 ' db= -51.5625 Ont[18]= 183 ' db= -51.09375 Ont[19]= 193 ' db= -50.625 Ont[20]= 204 ' db= -50.15625 Ont[21]= 215 ' db= -49.6875 Ont[22]= 227 ' db= -49.21875 Ont[23]= 239 ' db= -48.75 Ont[24]= 253 ' db= -48.28125 Ont[25]= 267 ' db= -47.8125 Ont[26]= 281 ' db= -47.34375 Ont[27]= 297 ' db= -46.875 Ont[28]= 313 ' db= -46.40625 Ont[29]= 331 ' db= -45.9375 Ont[30]= 349 ' db= -45.46875 Ont[31]= 369 ' db= -45 Ont[32]= 389 ' db= -44.53125 Ont[33]= 411 ' db= -44.0625 Ont[34]= 433 ' db= -43.59375 Ont[35]= 457 ' db= -43.125 Ont[36]= 483 ' db= -42.65625 Ont[37]= 509 ' db= -42.1875 Ont[38]= 538 ' db= -41.71875 Ont[39]= 568 ' db= -41.25 Ont[40]= 599 ' db= -40.78125 Ont[41]= 632 ' db= -40.3125 Ont[42]= 667 ' db= -39.84375 Ont[43]= 704 ' db= -39.375 Ont[44]= 743 ' db= -38.90625 Ont[45]= 785 ' db= -38.4375 Ont[46]= 828 ' db= -37.96875 Ont[47]= 874 ' db= -37.5 Ont[48]= 922 ' db= -37.03125 Ont[49]= 974 ' db= -36.5625 Ont[50]= 1028 ' db= -36.09375 Ont[51]= 1085 ' db= -35.625 Ont[52]= 1145 ' db= -35.15625 Ont[53]= 1208 ' db= -34.6875 Ont[54]= 1275 ' db= -34.21875 Ont[55]= 1346 ' db= -33.75 Ont[56]= 1420 ' db= -33.28125 Ont[57]= 1499 ' db= -32.8125 Ont[58]= 1582 ' db= -32.34375 Ont[59]= 1670 ' db= -31.875 Ont[60]= 1763 ' db= -31.40625 Ont[61]= 1860 ' db= -30.9375 Ont[62]= 1964 ' db= -30.46875 Ont[63]= 2072 ' db= -30 Ont[64]= 2187 ' db= -29.53125 Ont[65]= 2309 ' db= -29.0625 Ont[66]= 2437 ' db= -28.59375 Ont[67]= 2572 ' db= -28.125 Ont[68]= 2714 ' db= -27.65625 Ont[69]= 2865 ' db= -27.1875 Ont[70]= 3024 ' db= -26.71875 Ont[71]= 3191 ' db= -26.25 Ont[72]= 3368 ' db= -25.78125 Ont[73]= 3555 ' db= -25.3125 Ont[74]= 3752 ' db= -24.84375 Ont[75]= 3960 ' db= -24.375 Ont[76]= 4180 ' db= -23.90625 Ont[77]= 4412 ' db= -23.4375 Ont[78]= 4656 ' db= -22.96875 Ont[79]= 4915 ' db= -22.5 Ont[80]= 5187 ' db= -22.03125 Ont[81]= 5475 ' db= -21.5625 Ont[82]= 5778 ' db= -21.09375 Ont[83]= 6099 ' db= -20.625 Ont[84]= 6437 ' db= -20.15625 Ont[85]= 6794 ' db= -19.6875 Ont[86]= 7170 ' db= -19.21875 Ont[87]= 7568 ' db= -18.75 Ont[88]= 7988 ' db= -18.28125 Ont[89]= 8431 ' db= -17.8125 Ont[90]= 8898 ' db= -17.34375 Ont[91]= 9391 ' db= -16.875 Ont[92]= 9912 ' db= -16.40625 Ont[93]= 10462 ' db= -15.9375 Ont[94]= 11042 ' db= -15.46875 Ont[95]= 11654 ' db= -15 Ont[96]= 12300 ' db= -14.53125 Ont[97]= 12982 ' db= -14.0625 Ont[98]= 13702 ' db= -13.59375 Ont[99]= 14462 ' db= -13.125 Ont[100]= 15264 ' db= -12.65625 Ont[101]= 16110 ' db= -12.1875 Ont[102]= 17004 ' db= -11.71875 Ont[103]= 17947 ' db= -11.25 Ont[104]= 18942 ' db= -10.78125 Ont[105]= 19992 ' db= -10.3125 Ont[106]= 21100 ' db= -9.84375 Ont[107]= 22270 ' db= -9.375 Ont[108]= 23505 ' db= -8.90625 Ont[109]= 24809 ' db= -8.4375 Ont[110]= 26184 ' db= -7.96875 Ont[111]= 27636 ' db= -7.5 Ont[112]= 29169 ' db= -7.03125 Ont[113]= 30786 ' db= -6.5625 Ont[114]= 32493 ' db= -6.09375 Ont[115]= 34295 ' db= -5.625 Ont[116]= 36197 ' db= -5.15625 Ont[117]= 38204 ' db= -4.6875 Ont[118]= 40322 ' db= -4.21875 Ont[119]= 42558 ' db= -3.75 Ont[120]= 44918 ' db= -3.28125 Ont[121]= 47408 ' db= -2.8125 Ont[122]= 50037 ' db= -2.34375 Ont[123]= 52812 ' db= -1.875 Ont[124]= 55740 ' db= -1.40625 Ont[125]= 58831 ' db= -.9375 Ont[126]= 62093 ' db= -.46875 Ont[127]= 65535 ' db= 0 If PWM_Range_Shift > 0 Then For i = 0 To 127 Ont[i] = Ont[i] >> PWM_Range_Shift Next i EndIf Return '[EOF]