diff options
author | Nicholas Corgan <nick.corgan@ettus.com> | 2014-07-17 11:50:50 -0700 |
---|---|---|
committer | Nicholas Corgan <nick.corgan@ettus.com> | 2014-07-23 07:37:32 -0700 |
commit | a6e18604befdb6a954542f7722c8d55424065621 (patch) | |
tree | 22168e6f4c41c931e38ccd07ff8881b56c8cd88a /firmware/octoclock/lib/serial.c | |
parent | 7423d1691fff3af08f8e42e3e09d8c8d9ec99fe8 (diff) | |
download | uhd-a6e18604befdb6a954542f7722c8d55424065621.tar.gz uhd-a6e18604befdb6a954542f7722c8d55424065621.tar.bz2 uhd-a6e18604befdb6a954542f7722c8d55424065621.zip |
OctoClock firmware upgrade, added host driver
* 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
Diffstat (limited to 'firmware/octoclock/lib/serial.c')
-rw-r--r-- | firmware/octoclock/lib/serial.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/firmware/octoclock/lib/serial.c b/firmware/octoclock/lib/serial.c new file mode 100644 index 000000000..298cdff8d --- /dev/null +++ b/firmware/octoclock/lib/serial.c @@ -0,0 +1,156 @@ +/* + * 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; +} |