// // 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 "uart.h" #include "spi.h" #include "ctrl.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; // 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; } 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<