/* * Copyright 2014 Ettus Research LLC * * 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 3 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, see . */ #include #include #include #include #include #include #include void serial_init(volatile uint8_t* port, uint8_t index){ *port |= _BV(index); } static void _serial_tx_send(uint8_t* buffer, volatile uint8_t* port, uint8_t index){ const uint8_t delay = BAUD_115200_DELAY; uint8_t countdown; for(uint8_t i = 0; i < 10; ++i){ if(buffer[i]) *port |= _BV(index); else *port &= ~_BV(index); countdown = delay; while(--countdown) asm("nop"); } } static void _serial_tx_char(char c, volatile uint8_t* port, uint8_t index){ uint8_t buffer[10]; uint8_t i = 0; buffer[i++] = 0; // START for (int idx = 0; idx < 8; ++idx) buffer[i++] = (((uint8_t)(c) & ((uint8_t)1<<((idx)))) ? 0x01 : 0x00); // Endianness: 7- buffer[i++] = 1; // STOP _serial_tx_send(buffer, port, index); } void serial_tx_P(const char* message, volatile uint8_t* port, uint8_t index, bool newline){ char c = pgm_read_byte(message); if(c == '\0') return; do{ _serial_tx_char(c, port, index); c = pgm_read_byte(++message); } while(c != '\0'); if(newline){ _serial_tx_char('\r', port, index); _serial_tx_char('\n', port, index); } *port |= _BV(index); } void serial_tx(const char* message, volatile uint8_t* port, uint8_t index, bool newline){ if (message[0] == '\0') return; do { _serial_tx_char(*message, port, index); } while (*(++message) != '\0'); if (newline){ _serial_tx_char('\r', port, index); _serial_tx_char('\n', port, index); } *port |= _BV(index); } void serial_tx_byte(uint8_t byte, volatile uint8_t* port, uint8_t index, bool newline){ char ch[4]; ch[0] = '0' + (byte / 100); ch[1] = '0' + ((byte % 100) / 10); ch[2] = '0' + (byte % 10); ch[3] = '\0'; serial_tx(ch, port, index, newline); } void serial_tx_hex(uint8_t byte, volatile uint8_t* port, uint8_t index, bool newline){ char ch[3]; uint8_t _byte = byte >> 4; if (_byte < 10) ch[0] = '0' + _byte; else ch[0] = 'A' + (_byte - 10); byte &= 0x0F; if (byte < 10) ch[1] = '0' + byte; else ch[1] = 'A' + (byte - 10); ch[2] = '\0'; serial_tx(ch, port, index, newline); } char serial_rx_char(volatile uint8_t* port, uint8_t index){ char c = 0; const uint8_t delay = BAUD_115200_DELAY; uint8_t countdown; //Wait for character to appear, 0 will act as start marker while(*port & _BV(index)); //With start marker there, wait for next bit countdown = delay; while(--countdown) asm("nop"); for(uint8_t i = 0; i < 8; ++i){ if(*port & _BV(index)) c &= (uint8_t)(1 << i); countdown = delay; while(--countdown) asm("nop"); } return c; } //Assume ready (probably risky) char serial_rx_char_nowait(volatile uint8_t* port, uint8_t index){ char c = 0; const uint8_t delay = BAUD_115200_DELAY; uint8_t countdown; //Wait for start marker to pass countdown = delay; while(--countdown) asm("nop"); for(uint8_t i = 0; i < 8; ++i){ if(*port & _BV(index)) c &= (uint8_t)(1 << i); countdown = delay; while(--countdown) asm("nop"); } return c; }