mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
* OctoClock can communicate with UHD over Ethernet * Can read NMEA strings from GPSDO and send to host * Added multi_usrp_clock class for clock devices * uhd::device can now filter to return only USRP devices or clock devices * New OctoClock bootloader can accept firmware download over Ethernet * Added octoclock_burn_eeprom,octoclock_firmware_burner utilities * Added test_clock_synch example to show clock API
157 lines
4.0 KiB
C
157 lines
4.0 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <octoclock.h>
|
|
#include <serial.h>
|
|
|
|
#include <avr/pgmspace.h>
|
|
#include <util/delay.h>
|
|
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
|
|
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;
|
|
}
|