Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rain Drums at Cedar River Watershed -- Code for Atmel AT90CAN128 to run system
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include "config.h"
#include "board.h"
#include "uart_lib.h"
#include "uart_drv.h"
#include "rtc_drv.h"
// parameters to adjust:
#define PWR_FAULT_COUNT_LIMIT 20 //1000
#define VALVE_TIMER_TIMEOUT 600000
#define REFILL_TIMER_EACH_VALVE 5 // in seconds (num times thru loop of 1 second)
#define REFILL_NUM_TIMES 2 // as many as needed to drain and fill
#define DRAIN_NUM_TIMES 5
#define NUM_SOLENOID_VALVES 17
// Morse Code parameters:
// ( I use morse code for troubleshooting
// in the field where you can hear
// the solenoid valves clicking... )
#define DASH_LENGTH 650
#define DOT_LENGTH 200
#define SPACER_LENGTH 300
#define LETTER_SPACER_LENGTH 450
#define WORD_SPACER_LENGTH 900
// MIDI defines...
// midi data:
// pitch = 60 to 75 (which valve)
// velocity = 0 (note off), velocity = 1 (note on)
#define MSG_TYPE_MASK 0x80
#define COMND_MSG 0x80
#define DATA_MSG 0x00
#define COMND_MASK 0xF0 // AND with message byte to get command
#define CHAN_MASK 0x0F // AND with message byte to get channel
#define NOTE_ON 0x90
#define NOTE_OFF 0x80
#define TIMING 0xF0
#define CHANNEL 0x01 //channel 2
// end MIDI defines
// AT90CAN128 // AT90CAN64 addresses may differ
// port addresses
#define portA 0x02
#define portB 0x05
#define portC 0x08
#define portD 0x0B
#define portE 0x0E
#define portF 0x11
#define portG 0x14
typedef struct
{
uint8_t pinNumber;
uint8_t portAddress;
} pinPort;
#define pin(x) (1 << x)
#define BOARD_1
#ifdef BOARD_1
enum /* Atmel at90can128 pins (outPin)*/
{
/* 19 PB0 */ BUTTON_INPUT = 19,
/* 20 PB1 */
/* 21 PB2 */ WINTERIZED_LED = 21,
/* 22 PB3 */ RUNNING_LED,
/* 23 PB4 */ POWER_FAULT_ED,
/* 24 PB5 */ TEMP_FAUT_ED,
/* 25 PB6 */ PROBEM_VAVE_ED,
/* 26 PB7 */
/* 27 PD0 */
/* 28 PD1 */
/* 29 PD2 */
/* 30 PD3 */
/* 31 PD4 */ DRAIN_RIGHT = 31, //IN_2B
/* 32 PD5 */ DRAIN_EFT, //IN_1B,
/* 33 PD6 */ GATE_RIGHT, //IN_2A,
/* 34 PD7 */ GATE_EFT, //IN_1A,
/* 35 PE0 */
/* 36 PE1 */
/* 37 PE2 */
/* 38 PE3 */
/* 39 PE4 */
/* 40 PE5 */
/* 41 PE6 */
/* 42 PE7 */
/* 43 PF0 */
/* 44 PF1 */
/* 45 PF2 */ GATE_COSED = 45,
/* 46 PF3 */ GATE_OPEN,
/* 47 PF4 */ DRAIN_COSED,
/* 48 PF5 */ DRAIN_OPEN,
/* 49 PF6 */ TEMP_FAULT = 49,
/* 50 PF7 */ PWR_FAULT = 50,
/* 51 PG0 */
/* 52 PG1 */
/* 53 PG2 */
/* 54 PG3 */
/* 55 PG4 */
/* 56 PG5 */
/* 57 PG6 */
/* 58 PG7 */
};
#endif
pinPort outPin[59] = {
{ /* 00 */ pin(7), portC } ,
{ /* 01 */ pin(2), portG } ,
{ /* 02 */ pin(7), portA } ,
{ /* 03 */ pin(6), portA } ,
{ /* 04 */ pin(5), portA } ,
{ /* 05 */ pin(4), portA } ,
{ /* 06 */ pin(3), portA } ,
{ /* 07 */ pin(2), portA } ,
{ /* 08 */ pin(1), portA } ,
{ /* 09 */ pin(0), portA } ,
{ /* 10 */ pin(1), portG } ,
{ /* 11 */ pin(0), portC } ,
{ /* 12 */ pin(1), portC } ,
{ /* 13 */ pin(2), portC } ,
{ /* 14 */ pin(3), portC } ,
{ /* 15 */ pin(4), portC } ,
{ /* 16 */ pin(5), portC } ,
{ /* 17 */ pin(6), portC } ,
{ /* 18 */ pin(0), portG } , // NOT IMPLEMENTED
{ /* 19 PB0 */ pin(0),portB } ,
{ /* 20 PB1 */ pin(1),portB } ,
{ /* 21 PB2 */ pin(2),portB } ,
{ /* 22 PB3 */ pin(3),portB } ,
{ /* 23 PB4 */ pin(4),portB } ,
{ /* 24 PB5 */ pin(5),portB } ,
{ /* 25 PB6 */ pin(6),portB } ,
{ /* 26 PB7 */ pin(7),portB } ,
{ /* 27 PD0 */ pin(0),portD } ,
{ /* 28 PD1 */ pin(1),portD } ,
{ /* 29 PD2 */ pin(2),portD } ,
{ /* 30 PD3 */ pin(3),portD } ,
{ /* 31 PD4 */ pin(4),portD } ,
{ /* 32 PD5 */ pin(5),portD } ,
{ /* 33 PD6 */ pin(6),portD } ,
{ /* 34 PD7 */ pin(7),portD } ,
{ /* 35 PE0 */ pin(0),portE } ,
{ /* 36 PE1 */ pin(1),portE } ,
{ /* 37 PE2 */ pin(2),portE } ,
{ /* 38 PE3 */ pin(3),portE } ,
{ /* 39 PE4 */ pin(4),portE } ,
{ /* 40 PE5 */ pin(5),portE } ,
{ /* 41 PE6 */ pin(6),portE } ,
{ /* 42 PE7 */ pin(7),portE } ,
{ /* 43 PF0 */ pin(0),portF } ,
{ /* 44 PF1 */ pin(1),portF } ,
{ /* 45 PF2 */ pin(2),portF } ,
{ /* 46 PF3 */ pin(3),portF } ,
{ /* 47 PF4 */ pin(4),portF } ,
{ /* 48 PF5 */ pin(5),portF } ,
{ /* 49 PF6 */ pin(6),portF } ,
{ /* 50 PF7 */ pin(7),portF } ,
{ /* 51 PG0 */ pin(0),portG } ,
{ /* 52 PG1 */ pin(1),portG } ,
{ /* 53 PG2 */ pin(2),portG } ,
{ /* 54 PG3 */ pin(3),portG } ,
{ /* 55 PG4 */ pin(4),portG } ,
{ /* 56 PG5 */ pin(5),portG } ,
{ /* 57 PG6 */ pin(6),portG } ,
{ /* 58 PG7 */ pin(7),portG } ,
};
#include <avr/eeprom.h>
uint8_t EEMEM dummy;
uint8_t EEMEM isWinterized = 0; // !!! so it's zero after programming
// EEPROM access functions:
// uint8_t eeprom_read_byte (const uint8_t *addr);
// eeprom_write_byte (uint8_t *addr,uint8_t value);
static uint8_t readEEPROMbyte(uint8_t * eepromVariable)
{
while(eeprom_is_ready() == 0)
wdt_reset();
return eeprom_read_byte(eepromVariable);
}
static void writeEEPROMbyte(uint8_t * eepromVariable, uint8_t value )
{
while(eeprom_is_ready() == 0)
wdt_reset();
eeprom_write_byte (eepromVariable, value);
}
static void turnOn(uint8_t whichLED)
{
uint8_t registerAddress = outPin[whichLED].portAddress;
uint8_t pinNumber = outPin[whichLED].pinNumber;
_SFR_IO8(registerAddress) |= (pinNumber);
}
static void turnOff(uint8_t whichLED)
{
uint8_t registerAddress = outPin[whichLED].portAddress;
uint8_t pinNumber = outPin[whichLED].pinNumber;
_SFR_IO8(registerAddress) &= ~(pinNumber);
}
static uint8_t getPinState (uint8_t whichPin)
{
uint8_t registerAddress = outPin[whichPin].portAddress -2; // !! PINx
uint8_t pinNumber = outPin[whichPin].pinNumber;
uint8_t registerValue = _SFR_IO8(registerAddress);
if ((registerValue & pinNumber) == 0) return 0;
else return 1;
}
static uint8_t getPinAsByte (uint8_t whichPin)
{
return outPin[whichPin].pinNumber;
}
static volatile uint8_t rcvdByte = 0;
static volatile uint8_t testByte = 0;
static volatile uint8_t whichByte = 0;
static volatile uint8_t message = 0;
static volatile uint8_t pitch = 0;
static volatile uint8_t velocity = 0;
SIGNAL(SIG_UART1_RECV) // handles the MIDI signals...
{
// while (uart_test_hit() == 0)
// wdt_reset(); // Reset watchdog timer.
// turnOn(4);
rcvdByte = uart_getchar();
//PORTA = rcvdByte;
wdt_reset(); // Reset watchdog timer.
if(whichByte == 0)
{
testByte = rcvdByte & COMND_MSG;
if (testByte == COMND_MSG)
{
whichByte++;
message = rcvdByte & COMND_MASK;
//turnOn(0);
}
//else whichByte = 0; // effectively does this
}
else if(whichByte == 1)
{
testByte = rcvdByte & DATA_MSG;
if (testByte == DATA_MSG)
{
whichByte++;
pitch = rcvdByte;
//turnOn(1);
}
else whichByte = 0;
}
// get velocity and turn on or turn off valve...
else if(whichByte == 2)
{
testByte = rcvdByte & DATA_MSG;
if (testByte == DATA_MSG)
{
whichByte = 0;
velocity = rcvdByte;
if (pitch >= 60 || pitch <= 77)
{
if(velocity == 0) turnOff(pitch - 60);
else turnOn(pitch - 60);
}
}
else whichByte = 0;
//turnOn(2);
}
wdt_reset();
}
//////////// SENSE INPUT & SYSTEM STATE ////////////////////
enum // sysState
{
enumIsRunning = 1 << 0,
enumIsWinterized = 1 << 1,
enumIsFilling = 1 << 2,
enumIsDraining = 1 << 3,
enumIsPowerFault = 1 << 4,
enumIsPowerOK = 1 << 5,
};
enum // sysAction
{
enumNone,
enumFill,
enumDrain,
};
static volatile uint8_t sysAction = 0;
static volatile uint8_t sysState = 0;
static volatile uint8_t drainClosed = 0;
static volatile uint8_t drainOpen = 0;
static volatile uint8_t gateClosed = 0;
static volatile uint8_t gateOpen = 0;
static volatile uint8_t tempFault = 0;
static volatile uint8_t pwrFault = 0;
static volatile int32_t pwrFaultCount = 0;
static void turnAllValvesOff()
{
int i;
for(i = 0; i < 19; i++) {
turnOff(i);
}
wdt_reset();
}
static uint8_t closeGate(); // declaration only
static uint8_t openDrain()
{
turnAllValvesOff(); // all drip valves, that is...
turnOff(DRAIN_LEFT);
turnOff(DRAIN_RIGHT);
turnOff(GATE_LEFT);
turnOff(GATE_RIGHT);
wait_for(1);
wdt_reset();
turnOn(DRAIN_LEFT);
uint32_t timer = 0;
uint8_t error = 0;
while((getPinState(DRAIN_OPEN)) == 1 && (error == 0))
{
wdt_reset();
timer++;
if(timer > VALVE_TIMER_TIMEOUT)
{
turnOn(PROBLEM_VALVE_LED);
error = 1;
}
}
turnOff(DRAIN_LEFT);
if(error == 1) closeGate(); /// if fails, close the gate valve to stop any leaking...
if(error == 1) return 1; /// didn't open all the way or micro-switch problem or open circuit to switch
if(DRAIN_CLOSED == 0) return 2; /// something is wrong with pull-ups or
/// PORTF or a shorted micro-switch
return 0;
}
static uint8_t closeDrain()
{
turnAllValvesOff(); // all drip valves, that is...
turnOn(DRAIN_RIGHT);
turnOff(DRAIN_LEFT);
turnOff(GATE_LEFT);
turnOff(GATE_RIGHT);
wait_for(1);
wdt_reset();
turnOn(DRAIN_RIGHT);
uint32_t timer = 0;
uint8_t error = 0;
while((getPinState(DRAIN_CLOSED)) == 1 && (error == 0))
{
wdt_reset();
timer++;
if(timer > VALVE_TIMER_TIMEOUT)
{
turnOn(PROBLEM_VALVE_LED);
error = 1;
}
}
//if(error == 0) turnOff(PROBLEM_VALVE_LED);
turnOff(DRAIN_RIGHT);
if(error == 1) closeGate(); /// if fails, close the gate valve to stop any leaking...
if(error == 1) return 3; /// didn't close all the way or micro-switch problem or open circuit to switch
if(DRAIN_OPEN == 0) return 4; /// something is wrong with pull-ups or
/// PORTF or a shorted micro-switch
return 0;
}
static uint8_t openGate()
{
turnAllValvesOff(); // all drip valves, that is...
turnOff(DRAIN_LEFT);
turnOff(DRAIN_RIGHT);
turnOff(GATE_LEFT);
turnOff(GATE_RIGHT);
wait_for(5);
wdt_reset();
turnOn(GATE_LEFT);
uint32_t timer = 0;
uint8_t error = 0;
while((getPinState(GATE_OPEN)) == 1 && (error == 0))
{
//wait_for(2);
wdt_reset();
timer++;
if(timer > VALVE_TIMER_TIMEOUT)
{
turnOn(PROBLEM_VALVE_LED);
error = 1;
}
}
turnOff(GATE_LEFT);
if(error == 1) closeGate(); /// if fails, close the gate valve to stop any leaking...
if(error == 1) return 5; /// didn't open all the way or micro-switch problem or open circuit to switch
if(GATE_CLOSED == 0) return 6; /// something is wrong with pull-ups or
/// PORTF or a shorted micro-switch
return 0;
}
static uint8_t closeGate()
{
turnAllValvesOff(); // all drip valves, that is...
turnOff(DRAIN_LEFT);
turnOff(DRAIN_RIGHT);
turnOff(GATE_LEFT);
turnOff(GATE_RIGHT);
wait_for(1);
wdt_reset();
turnOn(GATE_RIGHT);
uint32_t timer = 0;
uint8_t error = 0;
while((getPinState(GATE_CLOSED)) == 1 && (error == 0))
{
//wait_for(2);
wdt_reset();
timer++;
if(timer > VALVE_TIMER_TIMEOUT)
{
turnOn(PROBLEM_VALVE_LED);
error = 1;
}
}
turnOff(GATE_RIGHT);
if(error == 1) return 7; /// didn't close all the way or micro-switch problem or open circuit to switch
if(GATE_OPEN == 0) return 8; /// something is wrong with pull-ups or
/// PORTF or a shorted micro-switch
return 0;
}
static void toggle(uint8_t pin)
{
if (getPinState(pin) == 0)
turnOn(pin);
else turnOff(pin);
}
static void doSolenoidDrainSequence()
{
int i;
int j;
int k;
for(j = 0; j < DRAIN_NUM_TIMES; j++)
{
for (i = 0; i <= NUM_SOLENOID_VALVES; i++)
{
turnOn(i);
for(k = 0; k < REFILL_TIMER_EACH_VALVE; k++)
{
wait_for(1000);
toggle(WINTERIZED_LED);
wdt_reset();
}
turnOff(i);
wait_for(1);
wdt_reset();
}
}
}
static void doSolenoidFillSequence()
{
int i;
int j;
int k;
for(j = 0; j < REFILL_NUM_TIMES; j++)
{
for (i = 0; i <= NUM_SOLENOID_VALVES; i++)
{
turnOn(i);
for(k = 0; k < REFILL_TIMER_EACH_VALVE; k++) {
wait_for(1000);
toggle(RUNNING_LED);
wdt_reset();
}
turnOff(i);
wait_for(1);
wdt_reset();
}
}
}
static void systemAction()
{
if(sysAction == enumDrain)
{
cli();
turnAllValvesOff();
turnOff(RUNNING_LED);
closeGate();
openDrain();
doSolenoidDrainSequence();
turnOn(WINTERIZED_LED);
closeDrain();
uint8_t test = readEEPROMbyte(&isWinterized);
if(test == 0)
writeEEPROMbyte(&isWinterized, 1);
sysAction = enumNone;
}
else if(sysAction == enumFill)
{
cli();
turnAllValvesOff();
turnOff(WINTERIZED_LED);
closeDrain();
openGate();
doSolenoidFillSequence(); //Refill sequence
turnOn(RUNNING_LED);
uint8_t test = readEEPROMbyte(&isWinterized);
if(test != 0)
writeEEPROMbyte(&isWinterized, 0);
sei();
sysAction = enumNone;
}
else ;
}
static void sysTempTest()
{
// check the temp & power, perhaps initiate a system action (sysAction)...
// check temperature switch...
if(getPinState(TEMP_FAULT) == 1) // 1 = above freezing
{
tempFault = 0;
turnOff(TEMP_FAULT_LED);
}
else
{
tempFault = 1;
turnOn(TEMP_FAULT_LED);
cli(); // make sure it's not taking serial commands
turnAllValvesOff();
}
// check power fault switch...
if(getPinState(PWR_FAULT) == 0) // ie, low == OK, high == power fault
pwrFaultCount--;
else
pwrFaultCount++;
if(pwrFaultCount < 0)
{
pwrFaultCount = 0;
pwrFault = 0;
turnOff(POWER_FAULT_LED);
}
else if(pwrFaultCount > PWR_FAULT_COUNT_LIMIT)
{
pwrFaultCount = PWR_FAULT_COUNT_LIMIT;
pwrFault = 1;
turnOn(POWER_FAULT_LED);
cli();
turnAllValvesOff();
}
if(((pwrFault == 1 || tempFault == 1) && (getPinState(WINTERIZED_LED)) == 0))
sysAction = enumDrain;
if(((pwrFault == 0 && tempFault == 0) && (getPinState(WINTERIZED_LED)) == 1))
sysAction = enumFill;
}
static void dash( uint8_t whichValve)
{
turnOn(whichValve);
wait_for(DASH_LENGTH);
wdt_reset();
turnOff(whichValve);
wait_for(SPACER_LENGTH);
wdt_reset();
}
static void dot(uint8_t whichValve)
{
turnOn(whichValve);
wait_for(DOT_LENGTH);
wdt_reset();
turnOff(whichValve);
wait_for(SPACER_LENGTH);
wdt_reset();
}
static void letterSpace()
{
wait_for(LETTER_SPACER_LENGTH);
wdt_reset();
}
static void zero(uint8_t i)
{
dash(i);
dash(i);
dash(i);
dash(i);
dash(i);
letterSpace();
}
static void one(uint8_t i)
{
dot(i);
dash(i);
dash(i);
dash(i);
dash(i);
letterSpace();
}
static void two(uint8_t i)
{
dot(i);
dot(i);
dash(i);
dash(i);
dash(i);
letterSpace();
}
static void three(uint8_t i)
{
dot(i);
dot(i);
dot(i);
dash(i);
dash(i);
letterSpace();
}
static void four(uint8_t i)
{
dot(i);
dot(i);
dot(i);
dot(i);
dash(i);
letterSpace();
}
static void five(uint8_t i)
{
dot(i);
dot(i);
dot(i);
dot(i);
dot(i);
letterSpace();
}
static void six(uint8_t i)
{
dash(i);
dot(i);
dot(i);
dot(i);
dot(i);
letterSpace();
}
static void seven(uint8_t i)
{
dash(i);
dash(i);
dot(i);
dot(i);
dot(i);
letterSpace();
}
static void eight(uint8_t i)
{
dash(i);
dash(i);
dash(i);
dot(i);
dot(i);
letterSpace();
}
static void nine(uint8_t i)
{
dash(i);
dash(i);
dash(i);
dash(i);
dot(i);
letterSpace();
}
static void doMorseCode()
{
int i = 0;
six(i);
zero(i);
i = 1;
six(i);
one(i);
i = 2;
six(i);
two(i);
i = 3;
six(i);
three(i);
i = 4;
six(i);
four(i);
i = 5;
six(i);
five(i);
i = 6;
six(i);
six(i);
i = 7;
six(i);
seven(i);
i = 8;
six(i);
eight(i);
i = 9;
six(i);
nine(i);
i = 10;
seven(i);
zero(i);
i = 11;
seven(i);
one(i);
i = 12;
seven(i);
two(i);
i = 13;
seven(i);
three(i);
i = 14;
seven(i);
four(i);
i = 15;
seven(i);
five(i);
i = 16;
seven(i);
six(i);
i = 17;
seven(i);
seven(i);
}
////////////////////////////////////////////////////////
int main (void)
{
wdt_disable();
DDRA = 0xff;
DDRB = 0xff;
DDRC = 0xff;
DDRD = 0xff;
DDRE = 0xff;
DDRF = 0xff;
int i;
// setup for 31,250 baudrate, 8mHz crystal...
// UBRR1 = 15;
// U2X1 = 0;
// setup for 38,400 baudrate, 8mHz crystal...
// UBRR1 = 12;
// U2X1 = 0;
/* Set baud rate */
UBRR1H = 0x00;
UBRR1L = (unsigned char)12;
/* Enable receiver and transmitter */
UCSR1B = (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1); // recv enable, tx enable, rc interrupt enable
UCSR1C = 6;
// Init UART-0 at xxx bauds
// Uart_select(UART_1);
// uart_init(CONF_8BIT_NOPAR_1STOP,38400);
// uart_set_baudrate(38400);
cli();
// set them all as outputs...
// PORTF = 0xff; //!!!!! configure as input with internal pull-up resistors
PORTF = 0x00; // configure input without external pull-ups...because they get blown easily! use external pull-up's
DDRF = 0x00; // sense inputs
wdt_enable(WDTO_2S); // !!! 2 second timeout
wdt_reset();
//test indicator lights
PORTB = 0; // turn off all indicator lights...
turnOn(RUNNING_LED);
wait_for(1000);
wdt_reset();
PORTB = 0; // turn off all indicator lights...
turnOn(WINTERIZED_LED);
wait_for(1000);
wdt_reset();
PORTB = 0; // turn off all indicator lights...
turnOn(POWER_FAULT_LED);
wait_for(1000);
wdt_reset();
PORTB = 0; // turn off all indicator lights...
turnOn(TEMP_FAULT_LED);
wait_for(1000);
wdt_reset();
PORTB = 0; // turn off all indicator lights...
turnOn(PROBLEM_VALVE_LED);
wait_for(1000);
wdt_reset();
PORTB = 0; // turn off all indicator lights...
for (i = 0; i<17; i++) // run through all the valves / valve circuit indicator lights
{
turnOn(i);
wait_for(50);
wdt_reset();
turnOff(i);
}
// get the system state saved at last power-down...
uint8_t test = readEEPROMbyte(&isWinterized);
if(test != 0)
{
turnOn(WINTERIZED_LED);
closeDrain();
closeGate();
}
else
{
turnOn(RUNNING_LED);
if(0 == closeDrain())
openGate();
else closeGate();
}
wait_for(1000);
wdt_reset();
wait_for(1000);
wdt_reset();
wait_for(1000);
wdt_reset();
wait_for(1000);
wdt_reset();
/////////////////////////////////////////////////////////////
// begin loop:
Uart_select(UART_1);
sei();
while(1)
{
sysTempTest();
wdt_reset();
systemAction();
wdt_reset();
}
return 0;
}
// old code from hc11 controller....
// no temp or power sense, just do MIDI...
/*
ldaa numBytesRead
cmpa #0
beq SpbCommand
cmpa #1
beq SpbPitch
cmpa #2
beq SpbVelocity
*** error condition ***
clr numBytesRead
jmp SpbExit
SpbCommand bra Spb1
ldaa sciReadByte
anda #CHAN_MASK
cmpa #CHANNEL
* beq Spb1
bra Spb1 accept all channels
jmp SpbExit it's not our channel so exit
Spb1 ldaa sciReadByte
anda #COMND_MSG
cmpa #COMND_MSG
beq SpbMessage
jmp SpbExit it's not a command msg so exit
SpbMessage inc numBytesRead
ldaa sciReadByte load the byte again
anda #COMND_MASK extract the message portion
staa message store it in message
jmp SpbExit
*** process pitch message ***
SpbPitch ldaa sciReadByte
anda #DATA_MSG
cmpa #DATA_MSG
beq SpbPit2
clr numBytesRead it's not a data message so exit
jmp SpbExit
SpbPit2 inc numBytesRead
ldaa sciReadByte
staa pitch
bra SpbExit
*** process velocity message ***
*** and execute command ***
SpbVelocity ldaa sciReadByte load the VELOCITY data
anda #DATA_MSG
cmpa #DATA_MSG
beq SpbVel2
clr numBytesRead look for a new command
jmp SpbExit
SpbVel2 clr numBytesRead finished with instruction
ldaa sciReadByte
staa velocity
jsr ProcessPitch()
SpbExit pulx
puly
pulb
rts
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.