diff options
-rw-r--r-- | tracker-kicad/control.kicad_sch | 48 | ||||
-rw-r--r-- | tracker-kicad/tracker-kicad.kicad_pcb | 2 | ||||
-rw-r--r-- | tracker-kicad/tracker-kicad.kicad_prl | 6 | ||||
-rw-r--r-- | tracker-kicad/tracker-kicad.kicad_sch | 4 | ||||
-rw-r--r-- | tracker-stm32/README.md | 11 | ||||
-rw-r--r-- | tracker-stm32/platformio.ini | 11 | ||||
-rw-r--r-- | tracker-stm32/src/main.cpp | 170 |
7 files changed, 204 insertions, 48 deletions
diff --git a/tracker-kicad/control.kicad_sch b/tracker-kicad/control.kicad_sch index 4186938..76f1497 100644 --- a/tracker-kicad/control.kicad_sch +++ b/tracker-kicad/control.kicad_sch @@ -1663,7 +1663,7 @@ (stroke (width 0) (type default)) (uuid 29152be4-0d1a-44a8-9854-0b4144b4dd38) ) - (wire (pts (xy 109.22 138.43) (xy 132.08 138.43)) + (wire (pts (xy 102.87 138.43) (xy 132.08 138.43)) (stroke (width 0) (type default)) (uuid 29a2c18f-22e1-45da-a3e5-12ea0b1c0b37) ) @@ -1791,7 +1791,7 @@ (stroke (width 0) (type default)) (uuid a1e09dbe-1cf3-403e-9a26-e9efa21fe29d) ) - (wire (pts (xy 109.22 146.05) (xy 132.08 146.05)) + (wire (pts (xy 102.87 146.05) (xy 132.08 146.05)) (stroke (width 0) (type default)) (uuid a2c54a08-8bc3-4756-8cf5-d467daea0690) ) @@ -1843,7 +1843,7 @@ (stroke (width 0) (type default)) (uuid c9eed8f6-0069-4928-9cd4-30b9409b078d) ) - (wire (pts (xy 109.22 140.97) (xy 132.08 140.97)) + (wire (pts (xy 102.87 140.97) (xy 132.08 140.97)) (stroke (width 0) (type default)) (uuid cb032207-dac4-49e4-9751-be4d8e712ce1) ) @@ -1923,7 +1923,7 @@ (stroke (width 0) (type default)) (uuid fd8144e1-254f-44c2-b762-61b1c5cafd85) ) - (wire (pts (xy 109.22 143.51) (xy 132.08 143.51)) + (wire (pts (xy 102.87 143.51) (xy 132.08 143.51)) (stroke (width 0) (type default)) (uuid ff94eee6-c7fd-4295-834d-75241aac5bfc) ) @@ -1986,6 +1986,10 @@ (effects (font (size 1.27 1.27)) (justify right bottom)) (uuid 3bcaf1f6-c3aa-43c5-a5e5-5418c555060d) ) + (label "ENC_2" (at 102.87 140.97 0) (fields_autoplaced) + (effects (font (size 1.27 1.27)) (justify left bottom)) + (uuid 3e5e4581-4630-4571-b10a-2726ad97bd48) + ) (label "SWDIO" (at 252.73 83.82 0) (fields_autoplaced) (effects (font (size 1.27 1.27)) (justify left bottom)) (uuid 4ab81be1-0683-434d-8ed2-ad9f859a952f) @@ -2034,6 +2038,10 @@ (effects (font (size 1.27 1.27)) (justify left bottom)) (uuid 8e20efb2-25c3-4f95-b3af-b701f276ec29) ) + (label "ENC_8" (at 102.87 146.05 0) (fields_autoplaced) + (effects (font (size 1.27 1.27)) (justify left bottom)) + (uuid 95a554b2-e944-4a8d-9df7-6dd264d9e240) + ) (label "SD_SSn" (at 232.41 35.56 180) (fields_autoplaced) (effects (font (size 1.27 1.27)) (justify right bottom)) (uuid 9c7aebab-babf-4653-b24f-3c65ab261623) @@ -2070,6 +2078,10 @@ (effects (font (size 1.27 1.27)) (justify right bottom)) (uuid c7cf5d5b-134d-4200-9858-51fe1ae36245) ) + (label "ENC_1" (at 102.87 138.43 0) (fields_autoplaced) + (effects (font (size 1.27 1.27)) (justify left bottom)) + (uuid ca3e438f-e397-4df6-b977-d6996006f66f) + ) (label "STATUSn" (at 76.2 146.05 180) (fields_autoplaced) (effects (font (size 1.27 1.27)) (justify right bottom)) (uuid ca7c9f84-a8f7-4a5a-b4ff-26d6c9124d72) @@ -2086,6 +2098,10 @@ (effects (font (size 1.27 1.27)) (justify right bottom)) (uuid d62225e8-b0d3-4e92-adb9-a8c9188ae3e7) ) + (label "ENC_4" (at 102.87 143.51 0) (fields_autoplaced) + (effects (font (size 1.27 1.27)) (justify left bottom)) + (uuid df488886-4495-48ef-858a-780e7dcb3ce1) + ) (label "BTN3n" (at 132.08 102.87 180) (fields_autoplaced) (effects (font (size 1.27 1.27)) (justify right bottom)) (uuid e22ccd77-6e9b-4c39-8556-12bd653e970f) @@ -2628,25 +2644,25 @@ ) ) - (symbol (lib_id "Switch:SW_Coded") (at 96.52 140.97 0) (unit 1) + (symbol (lib_id "Switch:SW_Coded") (at 90.17 140.97 0) (unit 1) (in_bom yes) (on_board yes) (dnp no) (fields_autoplaced) (uuid 48be4c2e-6e08-4e2c-b59f-5dc590e81fc4) - (property "Reference" "SW4" (at 97.155 129.54 0) + (property "Reference" "SW4" (at 90.805 129.54 0) (effects (font (size 1.27 1.27))) ) - (property "Value" "STATUS" (at 97.155 132.08 0) + (property "Value" "STATUS" (at 90.805 132.08 0) (effects (font (size 1.27 1.27))) ) - (property "Footprint" "mpb:Series_221AM_RotaryDIPSwitch" (at 95.885 140.335 0) + (property "Footprint" "mpb:Series_221AM_RotaryDIPSwitch" (at 89.535 140.335 0) (effects (font (size 1.27 1.27)) hide) ) - (property "Datasheet" "/home/bram/Sync/Doc/Datasheet/221AMC rotary dip switch.pdf" (at 95.885 140.335 0) + (property "Datasheet" "/home/bram/Sync/Doc/Datasheet/221AMC rotary dip switch.pdf" (at 89.535 140.335 0) (effects (font (size 1.27 1.27)) hide) ) - (property "MPN" "221AMC10R " (at 96.52 140.97 0) + (property "MPN" "221AMC10R " (at 90.17 140.97 0) (effects (font (size 1.27 1.27)) hide) ) - (property "Need_order" "1" (at 96.52 140.97 0) + (property "Need_order" "1" (at 90.17 140.97 0) (effects (font (size 1.27 1.27)) hide) ) (pin "1" (uuid 12685ae9-4519-47c3-8aef-cc9a6046b521)) @@ -4191,19 +4207,19 @@ ) ) - (symbol (lib_id "power:GND") (at 109.22 134.62 90) (unit 1) + (symbol (lib_id "power:GND") (at 102.87 134.62 90) (unit 1) (in_bom yes) (on_board yes) (dnp no) (fields_autoplaced) (uuid c8f53827-2cf9-4168-ad13-66956abbdc45) - (property "Reference" "#PWR?" (at 115.57 134.62 0) + (property "Reference" "#PWR?" (at 109.22 134.62 0) (effects (font (size 1.27 1.27)) hide) ) - (property "Value" "GND" (at 113.03 135.255 90) + (property "Value" "GND" (at 106.68 135.255 90) (effects (font (size 1.27 1.27)) (justify right) hide) ) - (property "Footprint" "" (at 109.22 134.62 0) + (property "Footprint" "" (at 102.87 134.62 0) (effects (font (size 1.27 1.27)) hide) ) - (property "Datasheet" "" (at 109.22 134.62 0) + (property "Datasheet" "" (at 102.87 134.62 0) (effects (font (size 1.27 1.27)) hide) ) (pin "1" (uuid eb46aa38-f1bf-43b9-9168-24a7f4821358)) diff --git a/tracker-kicad/tracker-kicad.kicad_pcb b/tracker-kicad/tracker-kicad.kicad_pcb index 273259c..1c4efd6 100644 --- a/tracker-kicad/tracker-kicad.kicad_pcb +++ b/tracker-kicad/tracker-kicad.kicad_pcb @@ -876,7 +876,7 @@ (property "ki_keywords" "R res resistor") (path "/717d30dc-b4e1-489a-b7b3-52f4b7c65672/f2cdc043-0377-478a-80ff-8d7e540c230a") (attr smd) - (fp_text reference "R29" (at -2.746667 0 270 unlocked) (layer "F.SilkS") + (fp_text reference "R29" (at -2.746667 0 90 unlocked) (layer "F.SilkS") (effects (font (size 0.7 0.7) (thickness 0.1))) (tstamp 8b3f6693-3ae0-439c-aaa6-ec865474511c) ) diff --git a/tracker-kicad/tracker-kicad.kicad_prl b/tracker-kicad/tracker-kicad.kicad_prl index 3ac6f9b..2d16a13 100644 --- a/tracker-kicad/tracker-kicad.kicad_prl +++ b/tracker-kicad/tracker-kicad.kicad_prl @@ -18,7 +18,7 @@ }, "selection_filter": { "dimensions": false, - "footprints": false, + "footprints": true, "graphics": false, "keepouts": false, "lockedItems": false, @@ -66,8 +66,8 @@ 39, 40 ], - "visible_layers": "ffc3f20_ffffffff", - "zone_display_mode": 0 + "visible_layers": "ffc3f30_ffffffff", + "zone_display_mode": 1 }, "meta": { "filename": "tracker-kicad.kicad_prl", diff --git a/tracker-kicad/tracker-kicad.kicad_sch b/tracker-kicad/tracker-kicad.kicad_sch index c8c897f..c74b6f8 100644 --- a/tracker-kicad/tracker-kicad.kicad_sch +++ b/tracker-kicad/tracker-kicad.kicad_sch @@ -4142,7 +4142,7 @@ (property "Datasheet" "~" (at 166.37 80.01 0) (effects (font (size 1.27 1.27)) hide) ) - (property "MPN" "" (at 166.37 80.01 0) + (property "MPN" "CBR 33pF + 2pF" (at 166.37 80.01 0) (effects (font (size 1.27 1.27)) hide) ) (property "Need_order" "" (at 166.37 80.01 0) @@ -6451,7 +6451,7 @@ (property "Datasheet" "~" (at 156.21 80.01 0) (effects (font (size 1.27 1.27)) hide) ) - (property "MPN" "" (at 156.21 80.01 0) + (property "MPN" "CBR" (at 156.21 80.01 0) (effects (font (size 1.27 1.27)) hide) ) (property "Need_order" "" (at 156.21 80.01 0) diff --git a/tracker-stm32/README.md b/tracker-stm32/README.md index a2bda13..e4518ab 100644 --- a/tracker-stm32/README.md +++ b/tracker-stm32/README.md @@ -31,3 +31,14 @@ Compile: Program NUCLEO board: pio run -t upload + +Program STM32: + + ./openocd.sh + + arm-none-eabi-gdb .pio/build/hercules/firmware.elf + (gdb) target remote :3333 + (gdb) monitor arm semihosting enable + (gdb) load + (gdb) cont + diff --git a/tracker-stm32/platformio.ini b/tracker-stm32/platformio.ini index a50655e..32ece90 100644 --- a/tracker-stm32/platformio.ini +++ b/tracker-stm32/platformio.ini @@ -9,4 +9,13 @@ lib_deps = jgromes/RadioLib@^6.0.0 mikalhart/TinyGPSPlus@1.0.3 arduino-libraries/SD@^1.2.4 - koendv/STM32duino-Semihosting@1.0.5 +; koendv/STM32duino-Semihosting@1.0.5 + +; USB VID/PID is Openmoko Neo1973 serial +build_flags = + -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC + -D USBCON + -D USBD_VID=0x1d50 + -D USBD_PID=0x5120 + -D USB_MANUFACTURER="HB9EGM" + -D USB_PRODUCT="\"HERCULES\"" diff --git a/tracker-stm32/src/main.cpp b/tracker-stm32/src/main.cpp index e452712..7c2a273 100644 --- a/tracker-stm32/src/main.cpp +++ b/tracker-stm32/src/main.cpp @@ -2,7 +2,11 @@ // This file is a bit of a mess, because first it contained aprs434 compressed // code running on STM32H7, and now it contains traditional APRS-over-LoRa for STM32F1 #include <Arduino.h> + +#if defined(SEMIHOSTING) #include <SemihostingStream.h> +#endif + #include <RadioLib.h> #include <Wire.h> #include <TinyGPS++.h> @@ -28,22 +32,15 @@ constexpr int ENCODER_SW_8 = PB15; constexpr int BAT_MEAS = PA0; -// Date Type Codes defined in aprs434.github.io -constexpr int DATA_TYPE_CODE_GEOLOCATION = 0; -constexpr int DATA_TYPE_CODE_STATUS_REPORT = 1; - // TODO: read these settings from the SD Card -constexpr char CALLSIGN[] = "HB9EGM"; -constexpr int SSID = 7; constexpr char CALLSIGN_SSID_PATH[] = "HB9EGM-7>APZEGM"; -constexpr int PATH_CODE = 2; // metropolitan mobile constexpr char SYMBOL_TABLE_IDENTIFIER = '/'; constexpr char SYMBOL_CODE_BICYCLE = 'b'; constexpr char SYMBOL_CODE_FOOT = '['; constexpr long REPORT_TX_INTERVAL = 181000; constexpr long TEXT_TX_INTERVAL = 47000; -constexpr char TEXT_REPORT[] = "mpb.li/git/lora-aprs-hb9egm"; // Max length=28 +constexpr char TEXT_REPORT[] = "mpb.li/git/lora-aprs-hb9egm"; // Max length=28 for compressed #if 0 @@ -68,7 +65,9 @@ constexpr size_t MAX_REPORT_LEN = 48; size_t report_len = 0; uint8_t report[MAX_REPORT_LEN]; +#if defined(SEMIHOSTING) SemihostingStream sh; +#endif static char letterize(int x) { return (char) x + 65; @@ -76,7 +75,21 @@ static char letterize(int x) { void setup() { Wire.begin(); + SerialUSB.begin(); pinMode(LED_STATUSn, OUTPUT); + pinMode(LED_TXn, OUTPUT); + digitalWrite(LED_TXn, HIGH); + + digitalWrite(EN_PA, LOW); + pinMode(EN_PA, OUTPUT); + digitalWrite(EN_RX, LOW); + pinMode(EN_RX, OUTPUT); + + pinMode(ENCODER_SW_1, INPUT_PULLUP); + pinMode(ENCODER_SW_2, INPUT_PULLUP); + pinMode(ENCODER_SW_4, INPUT_PULLUP); + pinMode(ENCODER_SW_8, INPUT_PULLUP); + pinMode(BTN1n, INPUT); #if 0 pinMode(SD_CS, OUTPUT); @@ -87,64 +100,82 @@ void setup() { } #endif - sh.print(F("START")); serialGNSS.begin(9600); +#if defined(SEMIHOSTING) sh.print(F("[RFM] Init ")); +#endif int state = radio.begin(433.775); if (state == RADIOLIB_ERR_NONE) { +#if defined(SEMIHOSTING) sh.println(F("success!")); +#endif } else { +#if defined(SEMIHOSTING) sh.print(F("failed, code ")); sh.println(state); +#endif while (true); } if (radio.setBandwidth(125.0) == RADIOLIB_ERR_INVALID_BANDWIDTH) { +#if defined(SEMIHOSTING) sh.println(F("Selected bandwidth is invalid for this module!")); +#endif while (true); } if (radio.setSpreadingFactor(12) == RADIOLIB_ERR_INVALID_SPREADING_FACTOR) { +#if defined(SEMIHOSTING) sh.println(F("Selected spreading factor is invalid for this module!")); +#endif while (true); } if (radio.setCodingRate(5) == RADIOLIB_ERR_INVALID_CODING_RATE) { +#if defined(SEMIHOSTING) sh.println(F("Selected coding rate is invalid for this module!")); +#endif while (true); } // NOTE: value 0x34 is reserved for LoRaWAN networks and should not be used if (radio.setSyncWord(0x14) != RADIOLIB_ERR_NONE) { +#if defined(SEMIHOSTING) sh.println(F("Unable to set sync word!")); +#endif while (true); } if (radio.setOutputPower(20) == RADIOLIB_ERR_INVALID_OUTPUT_POWER) { +#if defined(SEMIHOSTING) sh.println(F("Selected output power is invalid for this module!")); +#endif while (true); } if (radio.setPreambleLength(8) == RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH) { +#if defined(SEMIHOSTING) sh.println(F("Selected preamble length is invalid for this module!")); +#endif while (true); } // radio.setRfSwitchPins(4, 5); + + digitalWrite(LED_STATUSn, HIGH); } static void handle_radio_error(int state) { +#if defined(SEMIHOSTING) if (state == RADIOLIB_ERR_NONE) { sh.print(F(" RFM OK Datarate: ")); sh.print(radio.getDataRate()); sh.println(F(" bps")); - } else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) { sh.println(F(" too long!")); - } else if (state == RADIOLIB_ERR_TX_TIMEOUT) { sh.println(F(" timeout!")); @@ -154,6 +185,7 @@ static void handle_radio_error(int state) sh.print(F(" failed, code ")); sh.println(state); } +#endif } void append_position_report() @@ -192,6 +224,28 @@ void append_position_report() report[report_len++] = 0x47; } +static void init_report() +{ + report_len = 0; + + report[report_len++] = '<'; + report[report_len++] = 0xFF; + report[report_len++] = 0x01; + + const char* p = CALLSIGN_SSID_PATH; + while (*p) { + report[report_len++] = *(p++); + } +} + +static int read_encoder() +{ + return 15 - (digitalRead(ENCODER_SW_1) + + 2 * digitalRead(ENCODER_SW_2) + + 4 * digitalRead(ENCODER_SW_4) + + 8 * digitalRead(ENCODER_SW_8)); +} + void loop() { while (serialGNSS.available() > 0) { @@ -202,6 +256,56 @@ void loop() if (now - lastGnssPoll > 1000) { lastGnssPoll = now; + const int encoder_value = read_encoder(); + const bool btn1 = digitalRead(BTN1n) == 0; + digitalWrite(LED_TXn, not btn1); + + if (encoder_value == 1) { + digitalWrite(EN_RX, HIGH); + digitalWrite(EN_PA, LOW); + } + else if (encoder_value == 2) { + digitalWrite(EN_RX, LOW); + digitalWrite(EN_PA, HIGH); + } + else { + digitalWrite(EN_RX, LOW); + digitalWrite(EN_PA, LOW); + } + + if (SerialUSB) { + const long latitude = gps.location.lat(); + SerialUSB.print(F("Lat ")); + SerialUSB.print(latitude); + + const long longitude = gps.location.lng(); + SerialUSB.print(F(" Lon ")); + SerialUSB.print(longitude); + + const byte SIV = gps.satellites.value(); + SerialUSB.print(F(" SIV: ")); + SerialUSB.print(SIV); + + SerialUSB.print(F(" Enc: ")); + SerialUSB.print(encoder_value); + + SerialUSB.print(F(" BTN: ")); + SerialUSB.println((int)btn1); + } + } +} + +void oldloop() +{ + while (serialGNSS.available() > 0) { + gps.encode(serialGNSS.read()); + } + + const auto now = millis(); + if (now - lastGnssPoll > 1000) { + lastGnssPoll = now; + +#if 0 const long latitude = gps.location.lat(); sh.print(F("Lat ")); sh.print(latitude); @@ -213,23 +317,14 @@ void loop() const byte SIV = gps.satellites.value(); sh.print(F(" SIV: ")); sh.println(SIV); +#endif + if (now - lastPositionReport > REPORT_TX_INTERVAL) { lastPositionReport = now; - digitalWrite(LED_STATUSn, LOW); - - report_len = 0; - - report[report_len++] = '<'; - report[report_len++] = 0xFF; - report[report_len++] = 0x01; - - const char* p = CALLSIGN_SSID_PATH; - while (*p) { - report[report_len++] = *p; - p++; - } + digitalWrite(LED_TXn, LOW); + init_report(); report[report_len++] = ':'; report[report_len++] = '!'; report[report_len++] = SYMBOL_TABLE_IDENTIFIER; @@ -237,12 +332,37 @@ void loop() int state = radio.transmit(report, report_len); handle_radio_error(state); - digitalWrite(LED_STATUSn, HIGH); + digitalWrite(LED_TXn, HIGH); + } + } + + if (now - lastTextReport > TEXT_TX_INTERVAL) { + lastTextReport = now; + digitalWrite(LED_TXn, LOW); + + init_report(); + report[report_len++] = ':'; + report[report_len++] = '>'; + const char* p = TEXT_REPORT; + while (*p) { + report[report_len++] = *(p++); } + + int state = radio.transmit(report, report_len); + handle_radio_error(state); + + digitalWrite(LED_TXn, HIGH); } } #if 0 +// Date Type Codes defined in aprs434.github.io +constexpr int DATA_TYPE_CODE_GEOLOCATION = 0; +constexpr int DATA_TYPE_CODE_STATUS_REPORT = 1; +constexpr char CALLSIGN[] = "HB9EGM"; +constexpr int SSID = 7; +constexpr int PATH_CODE = 2; // metropolitan mobile + void loop() { while (serialGNSS.available() > 0) { |