diff --git a/c328.c b/c328.c index df1f922..6a34ec4 100644 --- a/c328.c +++ b/c328.c @@ -34,7 +34,7 @@ static uint16_t pkg_len = 64; /* Default is 64 according to datasheet */ /* Timeout counter */ volatile static uint8_t timeout_clk = 0; -void inline c3_tick(void) +inline void c3_tick(void) { if(timeout_clk) timeout_clk--; } diff --git a/gps.c b/gps.c index a386f83..b69db60 100644 --- a/gps.c +++ b/gps.c @@ -14,14 +14,90 @@ #include #include "gps.h" +#ifdef UBLOX5 +#include +#endif + /************* UART RX interrupt handler and buffer *************************/ +/* Timeout counter */ +volatile static uint8_t timeout_clk = 0; + +inline void gps_tick(void) +{ + if(timeout_clk) timeout_clk--; +} + /* The maximum length of the NMEA string is 82 characters */ #define RXBUFSIZE (82 + 1) /* Helper to convert uppercase hex ascii character to integer */ #define HTOI(c) (((c) - '0' > '9' ? (c) - 'A' + 10 : (c) - '0') & 0x0F) +#ifdef UBLOX5 + +#define UBXBUFSIZE (16) + +static volatile uint8_t ubx_rx[UBXBUFSIZE]; +static volatile uint8_t ubx_rx_len = 0; +static volatile uint8_t ubx_want_packet = 0; + +static inline void isr_ubx(uint8_t b) +{ + static uint8_t rx[UBXBUFSIZE]; + static uint8_t rx_len = 0; + static uint16_t pkt_len = 8; + static uint8_t ck_a = 0, ck_b = 0; + + rx[rx_len++] = b; + if(rx_len < 2) return; + + /* Should have received the sync pattern */ + if(rx_len == 2) + { + if(rx[0] != 0xB5 || rx[1] != 0x62) + { + /* Nope */ + rx[0] = rx[1]; + rx_len = 1; + } + + return; + } + + /* Update the checksum */ + if(rx_len <= pkt_len - 2) ck_b += ck_a += b; + + /* Add the payload data length to the packet size */ + if(rx_len == 6) + { + pkt_len += (rx[5] << 8) + rx[4]; + + /* Drop the packet if it's going to be too big for the buffer */ + if(pkt_len > UBXBUFSIZE) goto clear; + } + + /* Wait until the complete packet has been received */ + if(rx_len < pkt_len) return; + + /* The entire packet should now be in the buffer, test the checksum */ + if(rx[rx_len - 2] != ck_a) goto clear; + if(rx[rx_len - 1] != ck_b) goto clear; + + /* A valid packet has been received - copy it and set the flag */ + memcpy((void *) ubx_rx, rx, rx_len); + ubx_rx_len = rx_len; + ubx_want_packet = 0; + + /* Done with this packet */ +clear: + rx_len = 0; + pkt_len = 8; + ck_a = ck_b = 0; +} + +#endif + /* Received GPGGA lines are copied into this buffer by the interrupt */ static volatile char rxline[RXBUFSIZE]; static volatile char rx_lock = 0; @@ -36,7 +112,11 @@ ISR(USART1_RX_vect) uint8_t b; /* Read the received character */ - b = UDR1; + b = UDR1; + +#ifdef UBLOX5 + if(ubx_want_packet) isr_ubx(b); +#endif switch(b) { @@ -82,6 +162,17 @@ ISR(USART1_RX_vect) rx_have_checksum = 0; } +#ifdef UBLOX5 +static void tx_byte(uint8_t b) +{ + /* Wait for empty transmit buffer */ + while(!(UCSR1A & (1 << UDRE1))); + + /* Put data into buffer, sends the data */ + UDR1 = b; +} +#endif + /* Like atoi but for fixed point numbers. Processes at most n bytes and * returns a pointer the next position in the string. Reads dp decimal * places */ @@ -209,7 +300,52 @@ char gps_parse(gpsfix_t *gps) return(0); } -void gps_init() +#ifdef UBLOX5 +/* From the FSA03 guide on the ukhas wiki: * + * http://ukhas.org.uk/guides:falcom_fsa03 */ + +PROGMEM uint8_t ubx_setnav[] = { +0xB5,0x62,0x06,0x24,0x24,0x00,0xFF,0xFF,0x06,0x03,0x00,0x00,0x00,0x00,0x10,0x27, +0x00,0x00,0x05,0x00,0xFA,0x00,0xFA,0x00,0x64,0x00,0x2C,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x16,0xDC +}; + +PROGMEM uint8_t ubx_setnav_ack[] = { 0x05,0x01,0x02,0x00,0x06,0x24 }; + +char gps_ubx_init(void) +{ + uint8_t i; + + /* Send the prepared command */ + for(i = 0; i < sizeof(ubx_setnav); i++) + tx_byte(pgm_read_byte(&ubx_setnav[i])); + + /* Wait for a response */ + ubx_want_packet = 1; + + timeout_clk = 255; /* 0.85 seconds at 300hz */ + while(timeout_clk) + { + if(ubx_want_packet == 1) continue; + + /* Got a packet... the ACK for the command? */ + if(!memcmp_P((void *) &ubx_rx[2], ubx_setnav_ack, sizeof(ubx_setnav_ack))) + { + /* GPS device acknowledged the command */ + return(0); + } + + ubx_want_packet = 1; + } + + /* Timeout waiting for ACK packet */ + ubx_want_packet = 0; + + return(-1); +} +#endif + +void gps_init(void) { rxline[0] = '\0'; diff --git a/gps.h b/gps.h index a37f540..062bdb9 100644 --- a/gps.h +++ b/gps.h @@ -7,6 +7,12 @@ /* and redistribute it under the terms of this license. A */ /* copy should be included with this source. */ +#ifndef GPS_H +#define GPS_H + +/* Uncomment if using a u-blox 5 based GPS receiver */ +#define UBLOX5 1 + typedef struct { uint8_t hour; /* 0-23 */ @@ -28,6 +34,12 @@ typedef struct { } gpsfix_t; -extern void gps_init(); +extern void gps_init(void); extern char gps_parse(gpsfix_t *gps); +#ifdef UBLOX5 +extern char gps_ubx_init(void); +#endif + +#endif + diff --git a/hadie.c b/hadie.c index 1d51ae0..28ef6e1 100644 --- a/hadie.c +++ b/hadie.c @@ -163,17 +163,23 @@ int main(void) while(1) { - r = 10; - if(tx_image() == -1) { /* The camera goes to sleep while transmitting telemetry, * sync'ing here seems to prevent it. */ c3_sync(); + rtx_string_P(PSTR("\n")); r = 1; } + else + { + /* Put UBLOX5 GPS in proper nav mode */ + if(gps_ubx_init() != 0) + rtx_string_P(PSTR(PREFIX CALLSIGN ":GPS mode set failed\n")); + + r = 10; + } - rtx_string_P(PSTR("\n")); for(; r > 0; r--) tx_telemetry(); } diff --git a/rtty.c b/rtty.c index 11b10d5..a8cd7a6 100644 --- a/rtty.c +++ b/rtty.c @@ -15,12 +15,13 @@ #include #include "rtty.h" -/* For camera timeout */ -#include "c328.h" +/* For camera and GPS timeout */ +extern inline void c3_tick(void); +extern inline void gps_tick(void); /* MARK = Upper tone, Idle, bit */ #define TXPIN (1 << 0) /* PB0 */ -#define TXENABLE (1 << 1) /* PB1 */ +#define TXENABLE (1 << 2) /* PB2 */ #define TXBIT(b) PORTB = (PORTB & ~TXPIN) | ((b) ? TXPIN : 0) @@ -39,7 +40,8 @@ ISR(TIMER0_COMPA_vect) { case 0: b = 0; break; /* Start bit */ case 9: b = 1; break; /* Stop bit */ - case 10: b = 1; TCNT0 += OCR0A >> 1; bit = 0; break; /* Stop bit 0.5 */ + //case 10: b = 1; TCNT0 += OCR0A >> 1; bit = 0; break; /* Stop bit 0.5 */ + case 10: b = 1; bit = 0; break; /* Stop bit part 2 */ default: b = byte & 1; byte >>= 1; break; } @@ -52,11 +54,12 @@ ISR(TIMER0_COMPA_vect) txlen--; } - /* Camera timeout tick */ + /* Camera and GPS timeout tick */ c3_tick(); + gps_tick(); } -void rtx_init() +void rtx_init(void) { /* RTTY is driven by TIMER0 in CTC mode */ TCCR0A = _BV(WGM01); /* Mode 2, CTC */ @@ -70,7 +73,7 @@ void rtx_init() DDRB |= TXPIN | TXENABLE; } -void inline rtx_wait() +void inline rtx_wait(void) { /* Wait for interrupt driven TX to finish */ while(txlen > 0) while(txlen > 0); diff --git a/rtty.h b/rtty.h index 521ee3f..eea29d1 100644 --- a/rtty.h +++ b/rtty.h @@ -13,8 +13,8 @@ #include #include -extern void rtx_init(); -extern void inline rtx_wait(); +extern void rtx_init(void); +extern void inline rtx_wait(void); extern void rtx_data(uint8_t *data, size_t length); extern void rtx_data_P(PGM_P data, size_t length); extern void rtx_string(char *s);