313 lines
7.2 KiB
C++
313 lines
7.2 KiB
C++
#include <Arduino.h>
|
|
#include <avr/sleep.h>
|
|
#include <avr/interrupt.h>
|
|
#include <SPI.h>
|
|
#include <Wire.h>
|
|
#include <EEPROM.h>
|
|
#include <LoRaWAN.h>
|
|
|
|
// OLED
|
|
#include <U8x8lib.h>
|
|
U8X8_SSD1306_128X64_NONAME_HW_I2C oled(U8X8_PIN_NONE, PIN_PB0, PIN_PB1);
|
|
|
|
// GPS
|
|
#include <gps.h>
|
|
Gps gps;
|
|
bool hasFix = false;
|
|
bool oldFix = false;
|
|
|
|
// Button Handling
|
|
#include <Button2.h>
|
|
Button2 btn = Button2(PIN_PC2);
|
|
bool adhocsend = false;
|
|
|
|
// Modes for Display Menus and Navigation
|
|
enum Modes {
|
|
M_NORMAL,
|
|
M_SETUP
|
|
};
|
|
|
|
enum Settings {
|
|
S_NONE,
|
|
S_INTERVAL,
|
|
S_KEYSET,
|
|
S_BRIGHT,
|
|
S_EXIT
|
|
};
|
|
|
|
Modes amode = M_NORMAL; // Active Mode
|
|
Modes omode = M_NORMAL; // Previous Mode
|
|
Settings cset = S_INTERVAL; // Current Setting
|
|
Settings aset = S_NONE; // Selected Setting
|
|
|
|
#define EEPROM_KEYSET_ADR 0
|
|
#define EEPROM_INTERVAL_ADR 1
|
|
#define EEPROM_BRIGHTNESS_ADR 2
|
|
|
|
// LoRa
|
|
#include "config.h" // Contains LoRa ABP Keys
|
|
#define DIO0 PIN_PA4
|
|
#define NSS PIN_PA5
|
|
RFM95 rfm(DIO0, NSS);
|
|
LoRaWAN lora = LoRaWAN(rfm);
|
|
uint16_t Frame_Counter_Tx = 0x0001;
|
|
|
|
// Some Status Variables
|
|
uint8_t interval = 20; // Sending Interval in Settings
|
|
uint8_t packets = 0; // Sent LoRa Packets
|
|
uint8_t keyset = 1; // LoRa KeySet
|
|
uint8_t bright = 128; // Brightness
|
|
String statusmsg = "";
|
|
|
|
uint8_t loraBuffer[9]; // Lora Data Packet
|
|
uint32_t lastmillis;
|
|
|
|
// Supply Voltage
|
|
uint16_t readSupplyVoltage() {
|
|
uint16_t temp = 0;
|
|
analogReference(VDD);
|
|
VREF.CTRLA = VREF_ADC0REFSEL_1V5_gc;
|
|
ADC0.CTRLD = ADC_INITDLY_DLY256_gc;
|
|
ADC0_CTRLB = ADC_SAMPNUM_ACC64_gc;
|
|
uint16_t reading = analogRead(ADC_INTREF);
|
|
temp = reading / 64;
|
|
uint32_t intermediate = 1534500;
|
|
reading = 0;
|
|
reading = intermediate / temp;
|
|
return reading;
|
|
}
|
|
|
|
void loraKeySetup(uint8_t keyset) {
|
|
if (keyset == 1)
|
|
lora.setKeys(NwkSkey_1, AppSkey_1, DevAddr_1);
|
|
if (keyset == 2)
|
|
lora.setKeys(NwkSkey_2, AppSkey_2, DevAddr_2);
|
|
}
|
|
|
|
void fillLine() {
|
|
for (uint8_t i = oled.tx; i<15; i++)
|
|
oled.print(" ");
|
|
oled.println("");
|
|
}
|
|
|
|
// Button Handler Function
|
|
void handler(Button2& btn) {
|
|
switch (btn.getClickType()) {
|
|
case SINGLE_CLICK:
|
|
if (amode == M_SETUP) {
|
|
if (aset == S_INTERVAL) {
|
|
interval = interval += 10;
|
|
if (interval > 30)
|
|
interval = 10;
|
|
} else if (aset == S_KEYSET) {
|
|
keyset = keyset + 1;
|
|
if (keyset > 2)
|
|
keyset = 1;
|
|
loraKeySetup(keyset);
|
|
} else if (aset == S_BRIGHT) {
|
|
bright += 32;
|
|
if (bright > 255)
|
|
bright = 32;
|
|
oled.setContrast(bright);
|
|
} else {
|
|
switch (cset) {
|
|
case S_INTERVAL:
|
|
cset = S_KEYSET;
|
|
break;
|
|
case S_KEYSET:
|
|
cset = S_BRIGHT;
|
|
break;
|
|
case S_BRIGHT:
|
|
cset = S_EXIT;
|
|
break;
|
|
case S_EXIT:
|
|
cset = S_INTERVAL;
|
|
break;
|
|
}
|
|
}
|
|
} else if (amode == M_NORMAL) {
|
|
statusmsg = "Adhoc Request";
|
|
adhocsend = true;
|
|
}
|
|
break;
|
|
case LONG_CLICK:
|
|
switch (amode) {
|
|
case M_NORMAL:
|
|
amode = M_SETUP;
|
|
cset = S_INTERVAL;
|
|
break;
|
|
case M_SETUP:
|
|
if (cset == S_EXIT) {
|
|
aset = S_NONE;
|
|
amode = M_NORMAL;
|
|
EEPROM.update(EEPROM_KEYSET_ADR, keyset);
|
|
EEPROM.update(EEPROM_INTERVAL_ADR, interval);
|
|
EEPROM.update(EEPROM_BRIGHTNESS_ADR, bright);
|
|
} else if (aset == S_NONE) {
|
|
aset = cset;
|
|
} else {
|
|
aset = S_NONE;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Draw the Display
|
|
void updateDisplay() {
|
|
uint16_t buffer[6];
|
|
gps.gdisplay(buffer);
|
|
|
|
oled.home();
|
|
oled.setFont(u8x8_font_victoriabold8_r);
|
|
|
|
if (amode != omode) {
|
|
oled.clear();
|
|
omode = amode;
|
|
}
|
|
|
|
if (amode == M_SETUP) {
|
|
oled.println ("**** SETUP ****");
|
|
oled.println ("");
|
|
char tmp = ' ';
|
|
|
|
tmp = (cset == S_INTERVAL) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
tmp = (aset == S_INTERVAL) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
oled.print("Interval: ");
|
|
oled.println(interval);
|
|
|
|
tmp = (cset == S_KEYSET) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
tmp = (aset == S_KEYSET) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
oled.print("ABP Keys: ");
|
|
oled.println(keyset);
|
|
tmp = (cset == S_BRIGHT) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
tmp = (aset == S_BRIGHT) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
oled.print("Brightn.: ");
|
|
oled.println(bright);
|
|
|
|
oled.println("");
|
|
tmp = (cset == S_EXIT) ? '>' : ' ';
|
|
oled.print(tmp);
|
|
oled.println(" Exit Setup");
|
|
|
|
} else if (amode == M_NORMAL) {
|
|
if (hasFix) {
|
|
if (hasFix != oldFix){
|
|
oled.clear();
|
|
oldFix = hasFix;
|
|
}
|
|
oled.print("HDOP: ");
|
|
oled.print(buffer[0]);
|
|
fillLine();
|
|
oled.print("Sats: ");
|
|
oled.print(buffer[1]);
|
|
oled.print("/");
|
|
oled.print(buffer[2]);
|
|
fillLine();
|
|
oled.print("Int: ");
|
|
oled.print(interval);
|
|
fillLine();
|
|
oled.print("Packet: ");
|
|
oled.print(packets);
|
|
fillLine();
|
|
oled.print("Alt: ");
|
|
oled.print(buffer[3]);
|
|
fillLine();
|
|
oled.print("Speed: ");
|
|
oled.print(buffer[4]);
|
|
fillLine();
|
|
oled.print("Bat: ");
|
|
oled.print((float)readSupplyVoltage()/1000);
|
|
fillLine();
|
|
} else {
|
|
if (hasFix != oldFix){
|
|
oled.clear();
|
|
oldFix = hasFix;
|
|
}
|
|
oled.print("NO GPS FIX");
|
|
fillLine();
|
|
oled.print("Sats: ");
|
|
oled.print(buffer[1]);
|
|
oled.print("/");
|
|
oled.print(buffer[2]);
|
|
fillLine();
|
|
oled.print("Int: ");
|
|
oled.print(interval);
|
|
fillLine();
|
|
oled.print("Packet: ");
|
|
oled.print(packets);
|
|
fillLine();
|
|
oled.print("Bat: ");
|
|
oled.print((float)readSupplyVoltage()/1000);
|
|
fillLine();
|
|
}
|
|
oled.print(statusmsg);
|
|
oled.println(" ");
|
|
}
|
|
}
|
|
|
|
// Setup
|
|
void setup() {
|
|
// GPS Setup
|
|
Serial.begin(9600);
|
|
|
|
// Button
|
|
btn.setLongClickTime(1000);
|
|
btn.setClickHandler(handler);
|
|
btn.setLongClickHandler(handler);
|
|
|
|
// OLED Setup
|
|
Wire.begin();
|
|
Wire.setClock(400000L);
|
|
oled.begin();
|
|
oled.setPowerSave(0);
|
|
oled.setFlipMode(1);
|
|
oled.clear();
|
|
|
|
// Get Settings from EEPROM
|
|
EEPROM.get(EEPROM_KEYSET_ADR, keyset);
|
|
if (keyset < 1 || keyset > 2) keyset = 1;
|
|
|
|
EEPROM.get(EEPROM_INTERVAL_ADR, interval);
|
|
if (interval < 10 || interval > 30) interval = 20;
|
|
|
|
EEPROM.get(EEPROM_BRIGHTNESS_ADR, bright);
|
|
if (bright < 0 || bright > 255) bright = 128;
|
|
oled.setContrast(bright);
|
|
|
|
// Lora Initialization
|
|
rfm.init();
|
|
loraKeySetup(keyset);
|
|
}
|
|
|
|
// Main Loop
|
|
void loop() {
|
|
hasFix = gps.checkGpsFix();
|
|
uint32_t curmillis = millis();
|
|
if (hasFix && (((uint32_t)(curmillis - lastmillis) >= interval*1000) || adhocsend)) {
|
|
if (adhocsend) {
|
|
statusmsg = "Sending (Adhoc)";
|
|
} else {
|
|
statusmsg = "Sending";
|
|
}
|
|
updateDisplay();
|
|
adhocsend = false;
|
|
|
|
gps.buildPacket(loraBuffer);
|
|
lora.Send_Data((unsigned char *)&loraBuffer, sizeof(loraBuffer), Frame_Counter_Tx, SF7BW125, 0x01);
|
|
packets++;
|
|
Frame_Counter_Tx++;
|
|
lastmillis = millis();
|
|
} else {
|
|
updateDisplay();
|
|
}
|
|
statusmsg = "";
|
|
btn.loop();
|
|
} |