'**************************************************************** '* Name : Digit1A.bas * '* Author : Godfried-Willem RAES * '* Notice : Copyleft (c) 2014 Logosoft Public Domain * '* Date : 17.05.2014 * '* Version : 1.5 * '* Notes : p * '**************************************************************** '03.05.2014: PIC: 18F2525 On quad display board ' This code is a simple state machine. ' Compiler problem: no asm produced with Proton compiler... ' the fault is not in the IRQ include, as this works and compiles ok ' when combined with the snar_hub source code. ' After many hours bug found: the compiler refuses simple names in defines. ' following defines made the compiler refuse to do its work: ' $define a PORTC.4 ' $define b PORTC.3 ' $define c PORTB.0 ' $define d PORTB.1 ' $define e PORTB.2 ' $define f PORTB.3 ' $define g PORTB.4 ' After the subsitutions with aseg... it worked fine. ' 04.05.2014: Considering to implement a complete character set as well, ASCII based. ' Prog. change implemented: this now causes a second main loop to be performed. ' 05.05.2014: Green midi activity LED added. ' GMT test code added to GMT (g_tools) ' Decimal counter with external clock implemented. ' 06.05.2014: seconds counter and stopwatch implemented. ' 07.05.2014: testing... ' Loop , programma 0 o.k. , dec. and hexadecimal ' Loop2, ascii mode - u fout ' everything seems to work fine now. ' 08.05.2014: Some details in the ascii character set improved. ' 09.05.2014: q character changed in ascii mode. Special signs implemented. ' Could we implement an event counter with a preset possibility? ' Could be implement a countdown counter? ' Overflow bit added in the improved design. ' We could add a beep as well. (asc 7) ' 14.05.2014: Analog display mode added. ' To be tested. (prog. 5) ' 16.05.2014: program is now already 6234 bytes long! ' 17.05.2014: Further debug. Prog.change 5 not working..., causes infinite loop. ' 31.07.2014: Specific for board A now. Include "18F2525.inc" 'Include "18F2520.inc" 'also possible. (40MHz) ' Mapping for pin outputs and inputs: 7-segment display $define aseg PORTC.4 $define bseg PORTC.3 $define cseg PORTB.0 $define dseg PORTB.1 $define eseg PORTB.2 $define fseg PORTB.3 $define gseg PORTB.4 $define dot PORTC.5 $define beep PORTC.2 ' can be used for PWM ' $define leftdot PORTC.1 ' check with hardware, only for noot1 'red LED for debug: $define Debug_Led PORTA.0 ' for testing - red led - watchdog $define GreenLed PORTA.1 ' midi activity LED $define Carry PORTA.5 ' output - used as dot left for noot=1 $define CarryIn PORTA.4 ' input $define Ack PORTA.3 ' output $define AckIn PORTA.2 ' input $define LeftDot PORTA.2 ' output only on digit 1, noot1 ' configure the input and output pins: Clear SSPCON1.5 'RC3 must be available for I/O TRISA = %01010100 'bits set to 0 are output, 1 = input TRISB = %11100000 TRISC = %11000000 'RC1 en RC2 zijn pwm outputs and must be set to output ' 'RC6 en RC7 zijn USART I/O and must be set to input 'constant definitions: 'initialisations for the midi input parser: Symbol Midichannel = 0 Symbol Noot = 1 ' change this to 1,2,3,4 for other digits Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel ' 2 bytes follow 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 'application specific constants ' Setup the USART Declare Hserial_Baud = 31250 ' Set baud rate for the USART to MIDI specs. Declare Hserial_TXSTA = 0x24 ' instead of the normal 0x20 - ?? 0x24 Declare All_Digital = True ' the case here ' Declare Hserial_Clear = On ' should clear on errors. Bytes get lost of course... ' Create variables Dim Cnt As Dword System Dim CntHw As Cnt.Word1 'used in the timer0 interrupt, to create a 32 bit timer Dim CntLw As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H ' 'it makes Cntlw the low word of cnt ' 'We still have to copy the contents of Lw to Cnt Dim Tim3 As TMR3L.Word ' 16 bit counter for sampler - only used for stopwatch Dim Bytein As Byte System ' midi byte read from buffer Dim StBit As Bytein.7 ' highest bit of ByteIn Dim i As Byte System ' general purpose counter ' midi variables Dim statusbyte As Byte System Dim noteUit As Byte System ' note off + release value Dim release As Byte System Dim noteAan As Byte System ' note on + release value Dim velo As Byte System Dim Dotbit As velo.5 Dim notePres As Byte System ' note pressure + pressure value Dim pres As Byte System Dim Ctrl As Byte System ' continuous controller + value Dim value As Byte System Dim ProgStat As Byte System Dim prog As Byte System ' value for program change Dim VelFlags As Word System ' bits 0 - 15 used as flags for active timers Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 Dim teller As Word System ' used for event counter (Programma 2) Dim seccount As Word System ' counter used in the low interrupt Dim digit As Word System Dim digbyte As digit.Byte0 Dim klok As Byte System ' 64 ticks a second: low interrupt Dim Programma As Byte System Dim oldbyte As Byte System ' Dim st As Byte System ' Dim b1 As Byte System ' Dim b2 As Byte System '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler And buffer read subroutines into memory 'Include "ADC.inc" ' Load the ADC macros into the program - used in the IRQ include. Include "Display_Irq.inc" ' our own version for UART And Timer0/3 Interrupt 'Include "Timers.inc" ' required for velo support with timed pulses and periods. 'Include "DwordArrays.inc" ' support for dword arrays. 'make sure we initialize those pins on start up: 'fault?: there should be no executable statements outside the main program. Low aseg Low bseg Low cseg Low dseg Low eseg Low fseg Low gseg Low dot Low GreenLed Low Carry Low Ack Low Beep 'Low Debug_Led 'HPWM 2, 0, PWMfreq 'HPWM 1, 0, PWMfreq Clear CC66 Clear prog Clear Programma '----------------------------------------------------------------------------------------- ' Main program starts here MAIN: High Debug_Led DelayMS 50 ' wait for stability Low Debug_Led ' Clear VelFlags Init_Usart_Interrupt ' Initiate the USART serial buffer interrupt ' ' this procedure is in the irq file Clear_Serial_Buffer ' Clear the serial buffer and reset its pointers ' ' Configure Timer0 for: ' Clear TMR0L and TMR0H registers ' Interrupt on Timer0 overflow ' 16-bit operation ' Internal clock source 40MHz ' 1:256 Prescaler : thus 40MHz / 256 = 156.250kHz ' Opentimer0 (Timer_INT_On & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256) in macro file. Clear T1CON Clear IntConBits_T0IF ' clear interrupt flag Set INTCONBITS_T0IE ' enable interrupt on overflow T0CON = %10000111 ' bit 7 = enable/disable ' ' bit 6 = 1=8 bot, 0=16 bit ' ' bit 5 = 1 pin input, 0= Internal Clk0 ' ' bit 4 = HL or LH transition when bit5 =1 ' ' bit 3 = 1= bypass prescaler, 0= input from prescaler ' ' bit 2-0 = prescaler select: 111= 1:256 ' ' Setup the High priorities for the interrupts ' open and start timer3 for sampling: Clear T3CON Clear PIR2BITS_TMR3IF ' clear IRQ flag Set PIE2BITS_TMR3IE ' irq on Clear Tim3 ' Clear TMR3L And TMR3H registers Set RCONbits_IPEN ' Enable priority interrupts Clear IPR2bits_TMR3IP ' Set Timer3 as a low priority interrupt source ' we can also set T3Con in one instruction as: T3CON = %10110001 ' oef, now it works... ' ' bit 7 = 16 bit mode ' ' bit 6,3 = 0, 0 ' ' bit 5,4 = 1:8 prescale ' ' bit 2 = 0 ' ' bit 1 = 0 Internal clock = Fosc/4 ' ' bit 0 : 1= enable timer 3, 0= disable ' ' maximum count = 52.42ms, 1 tick =0.8uS, lowest freq.=19Hz LOOP: ' programma 0 Bytein = HRSIn ' Read data from the serial buffer, with no timeout If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo LOOP 'Check_Timers 'throw away... Else Clear statusbyte 'reset the status byte GoTo LOOP 'Check_Timers 'throw away End If 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 Clear GreenLed Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! Set GreenLed Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Set GreenLed Case Keypres_Status statusbyte = Bytein Set notePres '= 255 Set pres '= 255 Set GreenLed Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Case ProgChange_Status statusbyte = Bytein Set prog Set GreenLed End Select Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel Clear GreenLed GoTo LOOP 'Check_Timers 'disregard Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... If noteUit = Noot Then ' blank display Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg Clear dot Else Clear GreenLed EndIf Set noteUit '= 255 'reset EndIf 'GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If noteAan = Noot Then dot = Dotbit ' bit 5 of velo Clear Dotbit 'If Dotbit = 1 Then ' Set dot ' velo = velo - 32 ' clear dotbit 'Else ' Clear dot 'EndIf Select velo Case 0 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Clear gseg Case 1 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 2 Set aseg Set bseg Set gseg Set eseg Set dseg Clear cseg Clear fseg Case 3 Set aseg Set bseg Set cseg Set dseg Clear eseg Clear fseg Set gseg Case 4 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Set fseg Set gseg Case 5 Set aseg Clear bseg Set cseg Set dseg Clear eseg Set fseg Set gseg Case 6 Set aseg Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 7 Set aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 8 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 9 Set aseg Set bseg Set cseg Set dseg Clear eseg Set fseg Set gseg Case 10 ' hexadecimal extension Set aseg Set bseg Set cseg Clear dseg Set eseg Set fseg Set gseg Case 11 Clear aseg Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 12 Set aseg Clear bseg Clear cseg Set dseg Set eseg Set fseg Clear gseg Case 13 Clear aseg Set bseg Set cseg Set dseg Set eseg Clear fseg Set gseg Case 14 Set aseg Clear bseg Clear cseg Set dseg Set eseg Set fseg Set gseg Case 15 Set aseg Clear bseg Clear cseg Clear dseg Set eseg Set fseg Set gseg Case 16 ' blank display, leave dot. Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg End Select Else Clear GreenLED EndIf Set noteAan '= 255 'reset EndIf ' GoTo Check_Timers Case Keypres_Status 'use segment adressing of the display If notePres = 255 Then notePres = Bytein Else pres = Bytein If notePres = Noot Then gseg = pres.0 fseg = pres.1 eseg = pres.2 dseg = pres.3 cseg = pres.4 bseg = pres.5 aseg= pres.6 Else Clear GreenLED EndIf Set notePres EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf ' GoTo Check_Timers Case ProgChange_Status ' single byte follows! ProgStat = statusbyte If prog = 255 Then prog = Bytein GoSub ProgChange Select Programma Case 0 GoTo LOOP Case 1 GoTo LOOP2 Case 2 GoTo Teller_Loop Case 3 GoTo Second_Loop Case 4 GoTo Stopwatch_Loop Case 5 GoTo Ana5bitLoop End Select EndIf End Select EndIf 'Check_Timers: ' no timers in this code, it's a state machine. GoTo LOOP ' end of the main loop LOOP2: ' second loop for program change 1 - ASCII mode Bytein = HRSIn ' Read data from the serial buffer, with no timeout If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo LOOP2 Else Clear statusbyte 'reset the status byte GoTo LOOP2 End If 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 Clear GreenLed Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! Set GreenLed Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Set GreenLed Case Keypres_Status statusbyte = Bytein Set notePres '= 255 Set pres '= 255 Set GreenLed Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Set GreenLed Case ProgChange_Status statusbyte = Bytein Set prog Set GreenLed End Select Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel Clear GreenLed Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... If noteUit = Noot Then ' blank display Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg Clear dot Clear Beep Else Clear GreenLED EndIf Set noteUit '= 255 'reset EndIf Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If noteAan = Noot Then Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg Clear dot Clear Beep Select velo Case 7 Set Beep ' only connected for noot4 Case 39 ' apostroph Set bseg 'case 44 ' komma Case 45 Set gseg Case 46 ' punt Set dot Case 47 ' / Set bseg Set eseg Set gseg Case 48 ' 0 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg 'Clear gseg Case 49 'Clear aseg Set bseg Set cseg 'Clear dseg 'Clear eseg 'Clear fseg 'Clear gseg Case 50 Set aseg Set bseg Set gseg Set eseg Set dseg 'Clear cseg 'Clear fseg Case 51 Set aseg Set bseg Set cseg Set dseg 'Clear eseg 'Clear fseg Set gseg Case 52 'Clear aseg Set bseg Set cseg 'Clear dseg 'Clear eseg Set fseg Set gseg Case 53 Set aseg 'Clear bseg Set cseg Set dseg 'Clear eseg Set fseg Set gseg Case 54 Set aseg 'Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 55 Set aseg Set bseg Set cseg 'Clear dseg 'Clear eseg 'Clear fseg 'Clear gseg Case 56 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 57 Set aseg Set bseg Set cseg Set dseg 'Clear eseg Set fseg Set gseg Case 58 ' hexadecimal extension A Set aseg Set bseg Set cseg 'Clear dseg Set eseg Set fseg Set gseg Case 59 ' b 'Clear aseg 'Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 60 ' c Set aseg 'Clear bseg 'Clear cseg Set dseg Set eseg Set fseg 'Clear gseg Case 61 ' d 'Clear aseg Set bseg Set cseg Set dseg Set eseg 'Clear fseg Set gseg Case 62 ' E Set aseg 'Clear bseg 'Clear cseg Set dseg Set eseg Set fseg Set gseg Case 63 ' F Set aseg 'Clear bseg 'Clear cseg 'Clear dseg Set eseg Set fseg Set gseg ' case 85-90: ascii lookup ' Case 64 ' Clear aseg ' Clear bseg ' Clear cseg ' Clear dseg ' Clear eseg ' Clear fseg ' Clear gseg Case 65,97 ' "A", "a" Set aseg Set bseg Set cseg Set dseg Set eseg 'Clear fseg Set gseg Case 66,98 'Clear aseg 'Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 67,99 'Clear aseg 'Clear bseg 'Clear cseg Set dseg Set eseg 'Clear fseg Set gseg Case 68,100 ' d 'Clear aseg Set bseg Set cseg Set dseg Set eseg 'Clear fseg Set gseg Case 69,101 Set aseg 'Clear bseg 'Clear cseg Set dseg Set eseg Set fseg Set gseg Case 70,102 ' f Set aseg 'Clear bseg 'Clear cseg 'Clear dseg Set eseg Set fseg Set gseg Case 71, 103 ' "G", "g" Set aseg 'Clear bseg Set cseg Set dseg Set eseg Set fseg 'Clear gseg Case 72, 104 ' h 'Clear aseg 'Clear bseg Set cseg 'Clear dseg Set eseg Set fseg Set gseg Case 73, 105 ' kleine i 'Clear aseg 'Clear bseg Set cseg 'Clear dseg 'Clear eseg 'Clear fseg 'Clear gseg Case 74, 106 ' grote j 'Clear aseg Set bseg Set cseg Set dseg 'Clear eseg 'Clear fseg 'Clear gseg Case 75, 107 ' k 'Clear aseg 'Clear bseg 'Clear cseg 'Clear dseg Set eseg Set fseg Set gseg Case 76, 108 ' l 'Clear aseg 'Clear bseg 'Clear cseg Set dseg Set eseg Set fseg Clear gseg Case 77, 109 ' bizarre m Set aseg 'Clear bseg Set cseg 'Clear dseg Set eseg 'Clear fseg Set gseg Case 78, 110 ' n 'Clear aseg 'Clear bseg Set cseg 'Clear dseg Set eseg 'Clear fseg Set gseg Case 79,111 ' o 'Clear aseg 'Clear bseg Set cseg Set dseg Set eseg 'Clear fseg Set gseg Case 80,112 ' p Set aseg Set bseg 'Clear cseg 'Clear dseg Set eseg Set fseg Set gseg Case 81,113 ' Q, q Set aseg Set bseg Set cseg Set fseg Set gseg Case 82, 114 ' r 'Clear aseg 'Clear bseg 'Clear cseg 'Clear dseg Set eseg 'Clear fseg Set gseg Case 83,115 ' s Set aseg 'Clear bseg Set cseg Set dseg 'Clear eseg Set fseg 'Clear gseg Case 84,116 ' t 'Clear aseg 'Clear bseg 'Clear cseg Set dseg Set eseg Set fseg Set gseg Case 85, 117 'u 'Clear aseg 'Clear bseg Set cseg Set dseg Set eseg 'Clear fseg 'Clear gseg Case 86, 118 ' V 'Clear aseg Set bseg Set cseg 'Clear dseg Set eseg Set fseg 'Clear gseg Case 87, 119 ' w 'Clear aseg Set bseg 'Clear cseg Set dseg 'Clear eseg Set fseg Set gseg Case 88, 120 ' x three horizontal lines Set aseg 'Clear bseg 'Clear cseg Set dseg 'Clear eseg 'Clear fseg Set gseg Case 89, 121 'y 'Clear aseg Set bseg Set cseg Set dseg 'Clear eseg Set fseg Set gseg Case 90,122 ' z Set aseg Set bseg 'Clear cseg Set dseg Set eseg 'Clear fseg 'Clear gseg Case 92 Set cseg Set fseg Set gseg Case 93 Set aseg Set bseg Set cseg Set dseg Case 94 Set aseg Set bseg Set fseg Case 95 Set dseg Case 124 Set eseg Set fseg End Select Else Clear GreenLED EndIf Set noteAan '= 255 'reset EndIf Case Keypres_Status 'use segment adressing of the display If notePres = 255 Then notePres = Bytein Else pres = Bytein If notePres = Noot Then gseg = pres.0 fseg = pres.1 eseg = pres.2 dseg = pres.3 cseg = pres.4 bseg = pres.5 aseg = pres.6 Else Clear GreenLED EndIf Set notePres EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf Case ProgChange_Status If prog = 255 Then prog = Bytein ' now do the action... GoSub ProgChange Select Programma Case 0 GoTo LOOP Case 1 GoTo LOOP2 Case 2 GoTo Teller_Loop Case 3 GoTo Second_Loop Case 4 GoTo Stopwatch_Loop Case 5 GoTo Ana5bitLoop End Select EndIf End Select EndIf GoTo LOOP2 ' close the second loop Controller: Select Ctrl Case 26 ' we disregard the value! GoSub AllNotesOff If Programma = 2 Then Clear teller Case 27 ' we disregard the value! If Programma = 2 Then If Noot = 4 Then ' the other digits increment their 'teller' from the Carry flags. Inc teller End If EndIf Case 66 'on/off for the display If value = 0 Then Clear teller Clear PowerOn 'CC66.0 GoSub PowerDown Else Clear teller Set PowerOn 'CC66.0 EndIf Case 123 GoSub AllNotesOff End Select Clear GreenLED Set Ctrl '= 255 'mandatory reset Return ProgChange: Select prog Case 0 'Set statusbyte Set ProgStat Programma = prog Case 1 'Set statusbyte Set ProgStat Programma = prog Case 2 ' event counter with external (midi) clock increment ' this mode will start immediately on reception of the command ' it can be stopped by sending prog. change with value 0 ' incrementing the counter is done by sending controller 27 (any value) ' reset counter with controller 26 GoSub AllNotesOff ' clear display 'Set statusbyte Set ProgStat Clear teller Clear digit Programma = prog Case 3 ' timer with internal 1 second clock ' the counter will start on reception of the program change command GoSub AllNotesOff Set ProgStat Clear klok Clear seccount ' reset counter in low interrupt Clear digit Clear dot Programma = prog Case 4 ' stopwatch with start/stop over midi. Internal clock ' display should be MM:SS ' display 0 on startup: Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Clear gseg Clear Carry If Noot = 2 Then Set Dot Else Clear Dot EndIf Set ProgStat Clear klok Clear seccount Clear digit Programma = prog Case 5 'analog display - 5 bits (0-32) 'GoSub AllNotesOff Set ProgStat Clear klok Clear seccount ' reset counter in low interrupt Clear digit Clear dot Programma = prog End Select Set statusbyte Clear GreenLED Set prog ' added 17.05.2014 Return AllNotesOff: Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg Clear dot Clear Carry Clear Ack Clear teller Clear klok Clear seccount Clear Beep Return PowerDown: Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg Clear dot Clear GreenLed Clear Carry Clear Ack Clear Beep Return Teller_Loop: ' Counter with external increment command. ' the teller variable is incremented on reception of controller 27 Bytein = HRSIn ' Read data from the serial buffer, with no timeout If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo Teller_Loop 'Check_Tellers Else Clear statusbyte 'reset the status byte GoTo Teller_Loop 'Check_Tellers End If 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 Clear GreenLed Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! Set GreenLed Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Set GreenLed Case Keypres_Status statusbyte = Bytein Set notePres '= 255 Set pres '= 255 Set GreenLed Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Case ProgChange_Status statusbyte = Bytein Set prog Set GreenLed End Select Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel Clear GreenLed Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... Set noteUit '= 255 'reset Clear GreenLED EndIf Case NoteOn_Status ' could be implemented to set a preset value... If noteAan = 255 Then noteAan = Bytein Else velo = Bytein teller = velo // 10 ' this presets the teller variables for the digits Set noteAan '= 255 'reset Clear GreenLED EndIf Case Keypres_Status 'use segment adressing of the display - not implemented in this mode If notePres = 255 Then notePres = Bytein Else pres = Bytein Set notePres Clear GreenLED 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 ' single byte follows! ProgStat = statusbyte If prog = 255 Then prog = Bytein GoSub ProgChange Select Programma Case 0 GoTo LOOP Case 1 GoTo LOOP2 Case 2 GoTo Teller_Loop Case 3 GoTo Second_Loop Case 4 GoTo Stopwatch_Loop Case 5 GoTo Ana5bitLoop End Select EndIf End Select EndIf Check_Tellers: ' here we set the displays according to teller ' common for all displays: If AckIn = 1 Then Clear Carry Select Noot ' this is a constant ! Case 1 ' msb If CarryIn = 1 Then If Ack = 0 Then Inc teller Set Ack ' acknowledge to noot3 EndIf Else Clear Ack EndIf digbyte = teller // 10 ' this is the msb, so we do not need to send carry. ' however we can set the overflow bit on display version 2: If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then Set carry ' it will stay set, until we restart the counter EndIf oldbyte = digbyte EndIf Case 2, 3 If CarryIn = 1 Then If Ack = 0 Then Inc teller ' only incremented here for this noot Set Ack ' acknowledge to noot4 EndIf Else Clear Ack EndIf digbyte = teller // 10 If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then 'If Ackin = 0 Then Set carry 'End If EndIf EndIf oldbyte = digbyte EndIf Case 4 ' lsb digbyte = teller // 10 ' = teller MOD 10 If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then 'If AckIn = 0 Then ' will be set high by noot3 Set Carry ' make carry output high, such that teller for noot3 increments 'EndIf EndIf EndIf oldbyte = digbyte EndIf End Select Select digbyte Case 0 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Clear gseg Case 1 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 2 Set aseg Set bseg Set gseg Set eseg Set dseg Clear cseg Clear fseg Case 3 Set aseg Set bseg Set cseg Set dseg Clear eseg Clear fseg Set gseg Case 4 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Set fseg Set gseg Case 5 Set aseg Clear bseg Set cseg Set dseg Clear eseg Set fseg Set gseg Case 6 Set aseg Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 7 Set aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 8 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 9 Set aseg Set bseg Set cseg Set dseg Clear eseg Set fseg Set gseg End Select GoTo Teller_Loop Second_Loop: ' the seccount variable is incremented in the low interrupt for noot4 Bytein = HRSIn ' Read data from the serial buffer, with no timeout If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo Check_seconds Else Clear statusbyte 'reset the status byte GoTo Check_seconds End If 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 btg GreenLed Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! 'Set GreenLed Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 'Set GreenLed Case Keypres_Status statusbyte = Bytein Set notePres '= 255 Set pres '= 255 'Set GreenLed Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Case ProgChange_Status statusbyte = Bytein Set prog 'Set GreenLed End Select Else 'midi byte is 7 bits Select statusbyte Case <= Keypres_Status 'not handled here GoTo Check_seconds ' Clear GreenLed ' Case NoteOff_Status ' If noteUit = 255 Then ' noteUit = Bytein ' Else ' release = Bytein 'message complete, so we can do the action... ' Set noteUit '= 255 'reset ' clear GreenLED ' EndIf ' Case NoteOn_Status ' If noteAan = 255 Then ' noteAan = Bytein ' Else ' velo = Bytein ' Set noteAan '= 255 'reset ' Clear GreenLED ' EndIf ' Case Keypres_Status 'use segment adressing of the display - not implemented in this mode ' If notePres = 255 Then ' notePres = Bytein ' Else ' pres = Bytein ' Set notePres ' Clear GreenLED ' 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 ' single byte follows! ProgStat = statusbyte If prog = 255 Then prog = Bytein GoSub ProgChange Select Programma Case 0 GoTo LOOP Case 1 GoTo LOOP2 Case 2 GoTo Teller_Loop Case 3 GoTo Second_Loop Case 4 GoTo Stopwatch_Loop Case 5 GoTo Ana5bitLoop End Select EndIf End Select EndIf Check_seconds: ' here we set the displays according to seccount ' here we should use the Carry, Ack hardware to make sure the displays stay in sync. ' common for all displays: If AckIn = 1 Then Clear Carry Select Noot ' this is a constant ! Case 1 ' msb If CarryIn = 1 Then If Ack = 0 Then Inc teller Set Ack ' acknowledge to noot3 EndIf Else Clear Ack EndIf digbyte = teller // 10 ' this is the msb, so we do not need to send carry ' however we can set the overflow bit on display version 2: If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then Set carry ' it will stay set, until we restart the counter EndIf oldbyte = digbyte EndIf Case 2, 3 If CarryIn = 1 Then If Ack = 0 Then Inc teller ' only incremented here for this noot Set Ack ' acknowledge to noot4 EndIf Else Clear Ack EndIf digbyte = teller // 10 If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then 'If Ackin = 0 Then Set carry 'End If EndIf EndIf oldbyte = digbyte EndIf Case 4 ' lsb digbyte = seccount // 10 ' = teller MOD 10 If digbyte <> oldbyte Then If seccount > 0 Then If digbyte = 0 Then 'If AckIn = 0 Then ' will be set high by noot3 Set Carry ' make carry output high, such that teller for noot3 increments 'EndIf EndIf EndIf oldbyte = digbyte EndIf End Select Select digbyte Case 0 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Clear gseg Case 1 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 2 Set aseg Set bseg Set gseg Set eseg Set dseg Clear cseg Clear fseg Case 3 Set aseg Set bseg Set cseg Set dseg Clear eseg Clear fseg Set gseg Case 4 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Set fseg Set gseg Case 5 Set aseg Clear bseg Set cseg Set dseg Clear eseg Set fseg Set gseg Case 6 Set aseg Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 7 Set aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 8 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 9 Set aseg Set bseg Set cseg Set dseg Clear eseg Set fseg Set gseg End Select GoTo Second_Loop Stopwatch_Loop: ' the seccount variable is incremented in the low interrupt Bytein = HRSIn ' Read data from the serial buffer, with no timeout If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo Check_Stopwatch Else Clear statusbyte 'reset the status byte GoTo Check_Stopwatch End If 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 btg GreenLed Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! 'Set GreenLed Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 'Set GreenLed Case Keypres_Status statusbyte = Bytein Set notePres '= 255 Set pres '= 255 'Set GreenLed Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Case ProgChange_Status statusbyte = Bytein Set prog 'Set GreenLed End Select Else 'midi byte is 7 bits Select statusbyte Case <= Keypres_Status 'not a message for this channel GoTo Check_Stopwatch ' Clear GreenLed ' Case NoteOff_Status ' If noteUit = 255 Then ' noteUit = Bytein ' Else ' release = Bytein 'message complete, so we can do the action... ' Set noteUit '= 255 'reset ' Clear GreenLED ' EndIf ' Case NoteOn_Status ' If noteAan = 255 Then ' noteAan = Bytein ' Else ' velo = Bytein ' Set noteAan '= 255 'reset ' Clear GreenLED ' EndIf ' Case Keypres_Status 'use segment adressing of the display - not implemented in this mode ' If notePres = 255 Then ' notePres = Bytein ' Else ' pres = Bytein ' Set notePres ' Clear GreenLED ' 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 ' single byte follows! ProgStat = statusbyte If prog = 255 Then prog = Bytein GoSub ProgChange Select Programma Case 0 GoTo LOOP Case 1 GoTo LOOP2 Case 2 GoTo Teller_Loop Case 3 GoTo Second_Loop Case 4 GoTo Stopwatch_Loop Case 5 GoTo Ana5bitLoop End Select EndIf End Select EndIf Check_Stopwatch: ' here we set the displays according to teller ' here we should use the Carry, Ack hardware to make sure the displays stay in sync. ' common for all displays: If AckIn = 1 Then Clear Carry Select Noot ' this is a constant ! Case 1 ' msb If CarryIn = 1 Then If Ack = 0 Then Inc teller Set Ack ' acknowledge to noot2 EndIf Else Clear Ack EndIf digbyte = teller // 6 ' this is the msb, so we do not need to send carry ' however we can set the overflow bit on display version 2: If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then Set carry ' it will stay set, until we restart the counter EndIf oldbyte = digbyte EndIf Case 2 If CarryIn = 1 Then If Ack = 0 Then Inc teller ' only incremented here for this noot Set Ack ' acknowledge to noot3 EndIf Else Clear Ack EndIf digbyte = teller // 10 If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then 'If Ackin = 0 Then Set carry 'End If EndIf EndIf oldbyte = digbyte EndIf Case 3 If CarryIn = 1 Then If Ack = 0 Then Inc teller ' only incremented here for this noot Set Ack ' acknowledge to noot4 EndIf Else Clear Ack EndIf digbyte = teller // 6 If digbyte <> oldbyte Then If teller > 0 Then If digbyte = 0 Then 'If Ackin = 0 Then Set carry 'End If EndIf EndIf oldbyte = digbyte EndIf Case 4 ' lsb digbyte = seccount // 10 ' = teller MOD 10 If digbyte <> oldbyte Then If seccount > 0 Then If digbyte = 0 Then 'If AckIn = 0 Then ' will be set high by noot3 Set Carry ' make carry output high, such that teller for noot3 increments 'EndIf EndIf EndIf oldbyte = digbyte EndIf End Select Select digbyte Case 0 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Clear gseg Case 1 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 2 Set aseg Set bseg Set gseg Set eseg Set dseg Clear cseg Clear fseg Case 3 Set aseg Set bseg Set cseg Set dseg Clear eseg Clear fseg Set gseg Case 4 Clear aseg Set bseg Set cseg Clear dseg Clear eseg Set fseg Set gseg Case 5 Set aseg Clear bseg Set cseg Set dseg Clear eseg Set fseg Set gseg Case 6 Set aseg Clear bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 7 Set aseg Set bseg Set cseg Clear dseg Clear eseg Clear fseg Clear gseg Case 8 Set aseg Set bseg Set cseg Set dseg Set eseg Set fseg Set gseg Case 9 Set aseg Set bseg Set cseg Set dseg Clear eseg Set fseg Set gseg End Select GoTo Stopwatch_Loop Ana5bitLoop: Bytein = HRSIn ' Read data from the serial buffer, with no timeout If Bytein > ProgChange_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo Ana5bitLoop Else Clear statusbyte 'reset the status byte GoTo Ana5bitLoop End If 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 Clear GreenLed Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! Set GreenLed Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Set GreenLed Case Keypres_Status statusbyte = Bytein Set notePres '= 255 Set pres '= 255 Set GreenLed Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Case ProgChange_Status statusbyte = Bytein Set prog Set GreenLed End Select Else 'midi byte is 7 bits Select statusbyte 'Case 0 'not a message for this channel ' Clear GreenLed Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... ' If noteUit = Noot Then ' blank display ' Clear aseg ' Clear bseg ' Clear cseg ' Clear dseg ' Clear eseg ' Clear fseg ' Clear gseg ' Clear dot ' Clear Carry ' Else ' Clear GreenLed ' EndIf Set noteUit '= 255 'reset EndIf Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein 'If noteAan = Noot Then ' this would require us to send 4 note on commands... ' would be better to have it respond to any note 1-4. If noteAan < 5 Then Clear aseg Clear bseg Clear cseg Clear dseg Clear eseg Clear fseg Clear gseg Clear dot If Noot = 1 Then Low LeftDot 'Carry ' overflow LED on noot1 Select Noot Case 1 Select velo Case 0 'niks Case 1 High LeftDot 'Set Carry Case 2 High LeftDot 'Set Carry Set dseg Case 3 High LeftDot 'Set Carry Set eseg Case 4 High LeftDot 'Set Carry Set eseg Set gseg Case 5 High LeftDot 'Set Carry Set eseg Set fseg Case 6 High LeftDot 'Set Carry Set aseg Set eseg Set fseg Case 7 High LeftDot 'Set Carry Set aseg Set bseg Set eseg Set fseg Case 8 High LeftDot 'Set Carry Set aseg Set bseg Set cseg Set eseg Set fseg Case > 8 '9 High LeftDot 'Set Carry Set aseg Set bseg Set cseg Set eseg Set fseg Set dot ' seems not working End Select Case 2 Select velo Case 10 '11 Set dseg Case 11 '12 Set eseg Case 12 '13 Set eseg Set gseg Case 13 '14 Set eseg Set fseg Case 14 Set aseg Set eseg Set fseg Case 15 Set aseg Set bseg Set eseg Set fseg Case 16 Set aseg Set bseg Set cseg Set eseg Set fseg Case > 16 'Else ' >=18 Set aseg Set bseg Set cseg Set eseg Set fseg Set dot End Select Case 3 Select velo Case 18 Set dseg Case 19 Set eseg Case 20 Set eseg Set gseg Case 21 Set eseg Set fseg Case 22 Set aseg Set eseg Set fseg Case 23 Set aseg Set bseg Set eseg Set fseg Case 24 Set aseg Set bseg Set cseg Set eseg Set fseg Case > 24 'Else ' >=26 Set aseg Set bseg Set cseg Set eseg Set fseg Set dot End Select Case 4 Select velo Case 26 Set dseg Case 27 Set eseg Case 28 Set eseg Set gseg Case 29 Set eseg Set fseg Case 30 Set aseg Set eseg Set fseg Case 31 Set aseg Set bseg Set eseg Set fseg Case 32 Set aseg Set bseg Set cseg Set eseg Set fseg Case >32 Set aseg Set bseg Set cseg Set eseg Set fseg Set dot End Select End Select EndIf Set noteAan '= 255 'reset EndIf Case Keypres_Status 'use segment adressing of the display If notePres = 255 Then notePres = Bytein Else pres = Bytein Set notePres EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf Case ProgChange_Status ' single byte follows! ProgStat = statusbyte If prog = 255 Then prog = Bytein GoSub ProgChange Select Programma Case 0 If Noot = 1 Then Low LeftDot TRISA = %01010100 'bits set to 0 are output, 1 = input GoTo LOOP Case 1 If Noot = 1 Then Low LeftDot TRISA = %01010100 'bits set to 0 are output, 1 = input GoTo LOOP2 Case 2 If Noot = 1 Then Low LeftDot TRISA = %01010100 'bits set to 0 are output, 1 = input GoTo Teller_Loop Case 3 If Noot = 1 Then Low LeftDot TRISA = %01010100 'bits set to 0 are output, 1 = input GoTo Second_Loop Case 4 If Noot = 1 Then Low LeftDot TRISA = %01010100 'bits set to 0 are output, 1 = input GoTo Stopwatch_Loop Case 5 GoTo Ana5bitLoop End Select EndIf End Select EndIf GoTo Ana5bitLoop '[EOF]