From 4827565bc8f397c451fb504acb04820535130ce5 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Mon, 4 Feb 2019 17:02:19 +0100 Subject: [PATCH] GPS driver implemented --- Makefile | 5 +- device.h | 10 +- hardware/Bluetooth.c | 2 +- hardware/GPS.c | 289 ++++++++++++++++++++++++++++++++++++++ hardware/GPS.h | 67 +++++++++ hardware/Serial.c | 324 +++++++++++++++++++++++++++++++------------ hardware/Serial.h | 37 +++-- hardware/UserIO.c | 6 +- main.c | 3 + protocol/KISS.c | 4 +- 10 files changed, 634 insertions(+), 113 deletions(-) create mode 100644 hardware/GPS.c create mode 100644 hardware/GPS.h diff --git a/Makefile b/Makefile index b0fb9f4..edfccdb 100755 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ TARGET = images/OpenModem OPT = s FORMAT = ihex -SRC = main.c hardware/Serial.c hardware/AFSK.c hardware/VREF.c hardware/LED.c hardware/UserIO.c hardware/SD.c hardware/sdcard/diskio.c hardware/sdcard/ff.c hardware/sdcard/ffsystem.c hardware/sdcard/ffunicode.c hardware/Bluetooth.c util/CRC-CCIT.c protocol/AX25.c protocol/KISS.c +SRC = main.c hardware/Serial.c hardware/AFSK.c hardware/VREF.c hardware/LED.c hardware/UserIO.c hardware/SD.c hardware/sdcard/diskio.c hardware/sdcard/ff.c hardware/sdcard/ffsystem.c hardware/sdcard/ffunicode.c hardware/Bluetooth.c hardware/GPS.c util/CRC-CCIT.c protocol/AX25.c protocol/KISS.c # List Assembler source files here. @@ -36,10 +36,11 @@ CFLAGS += -std=gnu99 ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs # Optional linker flags. +# Previous: LDFLAGS = -Wl,-Map=$(TARGET).map,--cref # -Wl,...: tell GCC to pass this to linker. # -Map: create map file # --cref: add cross reference to map file -LDFLAGS = -Wl,-Map=$(TARGET).map,--cref +LDFLAGS = -Wl,-u,vfprintf,-lprintf_flt,-Map=$(TARGET).map,--cref # Additional libraries LDFLAGS += -lm diff --git a/device.h b/device.h index af08522..e71e1fb 100755 --- a/device.h +++ b/device.h @@ -27,7 +27,8 @@ #define TX_MAXWAIT 2UL #define CONFIG_QUEUE_SIZE 6000 // TODO: Optimise this by saving ram other places, add SD queue #define CONFIG_QUEUE_MAX_LENGTH 15 -#define CONFIG_SERIAL_BUFFER_SIZE 1536 // TODO: Tune this, what is actually required? +#define CONFIG_UART0_BUFFER_SIZE 1536 // TODO: Tune this, what is actually required? +#define CONFIG_UART1_BUFFER_SIZE 128 #define CONFIG_SERIAL_TIMEOUT_MS 10 #define CONFIG_BENCHMARK_MODE false @@ -80,6 +81,11 @@ #define BT_MODE 3 #define BT_RTS 4 + #define GPS_DDR DDRA + #define GPS_PORT PORTA + #define GPS_INPUT PINA + #define GPS_EN_PIN 5 + #define USR_IO_DDR DDRA #define USR_IO_PORT PORTA #define USR_IO_1 1 @@ -91,7 +97,6 @@ #endif /* - PA0 ANALOG_IN PA1 USR_1 PA2 USR_2 @@ -127,5 +132,4 @@ PD4 PTT_NEG PD5 PTT_SIG PD6 REF_DAC PD7 REF_ADC - */ \ No newline at end of file diff --git a/hardware/Bluetooth.c b/hardware/Bluetooth.c index 5dfd92f..7a96a44 100644 --- a/hardware/Bluetooth.c +++ b/hardware/Bluetooth.c @@ -13,7 +13,7 @@ void bluetooth_init(void) { // Check module RTS pin is pulled low if (!(BT_INPUT &_BV(BT_RTS))) { // Reconfigure UART to 9600 baud and issue reset - serial_setbaudrate_9600(); + serial_setbaudrate_9600(0); delay_ms(BT_AT_DELAY*2); printf(PSTR("AT")); printf(PSTR("AT+FACTORYRESET\r\n")); diff --git a/hardware/GPS.c b/hardware/GPS.c new file mode 100644 index 0000000..34ae9e9 --- /dev/null +++ b/hardware/GPS.c @@ -0,0 +1,289 @@ +#include "GPS.h" + +Serial *serial; + +bool gps_installed = false; +bool gps_power = true; + +uint8_t nmea_read_length = 0; +char nmea_input_buf[NMEA_MAX_LENGTH]; +char nmea_parse_buf[NMEA_MAX_LENGTH]; + +bool gps_detect(void) { + GPS_DDR &= ~_BV(GPS_EN_PIN); + return (GPS_INPUT & _BV(GPS_EN_PIN)); +} + +void gps_powerup(void) { + GPS_PORT |= _BV(GPS_EN_PIN); +} + +void gps_powerdown(void) { + GPS_PORT &= ~_BV(GPS_EN_PIN); +} + +bool gps_enabled(void) { + return gps_power; +} + +void gps_init(Serial *ser) { + serial = ser; + memset(nmea_input_buf, 0, sizeof(nmea_input_buf)); + memset(nmea_parse_buf, 0, sizeof(nmea_parse_buf)); + + gps_speed_knots = 0; + gps_speed_kmh = 0; + gps_bearing = 0; + + if (gps_detect()) { + gps_installed = true; + + serial_setbaudrate_9600(1); + gps_send_command(PMTK_SET_BAUD_57600); + serial_setbaudrate_57600(1); + + gps_send_command(PMTK_API_SET_FIX_CTL_1HZ); + gps_send_command(PMTK_SET_NMEA_OUTPUT_RMCGGA); + + GPS_DDR |= _BV(GPS_EN_PIN); + if (gps_enabled()) { gps_powerup(); } else { gps_powerdown(); } + + } else { + gps_installed = false; + gps_power = false; + } +} + +void gps_update_rtc(void) { + // TODO: implement this +} + +void gps_jobs(void) { + if (gps_enabled()) { gps_powerup(); } else { gps_powerdown(); } +} + +void gps_send_command(const char *cmd) { + fprintf_P(&serial->uart1, cmd); +} + +void gps_nmea_parse(uint8_t sentence_length) { + if (sentence_length > 4) { + if (nmea_parse_buf[sentence_length-4] == '*') { + uint16_t checksum = gps_nmea_parse_hex(nmea_parse_buf[sentence_length-3]); + checksum *= 16; + checksum += gps_nmea_parse_hex(nmea_parse_buf[sentence_length-2]); + + for (uint8_t i=1; i < sentence_length-4; i++) { + checksum ^= nmea_parse_buf[i]; + } + + if (checksum != 0) { + return; + } else { + // Parse GGA sentence + if (strstr(nmea_parse_buf, "$GPGGA")) { + char *pointer = nmea_parse_buf; + + // Parse UTC time + pointer = strchr(pointer, ',')+1; + uint32_t nmea_time = (float)atof(pointer); + + // Parse latitude + pointer = strchr(pointer, ',')+1; + char nmea_lat_deg_str[3]; + nmea_lat_deg_str[0] = pointer[0]; + nmea_lat_deg_str[1] = pointer[1]; + nmea_lat_deg_str[2] = '\0'; + + char nmea_lat_min_str[3]; + nmea_lat_min_str[0] = pointer[2]; + nmea_lat_min_str[1] = pointer[3]; + nmea_lat_min_str[2] = '\0'; + + char nmea_lat_dec_str[5]; + nmea_lat_dec_str[0] = pointer[5]; + nmea_lat_dec_str[1] = pointer[6]; + nmea_lat_dec_str[2] = pointer[7]; + nmea_lat_dec_str[3] = pointer[8]; + nmea_lat_dec_str[4] = '\0'; + + // Parse latitude sign + pointer = strchr(pointer, ',')+1; + char nmea_lat_sign = pointer[0]; + + // Parse longtitude + pointer = strchr(pointer, ',')+1; + char nmea_lon_deg_str[4]; + nmea_lon_deg_str[0] = pointer[0]; + nmea_lon_deg_str[1] = pointer[1]; + nmea_lon_deg_str[2] = pointer[2]; + nmea_lon_deg_str[3] = '\0'; + + char nmea_lon_min_str[3]; + nmea_lon_min_str[0] = pointer[3]; + nmea_lon_min_str[1] = pointer[4]; + nmea_lon_min_str[2] = '\0'; + + char nmea_lon_dec_str[5]; + nmea_lon_dec_str[0] = pointer[6]; + nmea_lon_dec_str[1] = pointer[7]; + nmea_lon_dec_str[2] = pointer[8]; + nmea_lon_dec_str[3] = pointer[9]; + nmea_lon_dec_str[4] = '\0'; + + // Parse longtitude sign + pointer = strchr(pointer, ',')+1; + char nmea_lon_sign = pointer[0]; + + // Get fix quality + pointer = strchr(pointer, ',')+1; + uint8_t nmea_fix = atoi(pointer); + if (nmea_fix == 1) { + gps_fix = true; + } else { + gps_fix = false; + } + + if (gps_fix) { + // Set times + gps_t_hour = nmea_time / 10000; + gps_t_minute = (nmea_time % 10000) / 100; + gps_t_second = (nmea_time % 100); + gps_update_rtc(); + + // Set latitude and longtitude + gps_lat_degrees = atoi(nmea_lat_deg_str); + gps_lat_minutes = atoi(nmea_lat_min_str); + gps_lat_seconds = (atoi(nmea_lat_dec_str)/10000.0)*60.0; + gps_lon_degrees = atoi(nmea_lon_deg_str); + gps_lon_minutes = atoi(nmea_lon_min_str); + gps_lon_seconds = (atoi(nmea_lon_dec_str)/10000.0)*60.0; + gps_lat = gps_lat_degrees + (gps_lat_minutes/60.0) + (gps_lat_seconds/3600.0); + gps_lon = gps_lon_degrees + (gps_lon_minutes/60.0) + (gps_lon_seconds/3600.0); + + // Get satellites + pointer = strchr(pointer, ',')+1; + gps_sats = atoi(pointer); + + // Get horizontal dilution of position + pointer = strchr(pointer, ',')+1; + gps_hdop = atof(pointer); + + // Get altitude + pointer = strchr(pointer, ',')+1; + gps_altitude = atof(pointer); + + // Ignore altitude unit reference + pointer = strchr(pointer, ',')+1; + + // Get geoid height + pointer = strchr(pointer, ',')+1; + gps_geoid_height = atof(pointer); + // TODO: Check this calculation + gps_height_above_msl = gps_geoid_height + gps_altitude; + + // Ignore geoid height unit reference + pointer = strchr(pointer, ',')+1; + + gps_lat_sign = nmea_lat_sign; + gps_lon_sign = nmea_lon_sign; + gps_lat *= (gps_lat_sign == 'N' ? 1 : -1); + gps_lon *= (gps_lon_sign == 'E' ? 1 : -1); + + // TODO: Remove this + // if (gps_fix) { + // printf("GPS fix: %d\r\n", nmea_fix); + // printf("GPS satellites: %d\r\n", gps_sats); + // printf("GPS latitude: %d\" %d' %.2fs %c\r\n", gps_lat_degrees, gps_lat_minutes, gps_lat_seconds, gps_lat_sign); + // printf("GPS longtitude: %d\" %d' %.2fs %c\r\n", gps_lon_degrees, gps_lon_minutes, gps_lon_seconds, gps_lon_sign); + // printf("GPS coords: %.6f,%.6f\r\n", gps_lat, gps_lon); + // printf("GPS speed %.2f Km/h\r\n", gps_speed_kmh); + // printf("GPS speed %.2f knots\r\n", gps_speed_knots); + // printf("GPS bearing %.2f\r\n", gps_bearing); + // printf("GPS height above MSL: %.2f\r\n", gps_height_above_msl); + // printf("GPS altitude: %.2f\r\n", gps_altitude); + // printf("GPS geoid height: %.2f\r\n", gps_geoid_height); + // printf("GPS HDOP: %.2f\r\n", gps_hdop); + // printf("GPS time %d:%d:%d UTC\r\n", gps_t_hour, gps_t_minute, gps_t_second); + // } else { + // printf("No GPS fix"); + // } + } + } + + // Parse RMC sentence + if (strstr(nmea_parse_buf, "$GPRMC")) { + if (gps_fix) { + char *pointer = nmea_parse_buf; + + // Ignore UTC time + pointer = strchr(pointer, ',')+1; + + // Ignore navigation receiver warning + pointer = strchr(pointer, ',')+1; + + // Ignore latitude + pointer = strchr(pointer, ',')+1; + + // Ignore latitude sign + pointer = strchr(pointer, ',')+1; + + // Ignore longtitude + pointer = strchr(pointer, ',')+1; + + // Ignore longtitude sign + pointer = strchr(pointer, ',')+1; + + // Get ground speed + pointer = strchr(pointer, ',')+1; + gps_speed_knots = atof(pointer); + gps_speed_kmh = gps_speed_knots * 1.852; + + // Get bearing + pointer = strchr(pointer, ',')+1; + gps_bearing = atof(pointer); + } else { + gps_speed_knots = 0; + gps_speed_kmh = 0; + } + } + } + } + } +} + +void gps_serial_callback(char byte) { + if (byte == '\n') { + for (uint8_t i = 0; i < NMEA_MAX_LENGTH; i++) + nmea_parse_buf[i] = nmea_input_buf[i]; + + memset(nmea_input_buf, 0, sizeof(nmea_input_buf)); + + gps_nmea_parse(nmea_read_length); + nmea_read_length = 0; + } else { + if (nmea_read_length < NMEA_MAX_LENGTH) { + nmea_input_buf[nmea_read_length++] = byte; + } + } +} + +void gps_poll(void) { + while (!fifo_isempty_locked(&uart1FIFO)) { + char sbyte = fifo_pop_locked(&uart1FIFO); + gps_serial_callback(sbyte); + } +} + +uint8_t gps_nmea_parse_hex(char c) { + if (c < '0') + return 0; + if (c <= '9') + return c - '0'; + if (c < 'A') + return 0; + if (c <= 'F') + return (c - 'A')+10; + + return 0; +} diff --git a/hardware/GPS.h b/hardware/GPS.h new file mode 100644 index 0000000..c9166f3 --- /dev/null +++ b/hardware/GPS.h @@ -0,0 +1,67 @@ +#ifndef GPS_H +#define GPS_H + +#include +#include +#include +#include +#include +#include "device.h" +#include "util/time.h" +#include "hardware/serial.h" + +#define NMEA_MAX_LENGTH 128 + +#define PMTK_SET_BAUD_57600 PSTR("$PMTK251,57600*2C\r\n") +#define PMTK_SET_BAUD_9600 PSTR("$PMTK251,9600*17\r\n") +#define PMTK_SET_NMEA_OUTPUT_RMCONLY PSTR("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n") +#define PMTK_SET_NMEA_OUTPUT_RMCGGA PSTR("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n") +#define PMTK_SET_NMEA_OUTPUT_NONE PSTR("$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n") +#define PMTK_SET_NMEA_OUTPUT_ALL PSTR("$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n") +#define PMTK_API_SET_FIX_CTL_200_mHZ PSTR("$PMTK300,5000,0,0,0,0*18\r\n") +#define PMTK_API_SET_FIX_CTL_1HZ PSTR("$PMTK300,1000,0,0,0,0*1C\r\n") +#define PGCMD_ANTENNA PSTR("$PGCMD,33,1*6C\r\n") +#define PGCMD_NOANTENNA PSTR("$PGCMD,33,0*6D\r\n") + +void gps_init(Serial *ser); +bool gps_enabled(void); +void gps_poll(void); +void gps_jobs(void); +void gps_send_command(const char *cmd); +uint8_t gps_parse_nmea(char *nmea); +uint8_t gps_nmea_parse_hex(char c); + +uint8_t gps_t_year; +uint8_t gps_t_month; +uint8_t gps_t_day; +uint8_t gps_t_hour; +uint8_t gps_t_minute; +uint8_t gps_t_second; + +int gps_lat_degrees; +int gps_lat_minutes; +float gps_lat_seconds; +float gps_lat; + +int gps_lon_degrees; +int gps_lon_minutes; +float gps_lon_seconds; +float gps_lon; + +float gps_geoid_height; +float gps_altitude; +float gps_height_above_msl; +float gps_speed_knots; +float gps_speed_kmh; +float gps_speed_mph; +float gps_bearing; +float gps_magvariation; +float gps_hdop; +char gps_lat_sign; +char gps_lon_sign; +char gps_mag_char; +bool gps_fix; +uint8_t gps_fix_quality; +uint8_t gps_sats; + +#endif \ No newline at end of file diff --git a/hardware/Serial.c b/hardware/Serial.c index 1788f9c..0b76fc9 100755 --- a/hardware/Serial.c +++ b/hardware/Serial.c @@ -6,25 +6,36 @@ extern volatile uint8_t queue_height; void serial_init(Serial *serial) { memset(serial, 0, sizeof(*serial)); - memset(serialBuf, 0, sizeof(serialBuf)); + memset(uart0Buf, 0, sizeof(uart0Buf)); + memset(uart1Buf, 0, sizeof(uart1Buf)); - serial_setbaudrate_115200(); + serial_setbaudrate_115200(0); + serial_setbaudrate_115200(1); // Set to 8-bit data, enable RX and TX, enable receive interrupt UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0); + UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); + UCSR1B = _BV(RXEN1) | _BV(TXEN1) | _BV(RXCIE1); + FILE uart0_fd = FDEV_SETUP_STREAM(uart0_putchar, uart0_getchar, _FDEV_SETUP_RW); + FILE uart1_fd = FDEV_SETUP_STREAM(uart1_putchar, uart1_getchar, _FDEV_SETUP_RW); serial->uart0 = uart0_fd; + serial->uart1 = uart1_fd; - fifo_init(&serialFIFO, serialBuf, sizeof(serialBuf)); + fifo_init(&uart0FIFO, uart0Buf, sizeof(uart0Buf)); + fifo_init(&uart1FIFO, uart1Buf, sizeof(uart1Buf)); } bool serial_available(uint8_t index) { if (index == 0) { if (UCSR0A & _BV(RXC0)) return true; + } else if (index == 1) { + if (UCSR1A & _BV(RXC1)) return true; } + return false; } @@ -38,167 +49,302 @@ int uart0_putchar(char c, FILE *stream) { int uart0_getchar(FILE *stream) { loop_until_bit_is_set(UCSR0A, RXC0); + LED_COM_ON(); return UDR0; } char uart0_getchar_nowait(void) { if (!(UCSR0A & _BV(RXC0))) return EOF; + LED_COM_ON(); return UDR0; } +int uart1_putchar(char c, FILE *stream) { + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; + return 1; +} + +int uart1_getchar(FILE *stream) { + loop_until_bit_is_set(UCSR1A, RXC1); + return UDR1; +} + +char uart1_getchar_nowait(void) { + if (!(UCSR1A & _BV(RXC1))) return EOF; + return UDR1; +} + ISR(USART0_RX_vect) { if (serial_available(0)) { LED_COM_ON(); - if (!fifo_isfull(&serialFIFO)) { + if (!fifo_isfull(&uart0FIFO)) { char c = uart0_getchar_nowait(); - fifo_push(&serialFIFO, c); + fifo_push(&uart0FIFO, c); } } } -void serial_setbaudrate_1200(void) { +ISR(USART1_RX_vect) { + if (serial_available(1)) { + if (!fifo_isfull(&uart1FIFO)) { + char c = uart1_getchar_nowait(); + fifo_push(&uart1FIFO, c); + } + } +} + +void serial_setbaudrate_1200(uint8_t port) { #undef BAUD #define BAUD 1200 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_2400(void) { +void serial_setbaudrate_2400(uint8_t port) { #undef BAUD #define BAUD 2400 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_4800(void) { +void serial_setbaudrate_4800(uint8_t port) { #undef BAUD #define BAUD 4800 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_9600(void) { +void serial_setbaudrate_9600(uint8_t port) { #undef BAUD #define BAUD 9600 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_14400(void) { +void serial_setbaudrate_14400(uint8_t port) { #undef BAUD #define BAUD 14400 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_19200(void) { +void serial_setbaudrate_19200(uint8_t port) { #undef BAUD #define BAUD 19200 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_28800(void) { +void serial_setbaudrate_28800(uint8_t port) { #undef BAUD #define BAUD 28800 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_38400(void) { +void serial_setbaudrate_38400(uint8_t port) { #undef BAUD #define BAUD 38400 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_57600(void) { +void serial_setbaudrate_57600(uint8_t port) { #undef BAUD #define BAUD 57600 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_76800(void) { +void serial_setbaudrate_76800(uint8_t port) { #undef BAUD #define BAUD 76800 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_115200(void) { +void serial_setbaudrate_115200(uint8_t port) { #undef BAUD #define BAUD 115200 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } -void serial_setbaudrate_230400(void) { +void serial_setbaudrate_230400(uint8_t port) { #undef BAUD #define BAUD 230400 #include - UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; - #if USE_2X - UCSR0A |= _BV(U2X0); - #else - UCSR0A &= ~(_BV(U2X0)); - #endif + if (port == 0) { + UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; + #if USE_2X + UCSR0A |= _BV(U2X0); + #else + UCSR0A &= ~(_BV(U2X0)); + #endif + } else if (port == 1) { + UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE; + #if USE_2X + UCSR1A |= _BV(U2X0); + #else + UCSR1A &= ~(_BV(U2X0)); + #endif + } } diff --git a/hardware/Serial.h b/hardware/Serial.h index a044a55..417c47e 100755 --- a/hardware/Serial.h +++ b/hardware/Serial.h @@ -11,28 +11,37 @@ typedef struct Serial { FILE uart0; + FILE uart1; } Serial; -FIFOBuffer serialFIFO; -uint8_t serialBuf[CONFIG_SERIAL_BUFFER_SIZE]; +FIFOBuffer uart0FIFO; +uint8_t uart0Buf[CONFIG_UART0_BUFFER_SIZE]; + +FIFOBuffer uart1FIFO; +uint8_t uart1Buf[CONFIG_UART1_BUFFER_SIZE]; void serial_init(Serial *serial); bool serial_available(uint8_t index); + int uart0_putchar(char c, FILE *stream); int uart0_getchar(FILE *stream); char uart0_getchar_nowait(void); -void serial_setbaudrate_1200(void); -void serial_setbaudrate_2400(void); -void serial_setbaudrate_4800(void); -void serial_setbaudrate_9600(void); -void serial_setbaudrate_14400(void); -void serial_setbaudrate_19200(void); -void serial_setbaudrate_28800(void); -void serial_setbaudrate_38400(void); -void serial_setbaudrate_57600(void); -void serial_setbaudrate_76800(void); -void serial_setbaudrate_115200(void); -void serial_setbaudrate_230400(void); +int uart1_putchar(char c, FILE *stream); +int uart1_getchar(FILE *stream); +char uart1_getchar_nowait(void); + +void serial_setbaudrate_1200(uint8_t port); +void serial_setbaudrate_2400(uint8_t port); +void serial_setbaudrate_4800(uint8_t port); +void serial_setbaudrate_9600(uint8_t port); +void serial_setbaudrate_14400(uint8_t port); +void serial_setbaudrate_19200(uint8_t port); +void serial_setbaudrate_28800(uint8_t port); +void serial_setbaudrate_38400(uint8_t port); +void serial_setbaudrate_57600(uint8_t port); +void serial_setbaudrate_76800(uint8_t port); +void serial_setbaudrate_115200(uint8_t port); +void serial_setbaudrate_230400(uint8_t port); #endif \ No newline at end of file diff --git a/hardware/UserIO.c b/hardware/UserIO.c index e02de1a..9802ae7 100644 --- a/hardware/UserIO.c +++ b/hardware/UserIO.c @@ -2,8 +2,10 @@ #include "hardware/Bluetooth.h" void usrio_init(void) { - USR_IO_DDR |= _BV(USR_IO_1) | _BV(USR_IO_2); - // TODO: Add BT module detect and set up other pins accordingly + USR_IO_DDR |= _BV(USR_IO_1) | _BV(USR_IO_2); + if (!bluetooth_enabled()) { + USR_IO_DDR |= _BV(USR_IO_3) | _BV(USR_IO_4); + } } bool usrio_1(void) { diff --git a/main.c b/main.c index 681a6e7..f066434 100755 --- a/main.c +++ b/main.c @@ -14,6 +14,7 @@ #include "hardware/UserIO.h" #include "hardware/SD.h" #include "hardware/Bluetooth.h" +#include "hardware/GPS.h" #include "protocol/AX25.h" #include "protocol/KISS.h" #include "util/time.h" @@ -69,6 +70,7 @@ void init(void) { kiss_init(&AX25, &modem, &serial); sd_init(); bluetooth_init(); + gps_init(&serial); usrio_init(); system_check(); @@ -83,6 +85,7 @@ int main (void) { kiss_poll(); kiss_csma(); sd_jobs(); + gps_poll(); } return(0); diff --git a/protocol/KISS.c b/protocol/KISS.c index e8c6583..984203f 100755 --- a/protocol/KISS.c +++ b/protocol/KISS.c @@ -50,8 +50,8 @@ void kiss_init(AX25Ctx *ax25, Afsk *afsk, Serial *ser) { } void kiss_poll(void) { - while (!fifo_isempty_locked(&serialFIFO)) { - char sbyte = fifo_pop_locked(&serialFIFO); + while (!fifo_isempty_locked(&uart0FIFO)) { + char sbyte = fifo_pop_locked(&uart0FIFO); kiss_serialCallback(sbyte); last_serial_read = timer_clock(); }