Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: AlohaTransceiver RingBuffer SX1276Lib_inAir SerialInterfaceProtocol mbed L3PDU
main.cpp
- Committer:
- rba90
- Date:
- 2016-09-02
- Revision:
- 22:fea9289f31b3
- Parent:
- 20:ff70a415660a
- Child:
- 24:e41b5098ed0a
File content as of revision 22:fea9289f31b3:
#include "mbed.h"
#include "AlohaTransceiver.h"
#include "buffer.h"
#include "SerialInterfaceProtocol.h"
#include "AlohaFrame.h"
#include "ControlPacket.h"
#include "DataBlockPacket.h"
Serial pc(USBTX, USBRX);
// sip uses two buffer queues
CircularBuffer<uint8_t> SerialInputBuffer(128);
CircularBuffer<uint8_t> SerialOutputBuffer(128);
SerialInterfaceProtocol SIP(&SerialInputBuffer, &SerialOutputBuffer);
// aloha transceiver
AlohaTransceiver aloha(DEVICE_ID);
AlohaFrame txFrame;
Timer timer;
InterruptIn button(USER_BUTTON);
// sensors
#define SUPPLY_VOLTAGE 3.3f;
AnalogIn TempSensor(PA_0);
// convert fp32 to 4 byte string
typedef union
{
float fp32;
uint8_t bytes[4];
} float_bytes_32;
typedef union
{
int16_t int16;
uint8_t bytes[2];
} int_string_16;
float getTemperature()
{
float reading = TempSensor.read();
float output_voltage = reading * SUPPLY_VOLTAGE;
return (output_voltage - 0.25) / 0.028;
}
bool getDoorState()
{
// TODO: Jamie, you need to implement this!
return true;
}
void serialInterruptHandler() {
// Note: you need to actually read from the serial to clear the RX interrupt
int c = pc.getc();
// add to buffer
if (SerialInputBuffer.isLocked())
{
printf("Mutex Locked\r\n");
}
else
{
SerialInputBuffer.enqueue((uint8_t) c);
}
}
int toggleChecksum(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
{
// one payload
if (payload_length != 1)
{
sprintf((char *) response, "Wrong Payload Length\r\n");
*response_length = 22;
return 1;
}
if ((bool) payload[0])
{
SIP.enableChecksum();
}
else
{
SIP.disableChecksum();
}
return 0;
}
int queryServiceQuality(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
{
// decode user message
uint8_t node_id = payload[0];
uint8_t source_type = 0x2; // query for service quality
// create a command packet
ControlPacket packet;
// layer 3 sequence id is not used in this case
packet.setSequenceID(0x0);
// set source id as current device id
packet.setSourceID(aloha.getDeviceID());
// set destination id as node id
packet.setDestinationID(node_id);
// set command as query (treat it similar to sensor)
packet.setCommand(0x0);
// store sensor type in data block 0
packet.setData(0, source_type);
// generate crc
packet.generateCrc();
// create buffer for transmission
uint8_t buffer[8];
memset(buffer, 0x0, sizeof(buffer));
// copy bytes into buffer
packet.serialize(buffer);
// send to aloha transceiver
aloha.send(buffer, 8, node_id);
return 0;
}
/*
* Format:
* < :start flag
* 02 :command
* xx :length
* xx: :00: get, 01: set
* xx :index for parameters
* ...
* ff :checksum
* > :end flag
*/
int configureRadio(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
{
// read settings from radio
#if USE_MODEM_LORA == 1
AlohaTransceiver::LoRaSettings_t *settings = aloha.getSettings();
#elif USE_MODEM_FSK == 1
AlohaTransceiver::FskSettings_t *settings = aloha.getSettings();
#else
#error "Please define a modem in the compiler options."
#endif
if (payload_length < 2)
{
sprintf((char *) response, "Wrong Payload Length\r\n");
*response_length = 22;
return 1;
}
// true is set, false is get
bool isSet = (bool) payload[0];
uint8_t idx = payload[1];
switch(idx)
{
case 0x00: // Power
{
if (isSet)
{
int8_t Power = (int8_t) payload[2];
settings->Power = Power;
return 0;
}
else
{
response[0] = (uint8_t) settings->Power;
*response_length = 1;
return 0;
}
}
case 0x01: // Bandwidth
{
if (isSet)
{
uint32_t Bandwidth = (payload[5]) |
(payload[4] << 8) |
(payload[3] << 16) |
(payload[2] << 24);
settings->Bandwidth = Bandwidth;
return 0;
}
else
{
response[3] = (uint8_t) (settings->Bandwidth);
response[2] = (uint8_t) (settings->Bandwidth >> 8);
response[1] = (uint8_t) (settings->Bandwidth >> 16);
response[0] = (uint8_t) (settings->Bandwidth >> 24);
*response_length = 4;
return 0;
}
}
case 0x02: // Datarate, AKA Spreading Factor
{
if (isSet)
{
uint32_t Datarate = (payload[5]) |
(payload[4] << 8) |
(payload[3] << 16) |
(payload[2] << 24);
settings->Datarate = Datarate;
return 0;
}
else
{
response[3] = (uint8_t) (settings->Datarate);
response[2] = (uint8_t) (settings->Datarate >> 8);
response[1] = (uint8_t) (settings->Datarate >> 16);
response[0] = (uint8_t) (settings->Datarate >> 24);
*response_length = 4;
return 0;
}
}
case 0x03: // Coderate
{
if (isSet)
{
uint8_t Coderate = payload[2];
settings->Coderate = Coderate;
return 0;
}
else
{
response[0] = (uint8_t) settings->Coderate;
*response_length = 1;
return 0;
}
}
case 0x04: //Preamble Length
{
if (isSet)
{
uint16_t PreambleLen = payload[3] | (payload[2] << 8);
settings->PreambleLen = PreambleLen;
return 0;
}
else
{
response[1] = (uint8_t) (settings->PreambleLen);
response[0] = (uint8_t)(settings->PreambleLen >> 8);
*response_length = 2;
return 0;
}
}
case 0x05: //Symbol Timeout
{
if (isSet)
{
uint16_t SymbolTimeout = payload[3] | (payload[2] << 8);
settings->SymbolTimeout = SymbolTimeout;
return 0;
}
else
{
response[1] = (uint8_t) (settings->SymbolTimeout);
response[0] = (uint8_t) (settings->SymbolTimeout >> 8);
*response_length = 2;
return 0;
}
}
case 0x06: //FixLen
{
if (isSet)
{
bool FixLen = payload[2];
settings->FixLen = FixLen;
return 0;
}
else
{
response[0] = (bool) (settings->SymbolTimeout);
*response_length = 1;
return 0;
}
}
case 0x07: //PayloadLen
{
if (isSet)
{
uint8_t PayloadLen = payload[2];
settings->PayloadLen = PayloadLen;
return 0;
}
else
{
response[0] = (uint8_t) (settings->PayloadLen);
return 0;
}
}
case 0x08: //CrcOn
{
if (isSet) {
bool CrcOn = payload[2];
settings->CrcOn = CrcOn;
return 0;
}
else
{
response[0] = (bool) (settings->CrcOn);
return 0;
}
}
case 0x09: //FreqHopOn
{
if (isSet) {
bool FreqHopOn = payload[2];
settings->FreqHopOn = FreqHopOn;
return 0;
}
else
{
response[0] = (bool) (settings->FreqHopOn);
return 0;
}
}
case 0x0A: //HopPeriod
{
if (isSet) {
uint8_t HopPeriod = payload[2];
settings->HopPeriod = HopPeriod;
return 0;
}
else
{
response[0] = (uint8_t) (settings->HopPeriod);
return 0;
}
}
case 0x0B: //IqInverted
{
if (isSet) {
bool IqInverted = payload[2];
settings->IqInverted = IqInverted;
return 0;
}
else
{
response[0] = (bool) (settings->IqInverted);
return 0;
}
}
case 0x0C: //RxContinuous
{
if(isSet)
{
bool RxContinuous = payload[2];
settings->RxContinuous = RxContinuous;
return 0;
}
else
{
response[0] = (bool) (settings->RxContinuous);
return 0;
}
}
case 0x0D: //TxTimeout
{
if (isSet)
{
uint32_t TxTimeout = (payload[5]) |
(payload[4] << 8) |
(payload[3] << 16) |
(payload[2] << 24);
settings->TxTimeout = TxTimeout;
return 0;
}
else
{
response[3] = (uint8_t) (settings->TxTimeout);
response[2] = (uint8_t) (settings->TxTimeout >> 8);
response[1] = (uint8_t) (settings->TxTimeout >> 16);
response[0] = (uint8_t) (settings->TxTimeout >> 24);
*response_length = 4;
return 0;
}
}
default:
{
break;
}
//case
}
return 0;
}
int radioUpdateSettings(uint8_t *payload, uint8_t payload_length, uint8_t *response, uint8_t *response_length)
{
aloha.updateSettings();
return 0;
}
void AlohaDataPacketHandler(uint8_t *payload, uint8_t payload_length, uint8_t src_addr)
{
// try to decode packet
BasicPacket packet(payload);
// verify crc
// skip for current development
// process the packet based on different feature id
BasicPacket::L3Fid_t fid = (BasicPacket::L3Fid_t) packet.getFid();
// we don't care about the type conversion. just create a new one.
switch (fid)
{
case BasicPacket::L3ControlPacket:
{
ControlPacket controlPacket(payload);
// execute command
uint8_t command = controlPacket.getCommand();
switch(command)
{
case 0x0: // query
{
uint8_t sensor_type = controlPacket.getData(0);
switch (sensor_type)
{
case 0x0: // temperature sensor
{
uint8_t temp = getTemperature();
// create a response
DataBlockPacket response;
// set sequence id (the sequence id is configured as incoming sequence id + 1)
response.setSequenceID(controlPacket.getSequenceID() + 1);
// set source id (the source id is the current device ID)
response.setSourceID(aloha.getDeviceID());
// set destination id (the destination ID is the original source address)
response.setDestinationID(controlPacket.getSourceID());
// set source type (temperature)
response.setSourceType(0x0);
// set payload type (signed integer)
response.setPayloadType(0x9);
// copy temperature (use first byte)
response.setData(0, temp);
// calculate crc
response.generateCrc();
// serialize and send it
uint8_t buffer[8];
memset(buffer, 0x0, sizeof(buffer));
// copy bytes into buffer
response.serialize(buffer);
// send to aloha transceiver
aloha.send(buffer, 8, src_addr);
break;
}
case 0x1: // door sensor
{
bool doorState = getDoorState();
// create a response
DataBlockPacket response;
// set sequence id (the sequence id is configured as incoming sequence id + 1)
response.setSequenceID(controlPacket.getSequenceID() + 1);
// set source id (the source id is the current device ID)
response.setSourceID(aloha.getDeviceID());
// set destination id (the destination ID is the original source address)
response.setDestinationID(controlPacket.getSourceID());
// set source type (door state)
response.setSourceType(0x1);
// set payload type (boolean)
response.setPayloadType(0x8);
// copy door state (first byte)
response.setData(0, doorState);
// calculate crc
response.generateCrc();
// serialize and send it
uint8_t buffer[8];
memset(buffer, 0x0, sizeof(buffer));
// copy bytes into buffer
response.serialize(buffer);
// send to aloha transceiver
aloha.send(buffer, 8, src_addr);
break;
}
case 0x2: // service quality
{
int_string_16 rssi;
uint8_t snr;
// get rssi and snr
rssi.int16 = aloha.getRssi();
snr = aloha.getSnr();
// create a response
DataBlockPacket response;
// set sequence id (the sequence id is configured as incoming sequence id + 1)
response.setSequenceID(controlPacket.getSequenceID() + 1);
// set source id (the source id is the current device ID)
response.setSourceID(aloha.getDeviceID());
// set destination id (the destination ID is the original source address)
response.setDestinationID(controlPacket.getSourceID());
// set source type (service quality)
response.setSourceType(0x2);
// set payload type (byte)
response.setPayloadType(0x0);
// set payload
response.setData(0, (uint8_t) snr); // store SNR
response.setData(1, (uint8_t) rssi.bytes[0]); // store higher bits of RSSI
response.setData(2, (uint8_t) rssi.bytes[1]); // store lower bits of RSSI
// calculate crc
response.generateCrc();
// serialize and send it
uint8_t buffer[8];
memset(buffer, 0x0, sizeof(buffer));
// copy bytes into buffer
response.serialize(buffer);
// send to aloha transceiver
aloha.send(buffer, 8, src_addr);
break;
}
default:
break;
}
break;
}
default:
break;
}
break;
}
case BasicPacket::L3DataBlockPacket:
{
DataBlockPacket dataBlockPacket(payload);
uint8_t source_type = dataBlockPacket.getSourceType();
switch(source_type)
{
case 0x2: // service quality
{
uint8_t payload[8];
// copy source type
payload[0] = 0x2;
// copy sensor data
payload[1] = dataBlockPacket.getSourceID();
// first byte is the snr of foreign host
payload[2] = dataBlockPacket.getData(0);
// second and third byte are the rssi of foreign host
payload[3] = dataBlockPacket.getData(1);
payload[4] = dataBlockPacket.getData(2);
// fourth byte is the snr of local host
payload[5] = (uint8_t) aloha.getSnr();
// fifth and sixth byte are the rssi of local host
int_string_16 rssi;
rssi.int16 = aloha.getRssi();
payload[6] = rssi.bytes[0];
payload[7] = rssi.bytes[1];
// make response
SIP.respond(0xf0, payload, 8);
break;
}
default:
break;
}
break;
}
default:
break;
}
}
void enqueueString(char* s, int len) {
for (int i = 0; i < len; i++) {
SerialInputBuffer.enqueue((uint8_t) s[i]);
}
}
void automaticPacketTransmit()
{
/*SerialInputBuffer.enqueue((uint8_t) '<');
SerialInputBuffer.enqueue((uint8_t) '0');
SerialInputBuffer.enqueue((uint8_t) '1');
SerialInputBuffer.enqueue((uint8_t) '0');
SerialInputBuffer.enqueue((uint8_t) '0');
SerialInputBuffer.enqueue((uint8_t) 'f');
SerialInputBuffer.enqueue((uint8_t) 'f');
SerialInputBuffer.enqueue((uint8_t) '>');*/
enqueueString("<0100ff>", 8);
}
int main() {
// initialize radio module
aloha.boardInit();
aloha.updateSettings();
aloha.enable();
// attach serial interrupt handler
pc.attach(&serialInterruptHandler);
// register callback functions for SIP
SIP.registerCommand(0x00, toggleChecksum);
SIP.registerCommand(0x01, queryServiceQuality);
SIP.registerCommand(0x02, configureRadio);
SIP.registerCommand(0x03, radioUpdateSettings);
// register callback functions for aloha transceiver
aloha.registerType(AlohaFrame::Aloha_Data, AlohaDataPacketHandler);
// configure button interrupt
button.fall(automaticPacketTransmit);
while(1) {
SIP.poll();
aloha.poll();
while (SerialOutputBuffer.getCounter() > 0)
{
uint8_t ch;
ch = SerialOutputBuffer.dequeue();
pc.putc(ch);
}
}
}