/*
* 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;
}