PIC Mapping for midi to LPT decoder for musical robots using Intel 8254 Timer chips: ************************************************************************************ last update: 30.01.2005 Workout for Default midi channel (set with DIP switch)= 14 ( = binary 1110) The circuit details are published on the page on the Logos website. data-port: RB0-RB7 Port B van de PIC, alle bits geflipt: RB7 ==> D0 pic pin 28 RB6 ==> D1 pic pin 27 RB5 ==> D2 pic pin 26 RB4 ==> D3 pic pin 25 RB3 ==> D4 pic pin 24 RB2 ==> D5 pic pin 23 RB1 ==> D6 pic pin 22 RB0 ==> D7 pic pin 21 adres-bus using port A, bits 0-5 Port A van de PIC: RA0 = bit 0 van Reg pic pin 2 RA1 = bit 1 van Reg pic pin 3 RA2 = bit 2 van Reg pic pin 4 RA3 = nc pic pin 5 RA4 = channel select dil switch bit 0 pic pin 6 bit0 RA5 = channel select DIL switch bit 1 pic pin 7 bit1 Port C van de PIC: RC0 = Timer 1 output. Test LED op PIC board (zoals op het board) LED via 1k2 naar GND. pic pin 11 RC1 = nc pic pin 12 RC2 = nc pic pin 13 RC3 = strobe bit (high at rest) pic pin 14 RC4 = channel select DIL switch bit2 pic pin 15 bit 2 RC5 = channel select DIL switch bit3 pic pin 16 bit 3 RC6 = serial output MIDI for debug pic pin 17 RC7 = serial input for MIDI data pic pin 18 (zoals op alle boards) GROUND: pic pin 19 pic pin 8 POSITIVE SUPPLY: 5V dc pic pin 20 Note1: we connect RA4, RA5, RC4, RC5 to a DIL switch for setting the midi-channel (0-F) (read only on startup or after PIC reset). Note2: it is essential that all data on the ports be stable before the strobe goes low. At rest, RA3 should always be high. Strobe duration must be 1 microsecond. Software implementation: ' constants: strobe = RC3, at rest should always be high. dport = RB7-RB0 (8 bits) aport = RA0-RA2 ( 3bits) (RA3 can be kept always low, such that we can always send a nibble) reg(0) => RA0 = 1, RA1 = 0, RA2 = 1 (dec. 5) reg(1) => RA0 = 0, RA1 = 0, RA2 = 1 (dec. 4) reg(2) => RA0 = 1, RA1 = 1, RA2 = 1 (dec. 7) reg(3) => RA0 = 0, RA1 = 1, RA2 = 1 (dec. 6) reg(4) => RA0 = 1, RA1 = 0, RA2 = 0 (dec. 1) reg(5) => RA0 = 0, RA1 = 0, RA2 = 0 (dec. 0) reg(6) => RA0 = 1, RA1 = 1, RA2 = 0 (dec. 3) reg(7) => RA0 = 0, RA1 = 1, RA2 = 0 (dec. 2) global variables: midichannel as byte ' procedure prototypes: Dripper_Initialize () VOID local n as byte ' should be called on startup CALL Dripper_Stop ' make sure power is OFF for n = 0 to 47 ' 11 is the note limit, but we go up to 47, for expansion boards CALL Dripper_NoteOff n, 20 ' zie proc. - this will be inaudible since we have no power yet next n CALL Dripper_Read_Port ' only read after a reset of the PIC CALL Dripper_Start ' autostart end function Dripper_Read_Port () VOID IF RA4 = 1 then bit set (midichannel, 0) else bit reset (midichannel, 0) IF RA5 = 1 then bit set (midichannel, 1) else bit reset (midichannel, 1) IF RC4 = 1 then bit set (midichannel, 2) else bit reset (midichannel, 2) IF RC5 = 1 then bit set (midichannel, 3) else bit reset (midichannel, 3) end function Dripper_Start () VOID ' sends pincode to board: (switch on the high power supply) ' this proc. should be called on reception of midi controller 66 with param = %true out dport, 239 ' pincode number out aport, reg(2) strobe ' (RC3 high to low and back to high for 1 microsecond) end function Dripper_Stop () VOID ' sends inverted pincode to board:(high power supply switched off ' not implemented on Vibi hardware yet out dport, 17 ' inverted pincode out aport, reg(2) ' port nr.3 - ext1port strobe '(RC3 high to low and back to high for 1 microsecond) end function Dripper_NoteOff (byval note as byte) VOID local cw as word if note > 47 then exit function cw = note mod 3 shift left cw, 6 cw = cw OR &B00010010 out aport, reg(1) out dport, 3 strobe out aport, reg(0 out dport, cw strobe out aport, reg(5) out dport, note \ 3 ' integer divide = chip number strobe out aport, reg(7) strobe end function Dripper_Puls (n as byte, velo as byte) VOID ' this is the 8 bit msb only code for the timer chips local cw as dword local wvelo as dword if velo = 0 then exit function if note > 47 the exit function cw = n MOD 3 ' control word , here 0,1,2 shift left cw, 6 ' put bits in the right place for the timer chip: D7 en D6 = select timer bit set cw,5 ' set bit 5, so be use msb only. (setting bit 4 would be lsb only) ' velo: ' in 256 microsecond increments ' thus the range is 0.256ms to 32 ms for 1-127 velo. out aport, reg(1) ' 2 bitlines velodatabus out dport, 3 ' set both lines high, write a command to the 82C54 strobe out aport, reg(0) ' databus 8 bit out dport, cw ' write program byte to the bus strobe out aport, reg(5) ' cause strobe on the 74154's out dport, note \ 3 ' chip number strobe out aport, reg(7) ' strobe ' now send the required data to the timer: out aport, reg(1) out dport, note MOD 3 ' 0=timer0 1=timer1 2=timer2 3=control strobe out dport, note \ 3 ' prepare chip selector out aport, reg(5) strobe ' send 1 byte of timer data out aport, reg(0) out dport, velo strobe out aport, reg(7) ' generate a strobe strobe ' now the counter should be counting... end Dripper_Puls_16bitcoding (note, velo) VOID local wvelo as dword local cw as dword ' this did not work on the wintel platform... if isfalse velo then exit function if note > 47 then exit function ' min and max. range to be checked again! (this is copied from vibi coding) wvelo = 3584 + (velo * 100) ' lineair in 100microsec. stapjes 3584 tot 16284 cw = note MOD 3 shift left cw, 6 bit set cw, 4 bit set cw, 5 out aport, reg(1) out dport, 3 ' command strobe out aport, reg(0) out dport, cw strobe out aport, reg(5) out dport, note \ 3 ' chip number - integer divide strobe out aport, reg(7) strobe out aport, reg(1) out dport, note MOD 3 strobe out aport, reg(5) out dport, note \ 3 strobe ' now send lsb: out aport, reg(0) out dport, LOBYT(wvelo) strobe out aport, reg(7) strobe ' then msb: out aport, reg(0) out dport, HIBYT(wvelo) strobe out aport, reg(7) strobe ' lsb-msb send, timer should be counting... end function FUNCTION Dripper_Midi_Input () VOID if statusbyte = controller then select case controller case 66 IF value then CALL Dripper_On ELSE CALL Dripper_Off END IF case 127 ' reset PIC, reread receive channel end select end if if statusbyte = note-on then select case note case < 48 select case velo case %False ' do nothing case else CALL Dripper_Puls noot, velo 'if working, replace with call to 16bit proc. end select end function ------------------------------------------------------------------------------------- Midi implementation: should listen to Note On commands for notes 0-47 listens to following controllers: 66 ' power ON 127 ' pic reset Dripper should listen to the channel set with the dip switches (0-15). The normal channel-setting for Dripper is 14. The pincode command can be implemented as a binary midi controller >= 66 (on/off). The user should send this controller in order to enable Dripper.