diff --git a/slave/slave/config.h b/slave/slave/config.h --- a/slave/slave/config.h +++ b/slave/slave/config.h @@ -11,11 +11,19 @@ #define F_CPU 11059200 // Clock frequency (used in calculations) +//Serial #define USART0_BAUDRATE 115200 #define USART1_BAUDRATE 115200 -#define SENSOR_LOOP 100 // Frequency of sensor reads (in ms) +// Circular serial buffer size. Must be at least MAX_CMD_LEN + 5 +#define BUFFER_SIZE 32 +// Maximum payload size of command +#define MAX_PAYLOAD_LEN 16 + + +//Sensors and IO +#define SENSOR_LOOP 200 // Frequency of sensor reads (in ms) #define HEATER_THRESHOLD 40 // Temperature threshold in Fahrenheit where heater is activated //I2C Addresses diff --git a/slave/slave/lib/inputOutput.c b/slave/slave/lib/inputOutput.c --- a/slave/slave/lib/inputOutput.c +++ b/slave/slave/lib/inputOutput.c @@ -8,7 +8,9 @@ #include #include "../config.h" #include "inputOutput.h" - +#include "led.h" +#include "sensors.h" + void io_configure() { // Configure ports/pins diff --git a/slave/slave/lib/led.c b/slave/slave/lib/led.c --- a/slave/slave/lib/led.c +++ b/slave/slave/lib/led.c @@ -83,27 +83,23 @@ void led_toggle(uint8_t led) switch(led) { case 0: - if ((PORTB & 0b00000001) == 1) PORTB &= ~(1 << PB0); //OFF - else PORTB |= (1 << PB0); //ON + PORTB ^= (1 << PB0); break; case 1: - if (((PORTB & 0b00000010)>>1) == 1) PORTB &= ~(1 << PB1); //OFF - else PORTB |= (1 << PB1); //ON + PORTB ^= (1 << PB1); break; case 2: - if (((PORTB & 0b00000100)>>2) == 1) PORTB &= ~(1 << PB2); //OFF - else PORTB |= (1 << PB2); //ON + PORTB ^= (1 << PB2); break; case 3: - if (((PORTB & 0b00001000)>>3) == 1) PORTB &= ~(1 << PB3); //OFF - else PORTB |= (1 << PB3); //ON + PORTB ^= (1 << PB3); break; default: - + break; } } diff --git a/slave/slave/lib/masterComm.c b/slave/slave/lib/masterComm.c new file mode 100644 --- /dev/null +++ b/slave/slave/lib/masterComm.c @@ -0,0 +1,34 @@ +/* + * masterComm.c + * + * Created: 1/22/2013 3:40:53 PM + * Author: kripperger + */ + + +#include +#include "../config.h" +#include "masterComm.h" +#include "serial.h" +#include "serparser.h" + + +void masterComm_send() +{ + //Send stuff + serial0_sendString("got data\r\n"); +} + + +void masterComm_check() +{ + if (serparser_parse() == PARSERESULT_PARSEOK) + { + if (getPayloadType() == ('@'-0x30)) // Request for data recieved + { + // Send all data + masterComm_send(); + } + } +} + diff --git a/slave/slave/lib/masterComm.h b/slave/slave/lib/masterComm.h new file mode 100644 --- /dev/null +++ b/slave/slave/lib/masterComm.h @@ -0,0 +1,20 @@ +/* + * masterComm.h + * + * Created: 1/22/2013 3:40:43 PM + * Author: kripperger + */ + + +#ifndef MASTERCOMM_H_ +#define MASTERCOMM_H_ + + + +void masterComm_check(); +void masterComm_send(); + + + + +#endif /* MASTERCOMM_H_ */ \ No newline at end of file diff --git a/slave/slave/lib/sensors.c b/slave/slave/lib/sensors.c --- a/slave/slave/lib/sensors.c +++ b/slave/slave/lib/sensors.c @@ -13,6 +13,7 @@ #include #include "sensors.h" #include "spi.h" +#include "i2c.h" int16_t spiTemp; // Thermocouple Temperature (from spi) int8_t boardTemp; // Board Temperature (from i2c) diff --git a/slave/slave/lib/serial.c b/slave/slave/lib/serial.c --- a/slave/slave/lib/serial.c +++ b/slave/slave/lib/serial.c @@ -1,34 +1,78 @@ -/* - * serial.c - * - * Created: 10/25/2012 3:19:49 PM - * Author: ethanzonca - */ +/* + * Master Firmware: USART Send/Recieve + * + * Wireless Observational Modular Aerial Network + * + * Ethan Zonca + * Matthew Kanning + * Kyle Ripperger + * Matthew Kroening + * + */ #include "serial.h" +#include "led.h" #include "../config.h" #include +#include +#include +// NOTE: USART ISRs for character reception are included in serparser.c void serial0_setup() { + //PORTD &= ~(1<>8); UBRR0L = (unsigned char)USART0_BAUD_PRESCALE; - /* Enable receiver and transmitter */ - UCSR0B = (1<>8); UBRR1L = (unsigned char)USART1_BAUD_PRESCALE; - /* Enable receiver and transmitter */ - UCSR1B = (1< +#include +#include "../config.h" +#include "serial.h" +#include "serparser.h" +#include "led.h" + +// Circular buffer for incoming data +uint8_t buffer[BUFFER_SIZE]; + +// Location of parser in the buffer +uint8_t bufferParsePosition = 0; + +// Location of receive byte interrupt in the buffer +volatile uint16_t bufferDataPosition = 0; + +// Parser state +uint8_t parserState = STATE_RESET; +uint8_t lastParserState = STATE_RESET; + +// Length of current payload data (and checksum) +uint8_t payloadLength = 0; + +// Data and checksum of most recent transmission +char receivedPayload[MAX_PAYLOAD_LEN]; + +// Payload type ID of the sensor of most recent transmission +char receivedPayloadType = 0; + +// Checksum to be calculated and then compared to the received checksum +char checksumCalc = 0; + +// Accessors +uint8_t getPayloadLength() +{ + return payloadLength; +} +uint8_t* getPayload() +{ + return receivedPayload; +} +uint8_t getPayloadType() { + return receivedPayloadType; +} + + +// Could inline if program space available +static void setParserState(uint8_t state) +{ + lastParserState = parserState; + parserState = state; + + // If resetting, clear vars + if(state == STATE_RESET) + { + payloadLength = 0; + checksumCalc = 0; + } + + // Every time we change state, we have parsed a byte + bufferParsePosition = (bufferParsePosition + 1) % BUFFER_SIZE; +} + +// Receive data on USART + +char debugBuff[16]; + + +ISR(USART0_RX_vect) +{ + buffer[bufferDataPosition % BUFFER_SIZE] = UDR0; + bufferDataPosition = (bufferDataPosition + 1) % BUFFER_SIZE; + //sprintf(debugBuff, "bdp: %d, bpp: %d \r\n", bufferDataPosition, bufferParsePosition); + //serial0_sendString((debugBuff)); +} + + + + +#define DEBUG + +// Parse data from circular buffer +int serparser_parse(void) +{ + + char byte; + + // Process first command (if any) on the circular buffer + while(bufferDataPosition != bufferParsePosition) + { + byte = buffer[bufferParsePosition]; + + // Reset + if(parserState == STATE_RESET) + { + if(byte == '[') // Start of frame; keep parsing + { + #ifdef DEBUG + serial0_sendString("start\r\n"); + #endif + setParserState(STATE_GETDATATYPE); + } + else // Not start of frame, reset + { + #ifdef DEBUG + serial0_sendString("invalid\r\n"); + #endif + setParserState(STATE_RESET); + return PARSERESULT_NODATA; // no valid start bit; better luck next time. run the function the next time around the main loop. + } + } + + // Get payload type ID + else if(parserState == STATE_GETDATATYPE) + { + #ifdef DEBUG + serial0_sendString("type\r\n"); + #endif + receivedPayloadType = byte - 0x30; // Store the type of data receiving + checksumCalc += byte; + setParserState(STATE_GETDATA); + } + + // Get payload data + else if(parserState == STATE_GETDATA) + { + if (byte == ']') // End of frame + { + #ifdef DEBUG + serial0_sendString("eof\r\n"); + sprintf(debugBuff, "%d B, sum=%d\r\n", payloadLength, checksumCalc); + serial0_sendString((debugBuff)); + #endif + + receivedPayload[payloadLength] = 0; // null-terminate string for atoi + + setParserState(STATE_GETCHECKSUM); + // Checksum is now after the close bracket to solve bug FS#29 + + + } + else // Still receiving data + { + #ifdef DEBUG + serial0_sendString("data\r\n"); + #endif + receivedPayload[payloadLength] = byte; + payloadLength++; + checksumCalc += byte; + + // Data buffer overrun protection + if(payloadLength > MAX_PAYLOAD_LEN) { + #ifdef DEBUG + serial0_sendString("ovf\r\n"); + #endif + setParserState(STATE_RESET); + return PARSERESULT_FAIL; + } + else { + // Set state. MUST call even though state is maintained to update parse position + setParserState(STATE_GETDATA); + return PARSERESULT_STILLPARSING; + } + + } + + } + else if(STATE_GETCHECKSUM) + { + // TODO: Compare checksums + if(byte == checksumCalc) { + #ifdef DEBUG + serial0_sendString("check\r\n"); + #endif + setParserState(STATE_RESET); + return PARSERESULT_PARSEOK; + } + else { + #ifdef DEBUG + serial0_sendString("bcheck\r\n"); + #endif + setParserState(STATE_RESET); + + return PARSERESULT_PARSEOK; + // !!!!!!!!!!!!!DEBUGGGGG ignore checksum ///// return PARSERESULT_FAIL; + } + + /* + if(bufferParsePosition == bufferDataPosition) + { + // We are at the end of the line. No more data to parse. + setParserState(STATE_RESET); + return PARSERESULT_PARSEOK; + } + else + { + setParserState(STATE_RESET); + // we could choose to keep parsing now, or parse the next message next loop around (better idea). + // return now so we hit it the next time around + return PARSERESULT_PARSEOK; + } + */ + } + } + return PARSERESULT_NODATA; + +} \ No newline at end of file diff --git a/slave/slave/lib/serparser.h b/slave/slave/lib/serparser.h new file mode 100644 --- /dev/null +++ b/slave/slave/lib/serparser.h @@ -0,0 +1,43 @@ +/* + * Master Firmware: Serial Parser + * + * Wireless Observational Modular Aerial Network + * + * Ethan Zonca + * Matthew Kanning + * Kyle Ripperger + * Matthew Kroening + * + */ + + +#ifndef SERPARSER_H_ +#define SERPARSER_H_ + +enum parseResults +{ + PARSERESULT_FAIL = 0, + PARSERESULT_NODATA, + PARSERESULT_STILLPARSING, + PARSERESULT_PARSEOK, +}; + +// Parser states +enum parseStates +{ + STATE_RESET = 0, + STATE_GETDATATYPE, + STATE_GETDATA, + STATE_GETCHECKSUM, +}; + + +// Accessors +uint8_t getPayloadLength(); +uint8_t* getPayload(); +uint8_t getPayloadType(); + +// Prototypes +int serparser_parse(void); + +#endif /* SERPARSER_H_ */ \ No newline at end of file diff --git a/slave/slave/slave.c b/slave/slave/slave.c --- a/slave/slave/slave.c +++ b/slave/slave/slave.c @@ -13,6 +13,7 @@ #include "config.h" +#include #include #include #include @@ -21,6 +22,7 @@ #include #include "modules.h" #include "lib/serial.h" +#include "lib/serparser.h" #include "lib/led.h" #include "lib/inputOutput.h" #include "lib/i2c.h" @@ -29,6 +31,9 @@ #include "lib/sensors.h" #include "lib/cameras.h" #include "lib/loopTimer.h" +#include "lib/masterComm.h" + + void micro_setup() { @@ -63,20 +68,28 @@ int main(void) while(1) - { + { + + // Master communication + //masterComm_check(); + + + // Main slave operations if ((time_millis() % SENSOR_LOOP) == 0) // Uses program timer to run every so often. Time interval defined in config.h { - sensors_readBoardTemp(); // Read board temperature sensor (Common on all slaves) (Data Read) - modules_run(moduleID); // Runs specific module functions (like data reading) - - io_regulateTemp(); // Gets board temperature and enables heater if below threshold + led_toggle(2); +// sensors_readBoardTemp(); // Read board temperature sensor (Common on all slaves) (Data Read) +// modules_run(moduleID); // Runs specific module functions (like data reading) - snprintf(buff,64,"|ModuleID: %u |BoardTemp: %i |Millis: %lu |Heater: %u\r\n",moduleID,sensors_getBoardTemp(),time_millis(),io_heaterStatus()); //DEBUG - serial0_sendString(buff); //DEBUG - - led_toggle(0); // Toggle LED0(Blue) to show loop running +// io_regulateTemp(); // Gets board temperature and enables heater if below threshold + led_toggle(1); +// snprintf(buff,64,"|ModuleID: %u |BoardTemp: %i |Millis: %lu |Heater: %u\r\n",moduleID,sensors_getBoardTemp(),time_millis(),io_heaterStatus()); //DEBUG +// snprintf(buff,64,"lol%i\r\n",sensors_getBoardTemp()); +// serial0_sendString(buff); //DEBUG + + led_toggle(0); // Toggle LED0(Blue) to show loop running + _delay_ms(1); // Delay to prevent the sensor loop from running again before time_millis changes } - } diff --git a/slave/slave/slave.cproj b/slave/slave/slave.cproj --- a/slave/slave/slave.cproj +++ b/slave/slave/slave.cproj @@ -22,7 +22,7 @@ 0 3.1.3 ISP - com.atmel.avrdbg.tool.ispmk2 + com.atmel.avrdbg.tool.avrdragon com.atmel.avrdbg.tool.simulator AVR Simulator @@ -67,6 +67,34 @@ True + + com.atmel.avrdbg.tool.avrdragon + AVR Dragon + 00A200035378 + true + false + + + + 127.0.0.1 + 64369 + False + + + ISP + + 0 + 1000000 + 2000000 + false + false + 0 + 0 + 0 + 0 + + + @@ -150,6 +178,12 @@ compile + + compile + + + compile + compile @@ -162,6 +196,12 @@ compile + + compile + + + compile + compile