Changeset - c1b1dfc6c2f4
[Not reviewed]
default
2 5 6
Ethan Zonca - 10 years ago 2016-05-15 16:22:12
ez@ethanzonca.com
Modularize code a bit and switch to new GPS setup. Untested on hardware.
11 files changed with 439 insertions and 905 deletions:
0 comments (0 inline, 0 general)
Makefile
Show inline comments
 
@@ -11,7 +11,7 @@
 
BUILD_NUMBER ?= 0
 

	
 
# SOURCES: list of sources in the user application
 
SOURCES = main.c  adc.c gpio.c i2c.c interrupts.c usart.c  gps.c system_stm32f0xx.c
 
SOURCES = main.c  adc.c gpio.c i2c.c interrupts.c uart.c  gps.c system_stm32f0xx.c system.c wspr.c
 
# TARGET: name of the user application
 
TARGET = wsprhab-b$(BUILD_NUMBER)
 

	
inc/gps.h
Show inline comments
 
@@ -40,32 +40,20 @@ enum gps_state
 
    GPS_STATE_NOFIX
 
};
 

	
 
// Messages (REMOVEME?)
 
#define GGA_MESSAGE
 
#define RMC_MESSAGE
 
#define UKN_MESSAGE
 

	
 
void gps_init();
 

	
 
void gps_update_position();
 
void gps_update_time(uint8_t* hour, uint8_t* minute, uint8_t* second);
 
void gps_check_lock(uint8_t* lock, uint8_t* sats);
 
uint8_t gps_check_nav(void);
 

	
 

	
 
void gps_poweron(void);
 
void gps_poweroff(void);
 
void gps_init(void);
 
void gps_sendubx(uint8_t* data, uint8_t size);
 
char* get_longitudeTrimmed(void);
 
char* get_longitudeLSBs(void);
 
char* get_latitudeTrimmed(void);
 
char* get_latitudeLSBs(void);
 
char* get_timestamp(void);
 
char* get_gpsaltitude(void);
 
char* get_speedKnots(void);
 
char* get_course(void);
 
char* get_hdop(void);
 
uint16_t get_hdop_int_tenths(void);
 
char* get_sv(void);
 
char* get_dayofmonth(void);
 
uint8_t gps_hasfix(void);
 
void gps_process(void);
 

	
 
void gps_acquirefix(void);
 
uint8_t gps_getstate(void);
 
void gps_acquirefix(void);
 
void parse_gps_transmission(void);
 
void XORbyteWithChecksum(uint8_t byte);
 

	
 

	
 
#endif /* GPS_H_ */
inc/system.h
Show inline comments
 
new file 100644
 
#ifndef _SYSTEM_H
 
#define _SYSTEM_H
 

	
 
// Prototypes
 
void sysclk_init(void);
 
void enter_sleep(void);
 
void enter_deepsleep(void);
 

	
 
#endif
inc/uart.h
Show inline comments
 
file renamed from inc/usart.h to inc/uart.h
inc/wspr.h
Show inline comments
 
new file 100644
 
#ifndef _WSPR_H
 
#define _WSPR_H
 

	
 
// Prototypes
 
void wspr_init(void);
 
void wspr_sleep(void);
 
void wspr_wakeup(void);
 
void wspr_transmit(void);
 

	
 

	
 
#endif
src/gps.c
Show inline comments
 
@@ -4,187 +4,35 @@
 

	
 
#include "config.h"
 
#include "gpio.h"
 
#include "usart.h"
 
#include "uart.h"
 
#include "gps.h"
 

	
 
// Circular buffer for incoming data
 
uint8_t nmeaBuffer[NMEABUFFER_SIZE];
 

	
 
// Location of parser in the buffer
 
uint8_t nmeaBufferParsePosition = 0;
 

	
 
uint8_t skipBytes = 0;
 

	
 
//used to index data arrays during data collection
 
uint32_t numBytes = 0;
 

	
 
//variables to store data from transmission
 
//least significant digit is stored at location 0 of arrays
 
char tramsmissionType[7];
 
typedef struct _gps_data
 
{
 
    int32_t hdop;
 
    int32_t sats_in_view;
 
    int32_t speed;
 
    int32_t heading;
 

	
 

	
 
void gps_poweron(void)
 
{
 
    // NOTE: pchannel
 
    HAL_GPIO_WritePin(GPS_NOTEN, 0);
 
    uart_init();
 

	
 
    // Begin DMA reception
 
    HAL_UART_Receive_DMA(uart_gethandle(), nmeaBuffer, NMEABUFFER_SIZE);
 

	
 
}
 

	
 
void gps_poweroff(void)
 
{
 
    // NOTE: pchannel
 
    uart_deinit();
 
    HAL_GPIO_WritePin(GPS_NOTEN, 1);
 
}
 
    int32_t latitude;
 
    int32_t longitude;
 
    int32_t altitude;
 

	
 
char timestamp[12];	//hhmmss.ss
 
char* get_timestamp() 
 
{
 
	return timestamp;
 
}
 
	
 
char latitude[14];	//lllll.lla
 
char latitudeTmpTRIM[8];
 
char latitudeTmpLSB[4];
 
char* get_latitudeTrimmed() 
 
{
 
	strncpy(latitudeTmpTRIM, &latitude[0], 7);
 
	latitudeTmpTRIM[7] = 0x00;
 
	return latitudeTmpTRIM;
 
}
 
char* get_latitudeLSBs()
 
{
 
	strncpy(latitudeTmpLSB, &latitude[7], 3);
 
	latitudeTmpLSB[3] = 0x00;
 
	return latitudeTmpLSB;
 
}
 

	
 
char longitude[14];	//yyyyy.yyb
 
char longitudeTmpTRIM[9];
 
char longitudeTmpLSB[4];
 
    uint8_t hour;
 
    uint8_t minute;
 
    uint8_t second;
 

	
 
char* get_longitudeTrimmed() 
 
{
 
	strncpy(longitudeTmpTRIM, &longitude[0], 8);
 
	longitudeTmpTRIM[8] = 0x00;
 
	return longitudeTmpTRIM;
 
}
 
char* get_longitudeLSBs()
 
{
 
	strncpy(longitudeTmpLSB, &longitude[8], 3);
 
	longitudeTmpLSB[3] = 0x00;
 
	return longitudeTmpLSB;
 
}
 
} gps_data_t;
 

	
 
char quality;		//quality for GGA and validity for RMC
 
char numSatellites[4];
 
char* get_sv() 
 
{
 
	return numSatellites;
 
}
 

	
 
char hdop[6];		//xx.x
 
char* get_hdop() 
 
{
 
	return hdop;
 
}
 
gps_data_t position;
 

	
 
uint16_t get_hdop_int_tenths(void)
 
{
 
    // If only one digit before decimal
 
    if(hdop[1] == '.')
 
    {
 
        return (hdop[0]-0x30)*10 + (hdop[2]-0x30);
 
    }
 

	
 
    // Return normal hdop
 
    return (hdop[0]-0x30)*100 + (hdop[1]-0x30)*10 + (hdop[2]-0x30);
 
}
 

	
 
char altitude[10];	//xxxxxx.x
 
char* get_gpsaltitude()
 
{
 
	return altitude;
 
}
 

	
 
//char wgs84Height[8];	//sxxx.x
 
//char lastUpdated[8];	//blank - included for testing
 
//char stationID[8];	//blank - included for testing
 
char checksum[3];	//xx
 

	
 
char knots[8];		//xxx.xx
 
char* get_speedKnots() 
 
{
 
	return knots;
 
}
 

	
 
char course[8];		//xxx.x
 
char* get_course() 
 
{
 
	return course;
 
}
 
	
 
char dayofmonth[9];	//ddmmyy
 
char* get_dayofmonth() 
 
{
 
	return dayofmonth;
 
}
 
// Private methods
 
static void gps_ubx_checksum(uint8_t* data, uint8_t len, uint8_t* cka, uint8_t* ckb);
 
static uint8_t _gps_verify_checksum(uint8_t* data, uint8_t len);
 

	
 

	
 
uint8_t gps_hadfix = 0;
 

	
 
uint8_t gps_hasfix() 
 
{
 
	uint8_t hasFix = get_latitudeTrimmed()[0] != 0x00;
 
	gps_hadfix = hasFix;
 
	return hasFix;
 
}
 

	
 
//char variation[9];	//xxx.xb
 
int calculatedChecksum;
 
int receivedChecksum;
 

	
 
// transmission state machine
 
enum decodeState {
 
	//shared fields
 
	INITIALIZE=0,
 
	GET_TYPE,
 
	GPS_CHECKSUM,	//XOR of all the bytes between the $ and the * (not including the delimiters themselves), written in hexadecimal
 
	//GGA data fields
 
	GGA_TIME,
 
	GGA_LATITUDE,
 
	GGA_LONGITUDE,
 
	GGA_QUALITY,
 
	GGA_SATELLITES,
 
	GGA_HDOP,
 
	GGA_ALTITUDE,
 
	GGA_WGS84,
 
	GGA_LAST_UPDATE,
 
	GGA_STATION_ID,
 
	//RMC data fields
 
	RMC_TIME,
 
	RMC_VALIDITY,
 
	RMC_LATITUDE,
 
	RMC_LONGITUDE,
 
	RMC_KNOTS,
 
	RMC_COURSE,
 
	RMC_DATE,
 
	RMC_MAG_VARIATION,
 
	
 
}decodeState;
 

	
 
//
 
//void usart1_isr(void)
 
//{
 
//	uint8_t recv = 0;// usart_recv(GPS_USART);
 
//	//ECHO debug: usart_send_blocking(GPS_USART, recv);
 
//	nmeaBuffer[nmeaBufferDataPosition % NMEABUFFER_SIZE] = recv;
 
//	nmeaBufferDataPosition = (nmeaBufferDataPosition + 1) % NMEABUFFER_SIZE;
 
//}
 

	
 
void gps_init() 
 
{
 
@@ -192,15 +40,6 @@ void gps_init()
 
   // done in poweron uart_init();
 

	
 

	
 
    timestamp[0] = 0x00;
 
    latitude[0] = 0x00;
 
    longitude[0] = 0x00;
 
    numSatellites[0] = 0x00;
 
    hdop[0] = 0x00;
 
    knots[0] = 0x00;
 
    course[0] = 0x00;
 
    dayofmonth[0] = 0x00;
 

	
 
//    // Disable GLONASS mode
 
//    uint8_t disable_glonass[20] = {0xB5, 0x62, 0x06, 0x3E, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x01, 0x06, 0x08, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x01, 0x8F, 0xB2};
 
//
 
@@ -217,69 +56,203 @@ void gps_init()
 

	
 
}
 

	
 
void gps_sendubx(uint8_t* dat, uint8_t size)
 

	
 
void gps_update_position()
 
{
 
    // Request a NAV-POSLLH message from the GPS
 
    uint8_t request[8] = {0xB5, 0x62, 0x01, 0x02, 0x00, 0x00, 0x03,
 
        0x0A};
 
    //_gps_send_msg(request, 8);
 
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);
 

	
 
    uint8_t buf[36];
 
    HAL_UART_Receive(uart_gethandle(), buf, 36, 100);
 

	
 
    //for(uint8_t i = 0; i < 36; i++)
 
    //    buf[i] = _gps_get_byte();
 

	
 
//    // Verify the sync and header bits
 
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
 
//        led_set(LED_RED, 1);
 
//    if( buf[2] != 0x01 || buf[3] != 0x02 )
 
//        led_set(LED_RED, 1);
 

	
 
    // 4 bytes of longitude (1e-7)
 
    position.longitude = (int32_t)buf[10] | (int32_t)buf[11] << 8 |
 
        (int32_t)buf[12] << 16 | (int32_t)buf[13] << 24;
 

	
 
    // 4 bytes of latitude (1e-7)
 
    position.latitude = (int32_t)buf[14] | (int32_t)buf[15] << 8 |
 
        (int32_t)buf[16] << 16 | (int32_t)buf[17] << 24;
 

	
 
    // 4 bytes of altitude above MSL (mm)
 
    position.altitude = (int32_t)buf[22] | (int32_t)buf[23] << 8 |
 
        (int32_t)buf[24] << 16 | (int32_t)buf[25] << 24;
 

	
 
    //if( !_gps_verify_checksum(&buf[2], 32) ) led_set(LED_RED, 1);
 
}
 

	
 

	
 
void gps_update_time(uint8_t* hour, uint8_t* minute, uint8_t* second)
 
{
 
    // Send a NAV-TIMEUTC message to the receiver
 
    uint8_t request[8] = {0xB5, 0x62, 0x01, 0x21, 0x00, 0x00,
 
        0x22, 0x67};
 
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);
 

	
 
    // Get the message back from the GPS
 
    uint8_t buf[28];
 
    HAL_UART_Receive(uart_gethandle(), buf, 28, 100);
 

	
 
//    // Verify the sync and header bits
 
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
 
//        led_set(LED_RED, 1);
 
//    if( buf[2] != 0x01 || buf[3] != 0x21 )
 
//        led_set(LED_RED, 1);
 

	
 
    *hour = buf[22];
 
    *minute = buf[23];
 
    *second = buf[24];
 

	
 
//    if( !_gps_verify_checksum(&buf[2], 24) ) led_set(LED_RED, 1);
 
}
 

	
 
/**
 
 * Check the navigation status to determine the quality of the
 
 * fix currently held by the receiver with a NAV-STATUS message.
 
 */
 
void gps_check_lock(uint8_t* lock, uint8_t* sats)
 
{
 
    uint8_t sendctr;
 
    for(sendctr = 0; sendctr < size; sendctr++)
 
    // Construct the request to the GPS
 
    uint8_t request[8] = {0xB5, 0x62, 0x01, 0x06, 0x00, 0x00,
 
        0x07, 0x16};
 
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);
 

	
 
    // Get the message back from the GPS
 
    uint8_t buf[60];
 
    HAL_UART_Receive(uart_gethandle(), buf, 60, 100);
 

	
 
    // Verify the sync and header bits
 
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
 
//        led_set(LED_RED, 1);
 
//    if( buf[2] != 0x01 || buf[3] != 0x06 )
 
//        led_set(LED_RED, 1);
 

	
 
    // Check 60 bytes minus SYNC and CHECKSUM (4 bytes)
 
//    if( !_gps_verify_checksum(&buf[2], 56) ) led_set(LED_RED, 1);
 

	
 
    // Return the value if GPSfixOK is set in 'flags'
 
    if( buf[17] & 0x01 )
 
        *lock = buf[16];
 
    else
 
        *lock = 0;
 

	
 
    *sats = buf[53];
 
}
 

	
 
/**
 
 * Verify that the uBlox 6 GPS receiver is set to the <1g airborne
 
 * navigaion mode.
 
 */
 
uint8_t gps_check_nav(void)
 
    {
 
        //usart_send(GPS_USART, dat[sendctr]);
 
    uint8_t request[8] = {0xB5, 0x62, 0x06, 0x24, 0x00, 0x00,
 
        0x2A, 0x84};
 
    HAL_UART_Transmit(uart_gethandle(), request, 8, 100);
 

	
 
    // Get the message back from the GPS
 
    uint8_t buf[44];
 
    HAL_UART_Receive(uart_gethandle(), buf, 44, 100);
 

	
 
//    // Verify sync and header bytes
 
//    if( buf[0] != 0xB5 || buf[1] != 0x62 )
 
//        led_set(LED_RED, 1);
 
//    if( buf[2] != 0x06 || buf[3] != 0x24 )
 
//        led_set(LED_RED, 1);
 

	
 
    // Check 40 bytes of message checksum
 
//    if( !_gps_verify_checksum(&buf[2], 40) ) led_set(LED_RED, 1);
 

	
 
    // Clock in and verify the ACK/NACK
 
    uint8_t ack[10];
 
    for(uint8_t i = 0; i < 10; i++)
 
        ack[i] = _gps_get_byte();
 

	
 
    // If we got a NACK, then return 0xFF
 
    if( ack[3] == 0x00 ) return 0xFF;
 

	
 
    // Return the navigation mode and let the caller analyse it
 
    return buf[8];
 
}
 

	
 
/**
 
 * Verify the checksum for the given data and length.
 
 */
 

	
 
static uint8_t _gps_verify_checksum(uint8_t* data, uint8_t len)
 
{
 
    uint8_t a, b;
 
    gps_ubx_checksum(data, len, &a, &b);
 
    if( a != *(data + len) || b != *(data + len + 1))
 
        return 0;
 
    else
 
        return 1;
 
}
 

	
 
// Calculate a UBX checksum using 8-bit Fletcher (RFC1145)
 
static void gps_ubx_checksum(uint8_t* data, uint8_t len, uint8_t* cka, uint8_t* ckb)
 
{
 
    *cka = 0;
 
    *ckb = 0;
 
    for( uint8_t i = 0; i < len; i++ )
 
    {
 
        *cka += *data;
 
        *ckb += *cka;
 
        data++;
 
    }
 
}
 

	
 
// Could inline if program space available
 
static void setParserState(uint8_t state)
 
{
 
	decodeState = state;
 

	
 
	// If resetting, clear vars
 
	if(state == INITIALIZE)
 
void gps_poweron(void)
 
	{
 
		calculatedChecksum = 0;
 
	}
 
    // NOTE: pchannel
 
    HAL_GPIO_WritePin(GPS_NOTEN, 0);
 
    uart_init();
 
	
 
	// Every time we change state, we have parsed a byte
 
	nmeaBufferParsePosition = (nmeaBufferParsePosition + 1) % NMEABUFFER_SIZE;
 
    // Begin DMA reception
 
    //HAL_UART_Receive_DMA(uart_gethandle(), nmeaBuffer, NMEABUFFER_SIZE);
 
}
 

	
 

	
 
static uint8_t gps_acquiring = 0;
 
static uint32_t gps_lastfix_time = 0;
 
void gps_poweroff(void)
 
{
 
    // NOTE: pchannel
 
    uart_deinit();
 
    HAL_GPIO_WritePin(GPS_NOTEN, 1);
 
}
 

	
 
//
 
//uint8_t gps_hadfix = 0;
 
//uint8_t gps_hasfix()
 
//{
 
//	uint8_t hasFix = get_latitudeTrimmed()[0] != 0x00;
 
//	gps_hadfix = hasFix;
 
//	return hasFix;
 
//}
 

	
 

	
 

	
 
void gps_process(void)
 
{
 
    // If we're trying to acquire a GPS fix
 
    if(gps_acquiring)
 
    {
 
        // Process incoming bytes
 
        parse_gps_transmission();
 

	
 
        // If fix acquired
 
        uint16_t hdop_int = get_hdop_int_tenths();
 
        if(hdop_int < 50 && hdop_int > 0)
 
        {
 
            // Set RTC to GPS time
 

	
 
            // Record time of fix (TODO: don't use ticks if sleeping... use RTC time)
 
            gps_lastfix_time = HAL_GetTick();
 
//void gps_sendubx(uint8_t* dat, uint8_t size)
 
//{
 
//    uint8_t sendctr;
 
//    for(sendctr = 0; sendctr < size; sendctr++)
 
//    {
 
//        HAL_UART_Transmit(huart1, dat[sendctr]);
 
//    }
 
//}
 

	
 
            // Turn off GPS module
 
            gps_poweroff();
 

	
 
            // Invalidate HDOP
 
            hdop[0] = '9';
 

	
 
            // Go to idle state
 
            gps_acquiring = 0;
 
        }
 
        else
 
        {
 
            // if too much time has elapsed, set an error flag and go idle
 
            //gps_acquiring = 0;
 
        }
 
    }
 
}
 
uint8_t gps_acquiring= 0;
 
uint32_t gps_lastfix_time;
 

	
 
void gps_acquirefix(void)
 
{
 
@@ -289,8 +262,6 @@ void gps_acquirefix(void)
 
    gps_acquiring = 1;
 
}
 

	
 

	
 

	
 
uint8_t gps_getstate(void)
 
{
 
    if(gps_acquiring)
 
@@ -304,477 +275,6 @@ uint8_t gps_getstate(void)
 

	
 
}
 

	
 
// MKa GPS transmission parser START
 
void parse_gps_transmission(void)
 
{
 
    uint16_t nmeaBufferDataPosition = NMEABUFFER_SIZE - uart_get_rxdma_handle()->Instance->CNDTR;
 

	
 
	char byte;
 

	
 
	while(nmeaBufferDataPosition != nmeaBufferParsePosition)
 
	{
 
	    // Pull byte off of the buffer
 
	    byte = nmeaBuffer[nmeaBufferParsePosition];
 

	
 
		if(decodeState == INITIALIZE) //start of transmission sentence
 
		{
 
			if(byte == '$')
 
			{
 
				setParserState(GET_TYPE);
 
				numBytes = 0; //prep for next phases
 
				skipBytes = 0;
 
				calculatedChecksum = 0;
 
			}
 

	
 
			else
 
			{
 
				setParserState(INITIALIZE);
 
			}
 
		}
 

	
 
		//parse transmission type
 
		else if (decodeState == GET_TYPE)
 
		{
 
			tramsmissionType[numBytes] = byte;
 
			numBytes++;
 

	
 
			if(byte == ',') //end of this data type
 
			{
 
				tramsmissionType[5] = 0x00;
 

	
 
				if (tramsmissionType[2] == 'G' &&
 
				tramsmissionType[3] == 'G' &&
 
				tramsmissionType[4] == 'A')
 
				{
 
					setParserState(GGA_TIME);
 
					numBytes = 0;
 
				}
 
				else if (tramsmissionType[2] == 'R' &&
 
				tramsmissionType[3] == 'M' &&
 
				tramsmissionType[4] == 'C')
 
				{
 
					setParserState(RMC_TIME);
 
					numBytes = 0;
 
				}
 
				else //this is an invalid transmission type
 
				{
 
					setParserState(INITIALIZE);
 
				}
 
			}
 
			else {
 
				// continue
 
				setParserState(GET_TYPE);
 
			}
 

	
 
		}
 

	
 
		///parses GGA transmissions START
 
		/// $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*xx
 
		//timestamp
 
		else if (decodeState == GGA_TIME)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				//timestamp[4] = 0x00; // Cut off at 4 (no seconds) for APRS
 
				setParserState(GGA_LATITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				setParserState(GGA_TIME);
 
				timestamp[numBytes] = byte; //byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 

	
 
		//latitude
 
		else if (decodeState == GGA_LATITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				skipBytes = 1;
 
				setParserState(GGA_LATITUDE);
 
			}
 
			else if (byte == ',') //end of this data type
 
			{
 

	
 
				latitude[numBytes] = 0x00; // null terminate
 

	
 
				setParserState(GGA_LONGITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				latitude[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_LATITUDE);
 
			}
 
		}
 

	
 
		//longitude
 
		else if (decodeState == GGA_LONGITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				skipBytes = 1;
 
				setParserState(GGA_LONGITUDE);
 
			}
 
			else if (byte == ',') //end of this data type
 
			{
 
				longitude[numBytes] = 0x00;
 
				setParserState(GGA_QUALITY);
 
				numBytes = 0; //prep for next phase of parse
 
				skipBytes = 0;
 
			}
 
			else //store data
 
			{
 
				longitude[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_LONGITUDE);
 
			}
 
		}
 

	
 
		//GGA quality
 
		else if (decodeState == GGA_QUALITY)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				setParserState(GGA_SATELLITES);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				quality = byte; //maybe reset if invalid data ??
 
				setParserState(GGA_QUALITY);
 
			}
 
		}
 

	
 
		//number of satellites
 
		else if (decodeState == GGA_SATELLITES)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				numSatellites[numBytes] = 0x00;
 
				setParserState(GGA_HDOP);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				numSatellites[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_SATELLITES);
 
			}
 
		}
 

	
 
		//HDOP
 
		else if (decodeState == GGA_HDOP)
 
		{
 
			if (byte == ',' ) //end of this data type
 
			{
 
				hdop[numBytes] = 0x00;
 
				setParserState(GGA_ALTITUDE);
 
				numBytes = 0; //prep for next phase of parse
 
				skipBytes = 0;
 
			}
 
			else //store data
 
			{
 
				hdop[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_HDOP);
 
			}
 
		}
 

	
 
		//altitude
 
		else if (decodeState == GGA_ALTITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				altitude[numBytes] = 0x00;
 
				skipBytes = 1;
 
				setParserState(GGA_ALTITUDE);
 
			}
 
			else if(byte == ',') //end of this data type
 
			{
 
				// If we actually have an altitude
 
				if(numBytes>0)
 
				{
 
					altitude[numBytes-1] = 0x00; // Cut off the "M" from the end of the altitude
 
				}
 
				else
 
				{
 
					altitude[numBytes] = 0x00;
 
				}
 
				setParserState(GGA_WGS84);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				altitude[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_ALTITUDE);
 
			}
 
		}
 

	
 
		//WGS84 Height
 
		else if (decodeState == GGA_WGS84)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				skipBytes = 1;
 
				setParserState(GGA_WGS84);
 
			}
 
			else if(byte == ',') //end of this data type
 
			{
 
				//wgs84Height[numBytes] = 0x00;
 
				setParserState(GGA_LAST_UPDATE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				//wgs84Height[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_WGS84);
 
			}
 
		}
 

	
 
		//last GGA DGPS update
 
		else if (decodeState == GGA_LAST_UPDATE)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
//				lastUpdated[numBytes] = 0x00;
 
				setParserState(GGA_STATION_ID);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data - this should be blank
 
			{
 
//				lastUpdated[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_LAST_UPDATE);
 
			}
 
		}
 

	
 
		//GGA DGPS station ID
 
		else if (decodeState == GGA_STATION_ID)
 
		{
 
			if (byte == ',' || byte == '*') //end of this data type
 
			{
 
//				stationID[numBytes] = 0x00;
 
				setParserState(GPS_CHECKSUM);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data - this should be blank
 
			{
 
//				stationID[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(GGA_STATION_ID);
 
			}
 
		}
 
		///parses GGA transmissions END
 

	
 
		/// $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh
 
		///parses RMC transmissions
 
		//time
 
		// emz: commented setter, GMC time better?
 
		else if(decodeState == RMC_TIME)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				//timestamp[numBytes] = 0x00;
 
				setParserState(RMC_VALIDITY);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				//timestamp[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(RMC_TIME);
 
			}
 
		}
 

	
 
		//validity
 
		// not needed? dupe gga
 
		else if(decodeState == RMC_VALIDITY)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				setParserState(RMC_LATITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				//quality = byte;
 
				numBytes++;
 
				setParserState(RMC_VALIDITY);
 
			}
 
		}
 

	
 
		//latitude RMC (we don't need this, commented out setter)
 
		else if(decodeState == RMC_LATITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				skipBytes = 1;
 
				setParserState(RMC_LATITUDE);
 
			}
 
			else if (byte == ',') //end of this data type
 
			{
 
				setParserState(RMC_LONGITUDE);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				//latitude[numBytes]= byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(RMC_LATITUDE);
 
			}
 
		}
 

	
 
		//longitude RMC (we don't need this, commented out setter)
 
		else if(decodeState == RMC_LONGITUDE)
 
		{
 
			if (byte == ',' && skipBytes == 0) //discard this byte
 
			{
 
				skipBytes = 1;
 
				setParserState(RMC_LONGITUDE);
 
			}
 
			else if (byte == ',') //end of this data type
 
			{
 
				setParserState(RMC_KNOTS);
 
				skipBytes = 0;
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				//longitude[numBytes]= byte; //adjust number of bytes to fit array
 
				numBytes++;
 
				setParserState(RMC_LONGITUDE);
 
			}
 
		}
 

	
 
		//knots
 
		else if(decodeState == RMC_KNOTS)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				knots[numBytes] = 0x00;
 
				setParserState(RMC_COURSE);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				setParserState(RMC_KNOTS);
 
				knots[numBytes]= byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 

	
 
		//course
 
		else if(decodeState == RMC_COURSE)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				course[numBytes] = 0x00;
 
				setParserState(RMC_DATE);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				setParserState(RMC_COURSE);
 
				course[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 

	
 
		//date
 
		else if(decodeState == RMC_DATE)
 
		{
 
			if (byte == ',') //end of this data type
 
			{
 
				// Cut it off at day of month. Also has month and year if we ever need it.
 
				dayofmonth[2] = 0x00;
 
				setParserState(RMC_MAG_VARIATION);
 
				skipBytes = 0; //prep for next phase of parse
 
				numBytes = 0;
 
			}
 
			else //store data
 
			{
 
				setParserState(RMC_DATE);
 
				dayofmonth[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 

	
 
		//magnetic variation
 
		else if(decodeState == RMC_MAG_VARIATION)
 
		{
 
			if (byte == '*') //end of this data type
 
			{
 
				//variation[numBytes] = 0x00;
 
				setParserState(GPS_CHECKSUM);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				setParserState(RMC_MAG_VARIATION);
 
				//variation[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 
		///parses RMC transmissions END
 

	
 

	
 
		//checksum
 
		else if (decodeState == GPS_CHECKSUM)
 
		{
 
			if (numBytes == 2) //end of data - terminating character ??
 
			{
 
				//checksum calculator for testing http://www.hhhh.org/wiml/proj/nmeaxor.html
 
				//TODO: must determine what to do with correct and incorrect messages
 
				receivedChecksum = checksum[0] + (checksum[1]*16);	//convert bytes to int
 
				if(calculatedChecksum==receivedChecksum)
 
				{
 

	
 
				}
 
				else
 
				{
 

	
 
				}
 

	
 
				setParserState(INITIALIZE);
 
				numBytes = 0; //prep for next phase of parse
 
			}
 
			else //store data
 
			{
 
				setParserState(GPS_CHECKSUM);
 
				checksum[numBytes] = byte; //adjust number of bytes to fit array
 
				numBytes++;
 
			}
 
		}
 
		else {
 
			setParserState(INITIALIZE);
 
		}
 

	
 
		if (decodeState!=GPS_CHECKSUM && decodeState!=INITIALIZE)	//want bytes between '$' and '*'
 
		{
 
			//input byte into running checksum
 
			XORbyteWithChecksum(byte);
 
		}
 
	}
 

	
 

	
 
}
 

	
 
void XORbyteWithChecksum(uint8_t byte)
 
{
 
	calculatedChecksum ^= (int)byte; //this may need to be re-coded
 
}
 

	
 

	
 

	
 

	
src/interrupts.c
Show inline comments
 
@@ -5,7 +5,7 @@
 
#include "stm32f0xx_hal.h"
 
#include "stm32f0xx.h"
 
#include "interrupts.h"
 
#include "usart.h"
 
#include "uart.h"
 
#include "gpio.h"
 
 
extern TIM_HandleTypeDef htim1;
src/main.c
Show inline comments
 
@@ -3,91 +3,13 @@
 
//
 
 
#include "stm32f0xx_hal.h"
 
#include "si5351.h"
 
#include "jtencode.h"
 
#include "adc.h"
 
#include "system.h"
 
#include "i2c.h"
 
#include "usart.h"
 
#include "uart.h"
 
#include "gpio.h"
 
#include "gps.h"
 
 
#define WSPR_DEFAULT_FREQ 10140100UL
 
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
 
#define WSPR_CTC 10672 // CTC value for WSPR
 
 
// Private functions
 
void sysclk_init(void);
 
void enter_sleep(void);
 
void enter_deepsleep(void);
 
 
// Test stuff
 
char call[7] = "KD8TDF";
 
char loc[5] = "EN72";
 
uint8_t dbm = 10;
 
uint8_t tx_buffer[255];
 
 
// Frequencies and channel info
 
uint32_t freq = WSPR_DEFAULT_FREQ;
 
uint8_t symbol_count = WSPR_SYMBOL_COUNT;
 
uint16_t ctc = WSPR_CTC;
 
uint16_t tone_spacing = WSPR_TONE_SPACING;
 
volatile uint8_t proceed = 0;
 
 
// Bring up TCXO and oscillator IC
 
void encode_wspr(void)
 
{
 
    HAL_GPIO_WritePin(OSC_NOTEN, 0);
 
    HAL_GPIO_WritePin(TCXO_EN, 1);
 
    HAL_Delay(100);
 
 
    // Bring up the chip
 
    si5351_init(i2c_get(), SI5351_CRYSTAL_LOAD_8PF, 0);
 
    si5351_set_correction(0);
 
    //si5351_set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
 
    //si5351_set_ms_source(SI5351_CLK0, SI5351_PLLA);
 
    si5351_set_freq(WSPR_DEFAULT_FREQ * 100, 0, SI5351_CLK0);
 
    si5351_drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power if desired (8ma max)
 
    si5351_output_enable(SI5351_CLK0, 1);
 
    //si5351_pll_reset(SI5351_PLLA);
 
 
    // Make sure the other outputs of the SI5351 are disabled
 
    si5351_output_enable(SI5351_CLK1, 0); // Disable the clock initially
 
    si5351_output_enable(SI5351_CLK2, 0); // Disable the clock initially
 
 
    // disable clock powers
 
    si5351_set_clock_pwr(SI5351_CLK1, 0);
 
    si5351_set_clock_pwr(SI5351_CLK2, 0);
 
 
 
    // Encode message to transmit
 
    wspr_encode(call, loc, dbm, tx_buffer);
 
 
    // Key transmitter
 
    si5351_output_enable(SI5351_CLK0, 1);
 
 
    // Loop through and transmit symbols TODO: Do this from an ISR or ISR-triggered main loop function call (optimal)
 
    uint8_t i;
 
    for(i=0; i<symbol_count; i++)
 
    {
 
        uint32_t freq2 = (freq * 100) + (tx_buffer[i] * tone_spacing);
 
        si5351_set_freq(freq2, 0, SI5351_CLK0);
 
        HAL_GPIO_TogglePin(LED_BLUE);
 
 
        proceed = 0;
 
        while(!proceed);
 
    }
 
 
    // Disable transmitter
 
    si5351_output_enable(SI5351_CLK0, 0);
 
 
    HAL_GPIO_WritePin(OSC_NOTEN, 1);
 
    HAL_GPIO_WritePin(TCXO_EN, 0);
 
}
 
 
 
 
 
TIM_HandleTypeDef htim1;
 
 
int main(void)
 
{
 
@@ -111,20 +33,6 @@ int main(void)
 
 
    HAL_GPIO_TogglePin(LED_BLUE);
 
 
    // Start timer for WSPR
 
    __TIM1_CLK_ENABLE();
 
    htim1.Instance = TIM1;
 
    htim1.Init.Prescaler = 512; // gives 64uS ticks from 8MHz ahbclk
 
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
 
    htim1.Init.Period = ctc; // Count up to this value (how many 64uS ticks per symbol)
 
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 
    htim1.Init.RepetitionCounter = 0;
 
    HAL_TIM_Base_Init(&htim1);
 
    HAL_TIM_Base_Start_IT(&htim1);
 
    HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0, 0);
 
    HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 
 
 
    uint32_t led_timer = HAL_GetTick();
 
    uint32_t last_gps  = HAL_GetTick();
 
    uint32_t last_wspr  = HAL_GetTick(); //0xfffff; // start immediately.
 
@@ -141,6 +49,7 @@ int main(void)
 
    uint8_t lastMinute = 0;
 
    uint16_t blink_rate = 250;
 
 
    gps_update_position();
 
 
    while (1)
 
    {
 
@@ -170,7 +79,7 @@ int main(void)
 
//            {
 
//                // Wait until the first second of the minute
 
//                HAL_Delay(1000);
 
//                encode_wspr();
 
//                wspr_transmit();
 
//            }
 
 
//            lastMinute = minute;
 
@@ -184,7 +93,7 @@ int main(void)
 
        }
 
        if(HAL_GetTick() - last_gps > 10)
 
        {
 
            gps_process();
 
            //gps_process();
 
            last_gps = HAL_GetTick();
 
        }
 
 
@@ -193,58 +102,5 @@ int main(void)
 
}
 
 
 
void enter_sleep(void)
 
{
 
    //HAL_SuspendTick();
 
    HAL_TIM_Base_Stop_IT(&htim1);
 
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
 
    HAL_TIM_Base_Start_IT(&htim1);
 
    //HAL_ResumeTick();
 
}
 
 
 
void enter_deepsleep(void) 
 
{
 
    // Request to enter STOP mode with regulator in low power mode
 
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
 
    // After wake-up from STOP reconfigure the PLL
 
    sysclk_init();
 
}
 
 
 
// Initialize system clocks
 
void sysclk_init(void)
 
{
 
    RCC_OscInitTypeDef RCC_OscInitStruct;
 
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
    RCC_PeriphCLKInitTypeDef PeriphClkInit;
 
 
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI14;
 
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 
    RCC_OscInitStruct.HSI14State = RCC_HSI14_ON;
 
    RCC_OscInitStruct.HSICalibrationValue = 16;
 
    RCC_OscInitStruct.HSI14CalibrationValue = 16;
 
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
 
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 
                                |RCC_CLOCKTYPE_PCLK1;
 
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
 
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
 
 
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
 
    PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK; //RCC_USART1CLKSOURCE_PCLK1;
 
    PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
 
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
 
 
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
 
 
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
 
 
    __SYSCFG_CLK_ENABLE();
 
    // SysTick_IRQn interrupt configuration 
 
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
 
}
 
src/system.c
Show inline comments
 
new file 100644
 
//
 
// System: basic low-level system configuration
 
//
 

	
 
#include "stm32f0xx_hal.h"
 
#include "wspr.h"
 

	
 
void enter_sleep(void)
 
{
 
    //HAL_SuspendTick();
 
    wspr_sleep();
 
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
 
    wspr_wakeup();
 
    //HAL_ResumeTick();
 
}
 

	
 

	
 
void enter_deepsleep(void)
 
{
 
    // Request to enter STOP mode with regulator in low power mode
 
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
 
    // After wake-up from STOP reconfigure the PLL
 
    sysclk_init();
 
}
 

	
 

	
 
// Initialize system clocks
 
void sysclk_init(void)
 
{
 
    RCC_OscInitTypeDef RCC_OscInitStruct;
 
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
    RCC_PeriphCLKInitTypeDef PeriphClkInit;
 

	
 
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSI14;
 
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 
    RCC_OscInitStruct.HSI14State = RCC_HSI14_ON;
 
    RCC_OscInitStruct.HSICalibrationValue = 16;
 
    RCC_OscInitStruct.HSI14CalibrationValue = 16;
 
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 

	
 
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 
                                |RCC_CLOCKTYPE_PCLK1;
 
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
 
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
 

	
 
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_I2C1;
 
    PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK; //RCC_USART1CLKSOURCE_PCLK1;
 
    PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
 
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
 

	
 
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
 

	
 
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
 

	
 
    __SYSCFG_CLK_ENABLE();
 
    // SysTick_IRQn interrupt configuration
 
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
 
}
src/uart.c
Show inline comments
 
file renamed from src/usart.c to src/uart.c
 
#include "stm32f0xx_hal.h"
 
 
#include "usart.h"
 
#include "uart.h"
 
#include "config.h"
 
#include "gpio.h"
 
 
@@ -39,36 +39,36 @@ void uart_init(void)
 
    huart1.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;
 
    HAL_UART_Init(&huart1);
 
 
 
    __DMA1_CLK_ENABLE();
 
 
  // Init UART DMA
 
    hdma_usart1_rx.Instance = DMA1_Channel3;
 
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
 
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
 
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
 
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
 
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
 
    HAL_DMA_Init(&hdma_usart1_rx);
 
 
    __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);
 
 
    hdma_usart1_tx.Instance = DMA1_Channel2;
 
    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
 
    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
 
    hdma_usart1_tx.Init.MemInc = DMA_MINC_DISABLE;
 
    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 
    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 
    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
 
    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
 
    HAL_DMA_Init(&hdma_usart1_tx);
 
 
    __HAL_LINKDMA(&huart1,hdmatx,hdma_usart1_tx);
 
 
//    HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
 
//    HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
 
//
 
//    __DMA1_CLK_ENABLE();
 
//
 
//  // Init UART DMA
 
//    hdma_usart1_rx.Instance = DMA1_Channel3;
 
//    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
 
//    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
 
//    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
 
//    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 
//    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 
//    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
 
//    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
 
//    HAL_DMA_Init(&hdma_usart1_rx);
 
//
 
//    __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);
 
//
 
//    hdma_usart1_tx.Instance = DMA1_Channel2;
 
//    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
 
//    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
 
//    hdma_usart1_tx.Init.MemInc = DMA_MINC_DISABLE;
 
//    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 
//    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 
//    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
 
//    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
 
//    HAL_DMA_Init(&hdma_usart1_tx);
 
//
 
//    __HAL_LINKDMA(&huart1,hdmatx,hdma_usart1_tx);
 
//
 
////    HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
 
////    HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
 
 
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
 
    //HAL_NVIC_EnableIRQ(USART1_IRQn);
src/wspr.c
Show inline comments
 
new file 100644
 
#include "stm32f0xx_hal.h"
 
#include "si5351.h"
 
#include "jtencode.h"
 
#include "gpio.h"
 
#include "wspr.h"
 
#include "config.h"
 

	
 

	
 
#define WSPR_DEFAULT_FREQ 10140100UL
 
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
 
#define WSPR_CTC 10672 // CTC value for WSPR
 

	
 
// Test stuff
 
char call[7] = "KD8TDF";
 
char loc[5] = "EN72";
 
uint8_t dbm = 10;
 
uint8_t tx_buffer[255];
 

	
 
// Frequencies and channel info
 
uint32_t freq = WSPR_DEFAULT_FREQ;
 
uint8_t symbol_count = WSPR_SYMBOL_COUNT;
 
uint16_t ctc = WSPR_CTC;
 
uint16_t tone_spacing = WSPR_TONE_SPACING;
 
volatile uint8_t proceed = 0;
 

	
 
TIM_HandleTypeDef htim1;
 

	
 

	
 

	
 
void wspr_init(void)
 
{
 
    // Start timer for WSPR
 
    __TIM1_CLK_ENABLE();
 
    htim1.Instance = TIM1;
 
    htim1.Init.Prescaler = 512; // gives 64uS ticks from 8MHz ahbclk
 
    htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
 
    htim1.Init.Period = ctc; // Count up to this value (how many 64uS ticks per symbol)
 
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 
    htim1.Init.RepetitionCounter = 0;
 
    HAL_TIM_Base_Init(&htim1);
 
    HAL_TIM_Base_Start_IT(&htim1);
 
    HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0, 0);
 
    HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 

	
 
}
 

	
 
// Do anything needed to prepare for sleep
 
void wspr_sleep(void)
 
{
 
    HAL_TIM_Base_Stop_IT(&htim1);
 
}
 

	
 
void wspr_wakeup(void)
 
{
 
    HAL_TIM_Base_Start_IT(&htim1);
 
}
 

	
 

	
 
// Bring up TCXO and oscillator IC
 
void wspr_transmit(void)
 
{
 
    HAL_GPIO_WritePin(OSC_NOTEN, 0);
 
    HAL_GPIO_WritePin(TCXO_EN, 1);
 
    HAL_Delay(100);
 

	
 
    // Bring up the chip
 
    si5351_init(i2c_get(), SI5351_CRYSTAL_LOAD_8PF, 0);
 
    si5351_set_correction(0);
 
    //si5351_set_pll(SI5351_PLL_FIXED, SI5351_PLLA);
 
    //si5351_set_ms_source(SI5351_CLK0, SI5351_PLLA);
 
    si5351_set_freq(WSPR_DEFAULT_FREQ * 100, 0, SI5351_CLK0);
 
    si5351_drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power if desired (8ma max)
 
    si5351_output_enable(SI5351_CLK0, 1);
 
    //si5351_pll_reset(SI5351_PLLA);
 

	
 
    // Make sure the other outputs of the SI5351 are disabled
 
    si5351_output_enable(SI5351_CLK1, 0); // Disable the clock initially
 
    si5351_output_enable(SI5351_CLK2, 0); // Disable the clock initially
 

	
 
    // disable clock powers
 
    si5351_set_clock_pwr(SI5351_CLK1, 0);
 
    si5351_set_clock_pwr(SI5351_CLK2, 0);
 

	
 

	
 
    // Encode message to transmit
 
    wspr_encode(call, loc, dbm, tx_buffer);
 

	
 
    // Key transmitter
 
    si5351_output_enable(SI5351_CLK0, 1);
 

	
 
    // Loop through and transmit symbols TODO: Do this from an ISR or ISR-triggered main loop function call (optimal)
 
    uint8_t i;
 
    for(i=0; i<symbol_count; i++)
 
    {
 
        uint32_t freq2 = (freq * 100) + (tx_buffer[i] * tone_spacing);
 
        si5351_set_freq(freq2, 0, SI5351_CLK0);
 
        HAL_GPIO_TogglePin(LED_BLUE);
 

	
 
        proceed = 0;
 
        while(!proceed);
 
    }
 

	
 
    // Disable transmitter
 
    si5351_output_enable(SI5351_CLK0, 0);
 

	
 
    HAL_GPIO_WritePin(OSC_NOTEN, 1);
 
    HAL_GPIO_WritePin(TCXO_EN, 0);
 
}
 

	
0 comments (0 inline, 0 general)