diff --git a/mote/v2/avr/ctrl.c b/mote/v2/avr/ctrl.c index 2e21c37..453fd28 100644 --- a/mote/v2/avr/ctrl.c +++ b/mote/v2/avr/ctrl.c @@ -22,6 +22,7 @@ #include "global.h" #include "buffer.h" #include "ctrl.h" +#include "encode.h" cBuffer ctrlRxBuffer; // ctrl receive buffer cBuffer ctrlTxBuffer; // ctrl transmit buffer @@ -29,6 +30,8 @@ cBuffer ctrlTxBuffer; // ctrl transmit buffer static char ctrlRxData[CTRL_RX_BUFFER_SIZE]; static char ctrlTxData[CTRL_TX_BUFFER_SIZE]; +extern uint8_t phy_to_log[]; + void ctrlInit(void) { // initialize the CTRL receive buffer @@ -94,6 +97,11 @@ uint8_t ctrlGetFromRxBuffer(uint8_t* data) } } +void ctrlFlushReceiveBuffer(void) +{ + ctrlRxBuffer.datalength = 0; +} + void ctrlRxToTxLoop(void) { uint8_t data; @@ -102,3 +110,55 @@ void ctrlRxToTxLoop(void) ctrlAddToTxBuffer(data); } } + +void ctrlDecode(void) +{ + uint8_t cmd[2]; + + if (ctrlGetFromRxBuffer(cmd) && ctrlGetFromRxBuffer(cmd+1)) { + ctrlAddToTxBuffer(cmd[0]); + ctrlAddToTxBuffer(cmd[1]); + + switch (cmd[0]) { + case 'g': + ctrlCmdGet(cmd[1]); + break; + case 's': + ctrlCmdSet(cmd[1]); + break; + case 'c': + if (cmd[1] == 't') ctrlCmdCommit(); + break; + } + + ctrlAddToTxBuffer('.'); + } + + ctrlFlushReceiveBuffer(); +} + +void ctrlCmdGet(uint8_t cmd) +{ + uint8_t i; + uint16_t hex; + + switch (cmd) { + case 'p': + for (i = 0 ; i < MAX_SENSORS; i++) { + hex = btoh(phy_to_log[i]); + ctrlAddToTxBuffer((uint8_t)(hex >> 8)); + ctrlAddToTxBuffer((uint8_t)hex); + } + break; + } +} + +void ctrlCmdSet(uint8_t cmd) +{ + /* TODO */ +} + +void ctrlCmdCommit(void) +{ + /* TODO */ +} diff --git a/mote/v2/avr/ctrl.h b/mote/v2/avr/ctrl.h index 51db9b6..2cfec86 100644 --- a/mote/v2/avr/ctrl.h +++ b/mote/v2/avr/ctrl.h @@ -86,8 +86,19 @@ uint8_t ctrlAddToRxBuffer(uint8_t data); */ uint8_t ctrlGetFromRxBuffer(uint8_t* data); +/** + * Flush the ctrl Rx buffer. + * + */ +void ctrlFlushReceiveBuffer(void); + /** * Loop all bytes from the ctrl Rx to Tx buffer. * */ -void ctrlRxToTxLoop(void); +void ctrlRxToTxLoop(void); + +void ctrlDecode(void); +void ctrlCmdGet(uint8_t cmd); +void ctrlCmdSet(uint8_t cmd); +void ctrlCmdCommit(void); diff --git a/mote/v2/avr/encode.c b/mote/v2/avr/encode.c new file mode 100644 index 0000000..613ec33 --- /dev/null +++ b/mote/v2/avr/encode.c @@ -0,0 +1,27 @@ +#include + +// hex to binary/byte decoding +uint8_t htob(uint16_t hex) +{ + uint8_t low_hex = (uint8_t) hex; + uint8_t high_hex = (uint8_t) (hex >> 8); + uint8_t byte; + + byte = (high_hex > 0x40) ? (high_hex & 0x0F) + 9 : high_hex & 0x0F; + byte = byte << 4; + byte |= (low_hex > 0x40) ? (low_hex & 0x0F) + 9 : low_hex & 0x0F; + return byte; +} + +// binary/byte to hex encoding +uint16_t btoh(uint8_t byte) +{ + uint8_t low_nibble = (byte & 0x0F); + uint8_t high_nibble = (byte & 0xF0) >> 4; + uint16_t hex; + + hex = (high_nibble > 0x09) ? high_nibble - 9 + 0x60 : high_nibble + 0x30; + hex = hex << 8; + hex |= (low_nibble > 0x09) ? low_nibble - 9 + 0x60 : low_nibble + 0x30; + return hex; +} diff --git a/mote/v2/avr/encode.h b/mote/v2/avr/encode.h new file mode 100644 index 0000000..2d4bb5e --- /dev/null +++ b/mote/v2/avr/encode.h @@ -0,0 +1,2 @@ +uint8_t htob(uint16_t hex); +uint16_t btoh(uint8_t byte); diff --git a/mote/v2/avr/global.h b/mote/v2/avr/global.h index cdf887a..79dd61d 100644 --- a/mote/v2/avr/global.h +++ b/mote/v2/avr/global.h @@ -39,4 +39,6 @@ #define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond +#define MAX_SENSORS 6 + #endif diff --git a/mote/v2/avr/main.c b/mote/v2/avr/main.c new file mode 100644 index 0000000..7b53fdc --- /dev/null +++ b/mote/v2/avr/main.c @@ -0,0 +1,264 @@ +// +// basiciotest.c : test code for the io and buffer ops of the UART and SPI ports +// +// Copyright (c) 2010 flukso.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// $Id$ + +#include +#include +#include + +#include + +#include "main.h" +#include "uart.h" +#include "spi.h" +#include "ctrl.h" +#include "global.h" +#include "encode.h" + +#define NO_OP_1 1 +#define NO_OP_2 2 +#define START_TX 4 +#define TRANSMIT 8 +#define HIGH_HEX 16 +#define TO_FROM_UART 32 +#define NEW_CTRL_MSG 64 + +#define SPI_END_OF_TX 0x00 +#define SPI_END_OF_MESSAGE '.' +#define SPI_FORWARD_TO_UART_PORT 'u' +#define SPI_FORWARD_TO_CTRL_PORT 'l' // 'l'ocal port + +volatile uint8_t spi_status, high_hex; + +uint8_t EEMEM first_EEPROM_byte_not_used_to_protect_from_brownout_corruption = 0x00; + +volatile struct event_struct EEMEM EEPROM_event = {0, 0}; +volatile struct event_struct event; + +uint8_t EEMEM EEPROM_phy_to_log[MAX_SENSORS] = {0, 1, 2, 3, 4, 5}; +uint8_t phy_to_log[MAX_SENSORS]; + +volatile struct sensor_struct EEMEM EEPROM_sensor[MAX_SENSORS]; +volatile struct sensor_struct sensor[MAX_SENSORS]; + +ISR(SPI_STC_vect) +{ + uint8_t spi_rx, rx, tx; + uint16_t spi_tx; + + // the SPI is double-buffered, requiring two NO_OPs when switching from Tx to Rx + if (spi_status & (NO_OP_1 | NO_OP_2)) { + spi_status--; + return; + } + + // do we have to transmit the first byte? + if (spi_status & START_TX) { + received_from_spi(SPI_FORWARD_TO_CTRL_PORT); + spi_status &= ~START_TX; + return; + } + + // are we in Tx mode? + if (spi_status & TRANSMIT) { + if (spi_status & HIGH_HEX) { + received_from_spi(high_hex); + spi_status &= ~HIGH_HEX; + return; + } + + if (spi_status & TO_FROM_UART) { + if (!uartReceiveByte(&tx)) { + received_from_spi(SPI_END_OF_TX); + spi_status &= ~TRANSMIT; + spi_status |= NO_OP_2; + return; + } + } + else { + if (ctrlGetFromTxBuffer(&tx)) { + if (tx == SPI_END_OF_MESSAGE) { + received_from_spi(tx); + return; + } + } + else { + received_from_spi(SPI_FORWARD_TO_UART_PORT); + spi_status |= TO_FROM_UART; + return; + } + } + + spi_tx = btoh(tx); + high_hex = (uint8_t)spi_tx; + spi_status |= HIGH_HEX; + received_from_spi((uint8_t)(spi_tx >> 8)); + return; + } + + // we're in Rx mode + switch (spi_rx = received_from_spi(0x00)) { + case SPI_END_OF_TX: + spi_status |= TRANSMIT | START_TX; + spi_status &= ~(HIGH_HEX | TO_FROM_UART); + break; + case SPI_END_OF_MESSAGE: + if (!(spi_status & TO_FROM_UART)) { + ctrlAddToRxBuffer(spi_rx); + spi_status |= NEW_CTRL_MSG; + } + break; + case SPI_FORWARD_TO_UART_PORT: + spi_status |= TO_FROM_UART; + break; + case SPI_FORWARD_TO_CTRL_PORT: + spi_status &= ~TO_FROM_UART; + break; + default: + if (spi_status & HIGH_HEX) { + rx = htob(((uint16_t)high_hex << 8) + spi_rx); + + if (spi_status & TO_FROM_UART) { + uartAddToTxBuffer(rx); + } + else { + ctrlAddToRxBuffer(rx); + } + } + else { + high_hex = spi_rx; + } + // toggle the HEX bit in spi_status + spi_status ^= HIGH_HEX; + } +} + +ISR(TIMER1_COMPA_vect) +{ + /* void */ +} + +ISR(ANALOG_COMP_vect) +{ + uint8_t i; + + PORTB |= (1< fTOV1 = 3686.4kHz / 65536 = 56.25Hz (DS p.134) + TCCR1B |= (1< 0 + // Set PB1=OC1A as output pin + DDRB |= (1<