Just a quick project to try out some new push solenoids...
Based on PIC16F688 and building on the MIDI input code used on my earlier POKEY project
include <system.h>
#include <memory.h>
#pragma DATA _CONFIG, _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
#pragma CLOCK_FREQ 8000000
typedef unsigned char byte;
// define the pins
//#define P_LED portc.0
// MIDI defs
#define MIDIMSG(b) ((b)>>4)
#define MIDICHAN(b) ((b)&0xf)
#define MIDIMSG_NOTEON 0x09
#define MIDIMSG_NOTEOFF 0x08
// MIDI message registers
byte runningStatus = 0;
int numParams = 0;
byte midiParams[2] = {0};
#define SZ_RXBUFFER 20
byte rxBuffer[SZ_RXBUFFER];
byte rxHead = 0;
byte rxTail = 0;
int tmr[4] = {0};
////////////////////////////////////////////////////////////
// INTERRUPT HANDLER CALLED WHEN CHARACTER RECEIVED AT
// SERIAL PORT
void interrupt( void )
{
// check if this is serial rx interrupt
if(pir1.5)
{
// get the byte
byte b = rcreg;
// calculate next buffer head
byte nextHead = (rxHead + 1);
if(nextHead >= SZ_RXBUFFER)
{
nextHead -= SZ_RXBUFFER;
}
// if buffer is not full
if(nextHead != rxTail)
{
// store the byte
rxBuffer[rxHead] = b;
rxHead = nextHead;
}
}
}
////////////////////////////////////////////////////////////
// INITIALISE SERIAL PORT FOR MIDI
void init_usart()
{
pir1.1 = 1; //TXIF
pir1.5 = 0; //RCIF
pie1.1 = 0; //TXIE no interrupts
pie1.5 = 1; //RCIE interrupt on receive
baudctl.4 = 0; // SCKP synchronous bit polarity
baudctl.3 = 1; // BRG16 enable 16 bit brg
baudctl.1 = 0; // WUE wake up enable off
baudctl.0 = 0; // ABDEN auto baud detect
txsta.6 = 0; // TX9 8 bit transmission
txsta.5 = 1; // TXEN transmit enable
txsta.4 = 0; // SYNC async mode
txsta.3 = 0; // SEDNB break character
txsta.2 = 0; // BRGH high baudrate
txsta.0 = 0; // TX9D bit 9
rcsta.7 = 1; // SPEN serial port enable
rcsta.6 = 0; // RX9 8 bit operation
rcsta.5 = 1; // SREN enable receiver
rcsta.4 = 1; // CREN continuous receive enable
spbrgh = 0; // brg high byte
spbrg = 15; // brg low byte (31250)
}
byte rxInc(byte *pbIndex)
{
// any data in the buffer?
if((*pbIndex) == rxHead)
return 0;
// move to next char
if(++(*pbIndex) >= SZ_RXBUFFER)
(*pbIndex) -= SZ_RXBUFFER;
return 1;
}
////////////////////////////////////////////////////////////
// RECEIVE MIDI MESSAGE
// Return the status byte or 0 if nothing complete received
// caller must check midiParams array for byte 1 and 2
byte receiveMessage()
{
// buffer overrun error?
if(rcsta.1)
{
rcsta.4 = 0;
rcsta.4 = 1;
}
// any data in the buffer?
if(rxHead == rxTail)
return 0;
// peek at next char in buffer
byte rxPos = rxTail;
byte q = rxBuffer[rxPos];
// is it a channel msg
if((q&0x80)>0)
{
runningStatus = 0;
switch(q&0xf0)
{
case 0x80: // Note-off 2 key velocity
case 0x90: // Note-on 2 key veolcity
case 0xA0: // Aftertouch 2 key touch
case 0xB0: // Continuous controller 2 controller # controller value
case 0xC0: // Patch change 2 instrument #
case 0xE0: // Pitch bend 2 lsb (7 bits) msb (7 bits)
runningStatus = q;
numParams = 2;
break;
case 0xD0: // Channel Pressure 1 pressure
runningStatus = q;
numParams = 1;
break;
case 0xF0: // (non-musical commands) - ignore all data for now
return q;
}
// step over the message
if(!rxInc(&rxPos))
return 0;
}
// do we have an active channel message
if(runningStatus)
{
// read params
for(int thisParam = 0; thisParam < numParams; ++thisParam)
{
midiParams[thisParam] = rxBuffer[rxPos];
if(!rxInc(&rxPos))
return 0;
}
// commit removal of message
rxTail = rxPos;
return runningStatus;
}
else
{
// remove char from the buffer
rxInc(&rxTail);
return q;
}
return 0;
}
void main()
{
// osc control / 8MHz / internal
osccon = 0b01110001;
// timer0... configure source and prescaler
cmcon0 = 7;
// enable serial receive interrupt
intcon = 0b11000000;
pie1.5 = 1;
// configure io
trisa = 0b00010000;
trisc = 0b00110000;
ansel = 0b00000000;
porta=0;
portc=0;
memset(tmr,0,sizeof(tmr));
// initialise MIDI comms
init_usart();
// loop forever
for(;;)
{
// get next MIDI note
byte msg = receiveMessage();
if(msg)
{
byte note = midiParams[0];
if(note >= 48 && note < 52)
{
int which = note-48;
// 0x90 note on
// 0x80 note ff
if((msg & 0xf0) == 0x90)
{
tmr[which] = 200;
}
}
}
for(int i=0;i<4;++i)
{
if(tmr[i] > 0)
tmr[i]--;
}
porta.2 = (tmr[0]>0)?1:0;
portc.0 = (tmr[1]>0)?1:0;
portc.1 = (tmr[2]>0)?1:0;
portc.2 = (tmr[3]>0)?1:0;
}
}
Subscribe to:
Post Comments (Atom)
WOW! It works really well! You should sell the Pre-Programmed PICs on Ebay like you did for the Hand-Cranked MIDI sequencer!
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDeleteI will email you.. removed post to hide your email address. Cheers/jason
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete