Cast tube base station
Dependencies: EALib USBDevice mbed
Diff: main.cpp
- Revision:
- 0:e559b5160d84
- Child:
- 1:240b94a8d002
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 16 19:49:47 2015 +0000 @@ -0,0 +1,759 @@ +/****************************************************************************** + * Includes + *****************************************************************************/ +#include "mbed.h" +#include "XBee.h" +#include "USBHID.h" +#include "ByteOperations.h" +#include "USBHIDProtocol.h" + +/****************************************************************************** + * Typedefs and defines + *****************************************************************************/ + +// define NODE_IS_COORDINATOR if this board should act +// as XBee coordinator. Make sure it is undefined if the board +// should act as End-Device +//#define NODE_IS_COORDINATOR (0) + +//#define CMD_BTN_MSG (0) +//#define CMD_ACK_MSG (1) +//#define NUMBER_OF_ZONES 72 +//#define ECHO_SERVER_PORT 7 +#define VERSION 0x01 +#define COMMAND 0 +#define DATA 1 + +#define XBeeDisconnected 0x400 +#define MaxTeethExceeded 0x800 + +// rotational stage modes +#define STOPPED 1 +#define PARKING 2 +#define GOTOMDPOSITION 3 +#define DRIVINGTOPOSITION 4 +#define STARTROTATING 5 +#define ROTATING 6 +#define MDSCAN 7 + +#define MAX_TEETH 384 + +#define LOW 0 +#define HIGH 1 + + +// input/output devices +static XBee xbee(P4_22, P4_23, P4_17, P4_19); +static DigitalIn indexInputLevel(p10); +static DigitalIn zeroInputLevel(p11); +static DigitalOut led1(LED1); // led1 + led 2 -> active low +static DigitalOut led2(LED2); +static DigitalOut led3(LED3); // led3 + led 4 -> active high +static DigitalOut led4(LED4); +static DigitalOut motorDrive(p12); +Serial pc(USBTX, USBRX); // tx, rx +Ticker lossOfSignalTimer; +Ticker updateLCD; +Ticker rotationalControl; +Ticker debounceDigInputs; +Ticker ledPulseCheck; +BusInOut databus(p25, p26, p27, p28, p29, p30, p31, p32); +DigitalOut registerSelect(p39); +DigitalOut readWrite(p38); +DigitalOut readWriteClock(p37); + +USBHID *hid; +HID_REPORT send_report __attribute__((aligned (4))); // Aligned for fast access +HID_REPORT recv_report __attribute__((aligned (4))); // Aligned for fast access + + + +// local variables +float rawTemperature = 0.0; +float rawThickness = 0.0; +uint32_t position = 0; +uint32_t seqNo = 0; +uint32_t prevSeqNo = 0; +bool xbeeIsUp = false; +bool saveProfileToDatabase = false; +char inBuff[256]; +char outBuff[256]; +uint8_t xbeeSigStrength = 0; +uint32_t errorFlags = 0; +int rotationalMode = STOPPED; +int mdPosition = 0; +int toothLowCount = 0; +int zeroLowCount = 0; +int zeroHighCount = 0; +int led1Duration = 0; +int led2Duration = 0; +int led3Duration = 0; +int led4Duration = 0; +int parkPosition = 0; +int indexInputState = HIGH; +int zeroInputState = HIGH; + + +void pulseLed(int led, int duration) +{ + + switch (led) + { + case LED1: + led1 = 0; // turn on led + led1Duration = duration; // set duration + break; + case LED2: + led2 = 0; // turn on led + led2Duration = duration; // set duration + break; + case LED3: + led3 = 1; // turn on led + led3Duration = duration; // set duration + break; + case LED4: + led4 = 1; // turn on led + led4Duration = duration; // set duration + break; + default: ; + } +} + + + +void ledPulser() +{ + + if (led1Duration > 0) + { + led1Duration--; + + if (led1Duration == 0) + led1 = 1; // turn led off + } + + if (led2Duration > 0) + { + led2Duration--; + + if (led2Duration == 0) + led2 = 1; // turn led off + } + + if (led3Duration > 0) + { + led3Duration--; + + if (led3Duration == 0) + led3 = 0; // turn led off + } + + if (led4Duration > 0) + { + led4Duration--; + + if (led4Duration == 0) + led4 = 0; // turn led off + } +} + + + + + + +void debounceInputs() +{ + + + if (indexInputLevel == 0) + { + if (toothLowCount < 5) // times 10 mS for debounce period + { + toothLowCount++; + + if (toothLowCount >= 5) + { + position++; + + if (position >= MAX_TEETH) + { + position = 0; + errorFlags |= MaxTeethExceeded; + } + } + } + } + else + toothLowCount = 0; + + if (zeroInputLevel == 0) + { + if (zeroLowCount < 5) // times 10 mS debounce period + { + zeroLowCount++; + + if (zeroLowCount >= 5) + { + position = 0; // zero position counter + } + } + } + else + { + zeroLowCount = 0; + } +} + + + + +static void xbeeDeviceUp(void) +{ + xbeeIsUp = true; +} + + + +static void xbeeDeviceDown(void) +{ + xbeeIsUp = false; +} + + + +static void xbeeNodeFound(void) +{ + uint32_t addrHi = 0; + uint32_t addrLo = 0; + uint8_t rssi = 0; + + xbee.getRemoteAddress(&addrHi, &addrLo); + xbee.getRssi(&rssi); +} + + +static void xbeeTxStat(void) +{ + + uint8_t frameId = 0; + XBee::XBeeTxStatus status = XBee::TxStatusOk; + + xbee.getTxStatus(&frameId, &status); +} + + + +static void xbeeDataAvailable(void) +{ + char* data = NULL; + uint8_t len = 0; + uint32_t addrHi = 0; + uint32_t addrLo = 0; + + xbee.getRemoteAddress(&addrHi, &addrLo); + xbee.getData(&data, &len); + //xbee.getRssi(&rssi); + + if (len > 0) { + + switch(data[0]) + { + case '1': + if (len > 1) + { + pulseLed( LED4, 5); + + // get values from data packet + // packet format - sprintf(data, "1%5.3f, %5.3f, %5.3f, %5.3f, %4x\n", rawTemperature, rawThickness, filteredTemperature, filteredThickness, errorFlags); + sscanf(&data[1], "%f,%f, %x\n", &rawTemperature, &rawThickness, &errorFlags); + } + break; + + default: + pc.printf("Unknown packet format %d\n", data[0]); + } + } +} + + + +static bool xbeeInit() +{ + xbee.registerCallback(xbeeDeviceUp, XBee::CbDeviceUp); + + xbee.registerCallback(xbeeDeviceDown, XBee::CbDeviceDown); + + xbee.registerCallback(xbeeNodeFound, XBee::CbNodeFound); + + xbee.registerCallback(xbeeTxStat, XBee::CbTxStat); + + xbee.registerCallback(xbeeDataAvailable, XBee::CbDataAvailable); + + XBee::XBeeError err = xbee.init(XBee::EndDevice, "EAEA"); + + if (err != XBee::Ok) + { + return false; + } + + return true; +} + + +static void reportInitFailed() +{ + while (true) { + wait_ms(200); + } +} + + +static void ledInit() +{ + led1 = 1; // turn off + led2 = 1; // turn off + led3 = 0; // turn off + led4 = 0; // turn off +} + + +void empty_report(HID_REPORT *data){ + register uint32_t *p = (uint32_t *)data->data; + for( register int i=0; i<((sizeof(HID_REPORT)-1)/4); i++ ){ + *p = 0xFFFFFFFF; + p++; + } +} + + + +void processUSB() +{ + uint8_t hiPosition; + uint8_t loPosition; + + if(hid->readNB(&recv_report)) //try to read a msg + { + pulseLed(LED3, 5); // pulse led3 to show USB activity + + // Data packet received, start parsing + int irx=0; + int itx=0; + + send_report.data[itx++] = recv_report.data[0]; + + switch ( recv_report.data[irx++] ) + { + case CMD_SYS_CHECK: + send_report.data[itx++] = VERSION; + break; + + case CMD_SYS_RESET: + empty_report(&recv_report); // Soft reset + break; + + case CMD_CURRENT_VALUES: + write_32_to_8(&itx, send_report.data, (uint32_t)(rawTemperature * 1000)); + write_32_to_8(&itx, send_report.data, (uint32_t)(rawThickness * 1000)); + write_32_to_8(&itx, send_report.data, position); + write_32_to_8(&itx, send_report.data, xbeeSigStrength); + write_32_to_8(&itx, send_report.data, errorFlags); + write_32_to_8(&itx, send_report.data, rotationalMode); + break; + + case PARK_AT_ZERO: + parkPosition = MAX_TEETH - 2; // to allow it to slow donw and hit zero + rotationalMode = PARKING; + break; + + case PARK_AT_POSITION: + hiPosition = recv_report.data[irx++]; + loPosition = recv_report.data[irx++]; + parkPosition = (hiPosition << 8) + loPosition; + + parkPosition -= 2; // to allow it to slow down and hit the required position + if (parkPosition < 0) + parkPosition += MAX_TEETH; + rotationalMode = PARKING; + break; + + case MD_SCAN: + hiPosition = recv_report.data[irx++]; + loPosition = recv_report.data[irx++]; + mdPosition = (hiPosition << 8) + loPosition; + rotationalMode = GOTOMDPOSITION; + break; + + case ROTATIONAL_SCAN: + rotationalMode = STARTROTATING; + break; + + case 0xEE: + hid->sendNB(&send_report); + break; + + default: + send_report.data[0] = 0xFF; //Failure + break; + } + + hid->send(&send_report); // Return command + optional new args + + empty_report(&recv_report); + empty_report(&send_report); + } +} + + +void checkForLossOfSignal() +{ + + xbee.getRssi(&xbeeSigStrength); +} + + + +void writeToLCD(bool rs, char data) +{ + + registerSelect = rs; // set register select pin + + readWrite = 0; // set read/write pin to write + + databus.output(); // set bus as output + + databus = data; // put data onto bus + + readWriteClock = 1; // pulse read/write clock + + wait_us(1); + + readWriteClock = 0; + + wait_us(1); + + databus = 0; // clear data bus +} + + + +char readFromLCD(bool rs) +{ + + char data; + + registerSelect = rs; // set register select pin + + readWrite = 1; // set read/write pin to read + + databus.input(); // set bus as input + + data = databus; // read data from bus + + readWriteClock = 1; // pulse read/write clock + + wait_us(10); + + readWriteClock = 0; + + return data; +} + + +void resetLCD() +{ +} + + +void initLCD(){ + + readWrite = 0; // set output so we always write to LCD + + wait_ms(15); // wait 15 ms to allow LCD to initialise + + writeToLCD(COMMAND, 0x30); // set interface for 8 bit mode + + wait_ms(5); // give it time + + writeToLCD(COMMAND, 0x30); // set interface for 8 bit mode again + + wait_us(100); // give it time + + writeToLCD(COMMAND, 0x30); // set interface for 8 bit mode again, last one before we can configure the display + + wait_us(500); // give it time + + writeToLCD(COMMAND, 0x38); // set interface for 8 bit mode, 2 display lines and 5 x 8 character font + + wait_us(100); // give it time + + writeToLCD(COMMAND, 0x08); // display off + + wait_us(100); // give it time + + writeToLCD(COMMAND, 0x01); // clear the screen + + wait_ms(2); // give it time to finish + + writeToLCD(COMMAND, 0x03); // set entry mode to increment cursor position cursor on write + + wait_us(100); // give it time to finish + + writeToLCD(COMMAND, 0x02); // position cursor at home + + wait_ms(2); // give it time to finish + + writeToLCD(COMMAND, 0x0C); // display on +} + + + + +void positionCursor(uint8_t x, uint8_t y) +{ + + switch (y) + { + case 0: + writeToLCD(COMMAND, 0x80 + 0x00 + x); + break; + + case 1: + writeToLCD(COMMAND, 0x80 + 0x40 + x); + break; + + case 2: + writeToLCD(COMMAND, 0x80 + 0x14 + x); + break; + + case 3: + writeToLCD(COMMAND, 0x80 + 0x54 + x); + break; + + default: + writeToLCD(COMMAND, 0x80 + 0x00 + x); + } + + wait_us(50); +} + + + +void clearLcdScreen() +{ + + writeToLCD(COMMAND, 0x01); + + wait_ms(2); +} + + + +void displayString(int x, int y, char *str) +{ + + positionCursor(x, y); // position cursor + + for (int i=0; i<strlen(str); i++) // write string to screen + { + writeToLCD(DATA, str[i]); + + wait_us(50); + } +} + + + + void updateDisplay() + { + char lineStr[20]; + + clearLcdScreen(); + + sprintf( lineStr, "Thickness %4.2f mm", rawThickness); + + displayString(0, 0, lineStr); + + sprintf( lineStr, "Temperature %4.1f C ", rawTemperature); + + displayString(0, 1, lineStr); + + sprintf( lineStr, "Sig strength %2d", xbeeSigStrength); + + displayString(0, 2, lineStr); + + switch (rotationalMode) + { + case STOPPED: + displayString(0, 3, "Parked"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + case PARKING: + displayString(0, 3, "Parking"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + case GOTOMDPOSITION: + displayString(0, 3, "Go to MD pos"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + case DRIVINGTOPOSITION: + displayString(0, 3, "Go to MD pos"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + case STARTROTATING: + displayString(0, 3, "Start scan"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + case ROTATING: + displayString(0, 3, "Scanning"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + case MDSCAN: + displayString(0, 3, "MD scanning"); + sprintf( lineStr, "%3d", position); + displayString(16, 3, lineStr); + break; + + default: + break; + } + +} + + + void displayDebugMsg(char *str) + { + + clearLcdScreen(); + + displayString(0, 0, str); +} + + + +void checkRotationMode() +{ + + switch (rotationalMode) + { + case STOPPED: + break; + + case PARKING: + if (motorDrive == 0) + motorDrive = 1; + + if (position == parkPosition) + { + motorDrive = 0; + rotationalMode = STOPPED; + } + break; + + case GOTOMDPOSITION: + motorDrive = 1; + rotationalMode = DRIVINGTOPOSITION; + break; + + case DRIVINGTOPOSITION: + if (position == mdPosition) + { + motorDrive = 0; + rotationalMode = MDSCAN; + } + break; + + case STARTROTATING: + motorDrive = 1; + rotationalMode = ROTATING; + break; + + case ROTATING: + break; + + default: + break; + } +} + + + + +int main() +{ + + ledInit(); // initialise leds + + motorDrive = 0; // set motor drive output to off + + initLCD(); // initialize the LCD + + displayDebugMsg("Initializing XBee"); + + if (!xbeeInit()) { + reportInitFailed(); + } + + // Wait until XBee node is reported to be up. + // - For End-device this means that the node is associated with a + // coordinator + // - For a coordinator this means that the node is initialized and ready + displayDebugMsg("Connecting to XBee"); + + while(!xbeeIsUp) + { + xbee.process(); + } + + displayDebugMsg(" "); // clear display + + displayDebugMsg("Initialising USB"); + + static USBHID hid_object(64, 64); // USB Initialize + hid = &hid_object; + send_report.length = 64; + + lossOfSignalTimer.attach(&checkForLossOfSignal, 2.0); // check for loss of signal every 2 seconds + + updateLCD.attach(&updateDisplay, 1.0); + + rotationalControl.attach(checkRotationMode, 0.05); + + debounceDigInputs.attach(debounceInputs, 0.01); + + ledPulseCheck.attach(ledPulser, 0.01); + + ledInit(); // turn off all leds as initialisation complete + + while (1) + { + if (xbeeIsUp) + { + xbee.process(); + + processUSB(); + + wait_ms(2); + } + else + { + errorFlags = XBeeDisconnected; // set error flag for no connection to XBee + + rawTemperature = 0.0; // clear display values + rawThickness = 0.0; + } + } +}