Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 294 additions & 0 deletions GccBoardProject1/src/loraDriver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
/*
* loraDriver.c
*
* Created: 3/24/2017 12:08:18 PM
* Author: mazacar8
*/

#include "loraDriver.h"
#include <stdio.h>
#include <asf.h>
#include "saml21j18b.h"
#include "status_codes.h"

uint8_t reset_N = PIN_PB00;
uint16_t rx_offset = 0;

/**
* @brief Initializes UART for the RN2903 and debug interface
*
*/
void init_uart() {
struct usart_config config_usart;
struct usart_config config_lora;

//Debug Interface configuration
usart_get_config_defaults(&config_usart);
config_usart.baudrate = DEBUG_BAUD;
config_usart.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
config_usart.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
config_usart.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
config_usart.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
config_usart.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the serial debug stuff should probably be wrapped inside of #IFDEF's. We don't want to be writing debug output if not necessary.


//Lora UART interface configuration
usart_get_config_defaults(&config_lora);
config_lora.baudrate = LORA_BAUD;
config_lora.mux_setting = EXT3_UART_SERCOM_MUX_SETTING;
config_lora.pinmux_pad0 = EXT3_UART_SERCOM_PINMUX_PAD0;
config_lora.pinmux_pad1 = EXT3_UART_SERCOM_PINMUX_PAD1;
config_lora.pinmux_pad2 = EXT3_UART_SERCOM_PINMUX_PAD2;
config_lora.pinmux_pad3 = EXT3_UART_SERCOM_PINMUX_PAD3;

while (usart_init(&usart_instance, EDBG_CDC_MODULE, &config_usart) != STATUS_OK) {
}

while (usart_init(&lora_uart_instance, EXT3_UART_MODULE, &config_lora) != STATUS_OK) {
}

usart_enable(&usart_instance);
usart_enable(&lora_uart_instance);
uint8_t msg[] = "UART Initialized\r\n";
printSerial(msg,sizeof(msg));
}

/**
* @brief Initializes and saves setup values for RN2903
*
*/
void lora_setup()
{
uint16_t n = (uint16_t) sprintf(tx_buffer,"Setting up LORA...\r\n");
printSerial(tx_buffer,n);
lora_reset();
n = (uint16_t) sprintf(tx_buffer,"sys factoryRESET\r\n");
send_lora_command(tx_buffer,n);
delay_ms(5000);
read_response();
n = (uint16_t) sprintf(tx_buffer,"mac set appeui 0000000000000100\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"mac set deveui 1122334455667799\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"mac set appkey 2b7e151628aed2a6abf7156669cf4f3c\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"mac set dr 0\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"mac set pwridx 5\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"mac set adr off\r\n");
send_lora_command(tx_buffer,n);

setup_channels();

n = (uint16_t) sprintf(tx_buffer,"mac set devaddr 00000000\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"radio set pwr 20\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"radio set prlen 8\r\n");
send_lora_command(tx_buffer,n);
n = (uint16_t) sprintf(tx_buffer,"mac save\r\n");
send_lora_command(tx_buffer,n);
lora_join();
}

/**
* @brief Resets the RN2903
*
*/
void lora_reset(){

port_get_config_defaults(&reset_config);
reset_config.direction = PORT_PIN_DIR_OUTPUT;
reset_config.input_pull = PORT_PIN_PULL_NONE;
reset_config.powersave = false;
port_pin_set_config(reset_N,&reset_config);
port_pin_set_output_level(reset_N,LOW);
port_pin_set_output_level(reset_N,HIGH);
delay_ms(2000);

}

/**
* @brief Switches off all but channels 0-7 for Lora transmit
*
*/
void setup_channels(){
uint16_t n;

for (int i = 0; i < 72; i++) {
if (i < 8){
n = (uint16_t) sprintf(tx_buffer,"mac set ch status %d on\r\n",i);
send_lora_command(tx_buffer,n);
}

else{
n = (uint16_t) sprintf(tx_buffer,"mac set ch status %d off\r\n",i);
send_lora_command(tx_buffer,n);
}

}

}

/**
* @brief Attempts to join the Lora network a maximum of 5 times
*
*/
void lora_join() {
int i,j;
uint16_t n;
bool accepted = false;

//Loop MAX_JOIN_ATTEMPTS to try and join the network
for(i = 0; i < MAX_JOIN_ATTEMPTS; i++){

n = (uint16_t) sprintf(tx_buffer,"mac join otaa\r\n");
send_lora_command(tx_buffer,n);
if(rx_buffer[0] != 'o'){
//Command not received by RN2903. Needs to be sent again.
n = (uint16_t) sprintf(tx_buffer,"Command Failed. Retrying in 10 s\r\n");
printSerial(tx_buffer,n);
delay_ms(10000);
continue;
}

//Loop until response from gateway is received
for(j = 0; j < MAX_STATUS_CHECKS; j++){

if(read_response()){
//Gateway responded
if(rx_buffer[0] == 'a'){ //Checking if 'accepted'. Temporarily doing it this way until read_response is fixed
accepted = true;
n = (uint16_t) sprintf(tx_buffer,"Join Accepted!\r\n");
printSerial(tx_buffer,n);
break;
}
else if(j == MAX_STATUS_CHECKS - 1){
n = (uint16_t) sprintf(tx_buffer,"Join Failed... Aborting\r\n");
printSerial(tx_buffer,n);
accepted = false;
}
else{
//Join request sent and denied, so new command must be sent
n = (uint16_t) sprintf(tx_buffer,"Join Failed... Retrying in 10 seconds\r\n");
printSerial(tx_buffer,n);
accepted = false;
delay_ms(10000);
break;
}

}

else{
//Wait 5 seconds before checking for the response again
n = sprintf(tx_buffer,"Waiting 5 seconds\r\n");
printSerial(tx_buffer,n);
delay_ms(5000);
}

}

if(accepted){
break;
}
}

}

/**
* @brief Sends a command to the RN2903
*
* @param cmd Command to send
* @param len Length of command to send
*/
void send_lora_command(uint8_t cmd[],uint16_t len)
{
while(usart_write_buffer_wait(&lora_uart_instance, cmd, len) != STATUS_OK);
uint8_t msg[] = "Sent command: ";
printSerial(msg,sizeof(msg));
printSerial(cmd,len);
//delay_ms(500);
read_response();

}

/**
* @brief Prints to the debug interface
*
* @param cmd Command to print
* @param len Length of command to print
*/
void printSerial(uint8_t cmd[],uint16_t len)
{
while(usart_write_buffer_wait(&usart_instance, cmd, len) != STATUS_OK);

}

/**
* @brief Reads the response from RN2903
*
* @return true if there was a response, false if there wasn't
*/
bool read_response()
{

uint16_t c,n;
uint8_t msg[] = "ReadBuf overflow, emptying buffer\r\n";
uint8_t noresp[] = "No response\r\n";
uint8_t msg1[] = "Received from RN2903: ";

status_code_genare_t err;
uint8_t check[10];

if(usart_read_wait(&lora_uart_instance, &c) == STATUS_OK){
rx_buffer[rx_offset++] = c;
while((char)c != '\n'){
while((err = usart_read_wait(&lora_uart_instance, &c))!=STATUS_OK){
n = sprintf(check,"ERROR: %x\r\n",err);
//printSerial(check,n);
};
if(rx_offset == RX_BUFFER_SIZE){
n = (uint16_t) sprintf(tx_buffer,"ReadBuf overflow, emptying buffer\r\n");
printSerial(tx_buffer,n);
}
rx_buffer[rx_offset++] = c;

}

rx_buffer[rx_offset] = 0;
printSerial(msg1,sizeof(msg1)-1);
printSerial(rx_buffer,rx_offset);
rx_offset = 0;
return true;

}

else{
printSerial(noresp,sizeof(noresp));
return false;
}

}

/**
* @brief Sends "string" over the Lora Network
*
* @param string String to send over the network
*/
void send_lora_data(uint8_t string[]){

uint16_t n = sprintf(tx_buffer,"mac tx uncnf 1 %x\r\n",string);
send_lora_command(tx_buffer,n);
}

/**
* @brief Sends an integer over the Lora Network
*
* @param count Integer to send over the network
*/
void send_lora_count(uint16_t count){

uint16_t n = sprintf(tx_buffer,"mac tx uncnf 1 %x\r\n",count);
send_lora_command(tx_buffer,n);
}

39 changes: 39 additions & 0 deletions GccBoardProject1/src/loraDriver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* loraDriver.h
*
* Created: 3/24/2017 12:08:35 PM
* Author: mazacar8
*/

#include <stdint.h>
#include <stdbool.h>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, these can live inside the #IFNDEF


#ifndef LORADRIVER_H_
#define LORADRIVER_H_

#define MAX_JOIN_ATTEMPTS 5
#define MAX_STATUS_CHECKS 5
#define LORA_BAUD 57600
#define DEBUG_BAUD 115200
#define RX_BUFFER_SIZE 100
#define TX_BUFFER_SIZE 100

struct port_config reset_config;
struct usart_module usart_instance;
struct usart_module lora_uart_instance;

volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint8_t tx_buffer[TX_BUFFER_SIZE];

void lora_setup(void);
void lora_join(void);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Void returns for most of these functions are fine, but since join has a variety of outcomes this should probably communicate some more information back to the calling function. You could define a lora_error_t struct or similar, or just change it to an int and #define some return values.

void lora_reset(void);
void send_lora_data(uint8_t string[]);
void setup_channels();
void init_uart(void);
void send_lora_command(uint8_t cmd[],uint16_t len);
void printSerial(uint8_t cmd[],uint16_t len);
bool read_response(void);
void send_lora_count(uint16_t count);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary for this PR, but we do need to start looking at the LoRaWAN activation by personalization so that we don't need to do OTAA join every time. I added a Trello card and assigned you to it to track.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a similar vein, we should start investigating RX and determine if that'll be possible. We will want to be able to receive for OTA configuration.

#endif /* LORADRIVER_H_ */