PIC Mapping for midi to LPT decoder for musical robots using Intel 8254 Timer chips: ************************************************************************************ last update: 02.02.2005 with 16 bit timer programming and velo rescaling. Workout for Default midi channel (set with DIP switch)= 15 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 het 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, RC3 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 variable: midichannel as byte ' procedure prototypes: Tubi_Initialize local n as byte ' should be called on startup CALL Tubi_Stop ' make sure power is OFF for n = 24 to 109 CALL Tubi_Beat n, 20 ' zie proc. - this will be inaudible since we have no power yet next n CALL Tubi_Read_Port ' only read after a reset of the PIC - to do end Tubi_Read_Port 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 Tubi_Start ' 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, 233 ' pincode number out aport, reg(2) out dport, 233 ' only for stabilisation of data on bus, mayber not required with pic's... strobe (RC3 high to low and back to high for 1 microsecond) end Tubi_Stop ' sends inverted pincode to board:(high power supply switched off) out dport, 22 ' inverted pincode out aport, reg(2) ' port nr.3 - ext1port out dport, 22 ' redundant glitch avoidance strobe '(RC3 high to low and back to high for 1 microsecond) end Tubi_Beat (note as byte, velo as byte) ' notes 24-60 = quartertones ' notes 72-108 = normal pitches ' code modified for 16 bit timing 30.01.2005 ' lsb-msb order checked with data sheet! local regselect as dword local cw as dword local wvelo as word if velo = 0 then exit function if note = 81 then note = 117 ' patch caused by a hardware fault. if note = 60 then note = 109 ' hoogste kwarttoon anders geschakeld. if note < 24 then exit function if note > 119 then exit function if note < 61 then ' quartertones 24-61 regselect = 5 note = note - 24 ' so we have 0 - 35 else ' normal notes if note > 71 then note = note - 72 ' so we now have 0-36 regselect = 4 else exit function end if end if 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,4 ' set bit 4, so we enable 16 bit timing bit set cw,5 ' set bit 5, so we also use msb (setting bit 4 is lsb) ' velo, if 7 bit: ' in 256 microsecond increments ' thus the range is 0.256ms to 32 ms for 1-127 velo. ' leading to a pretty bad resolution ' better scaling: 4ms to 16ms - 30.01.2005 'wvelo = 3582 + (velo * velo) ' 3584 to 19713 microseconds, quadratic ' changed to: wvelo = 3582 + (velo * 64) + (velo ^2 / 2) ' lin-log scale. ' if multiply is hard on PIC-level, we can also do ' wvelo = velo ' SHIFT LEFT (wvelo, 6) ' wvelo = 3584 + wvelo ' 3648 to 11712 microseconds ' but now we should use 16-bit timing 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(regselect) ' cause strobe on the 74154's out dport, note \ 3 ' chip number strobe out aport, reg(regselect +2) ' strobe ' now send the required 2 byte 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(regselect) strobe ' send lsb byte of timer data out aport, reg(0) out dport, lobyt (wvelo) strobe out aport, reg(regselect+2) ' generate a strobe strobe out aport, reg(0) ' send msb of timer data out dport, hibyt (wvelo) strobe out aport, reg(regselect+2) ' generate strobe strobe ' now the counter should be counting... end Midi implementation: Tubi should listen to Note On + Velo commands for notes 24 - 119 on the channel set with the dip switches (0-15). The normal channel-setting for Tubi is 15. The pincode command can be implemented as a binary midi controller >= 66 (on/off). The user should send this controller in order to enable tubi.