From 69d2363b59c0d06b76a7e3e4480f632ffa836548 Mon Sep 17 00:00:00 2001 From: Wolfgang Klenk Date: Wed, 12 Apr 2017 20:02:13 +0200 Subject: [PATCH] Check-in of hardware abstraction layer --- README.md | 26 +++ examples/hello/build/aes.o | Bin 0 -> 10612 bytes examples/hello/build/debug.o | Bin 0 -> 2864 bytes examples/hello/build/gpio.o | Bin 0 -> 4648 bytes examples/hello/build/hal.o | Bin 0 -> 7452 bytes examples/hello/build/hello.out | Bin 0 -> 66028 bytes examples/hello/build/lmic.o | Bin 0 -> 31720 bytes examples/hello/build/main.o | Bin 0 -> 1840 bytes examples/hello/build/oslmic.o | Bin 0 -> 2416 bytes examples/hello/build/radio.o | Bin 0 -> 7580 bytes examples/projects.gmk | 105 ++------- examples/projects.gmk.lmic_1.6_original | 121 ++++++++++ lora_gps_hat/debug.c | 82 +++++++ lora_gps_hat/debug.h | 63 +++++ lora_gps_hat/gpio.c | 200 ++++++++++++++++ lora_gps_hat/gpio.h | 62 +++++ lora_gps_hat/hal.c | 292 ++++++++++++++++++++++++ 17 files changed, 863 insertions(+), 88 deletions(-) create mode 100644 examples/hello/build/aes.o create mode 100644 examples/hello/build/debug.o create mode 100644 examples/hello/build/gpio.o create mode 100644 examples/hello/build/hal.o create mode 100755 examples/hello/build/hello.out create mode 100644 examples/hello/build/lmic.o create mode 100644 examples/hello/build/main.o create mode 100644 examples/hello/build/oslmic.o create mode 100644 examples/hello/build/radio.o create mode 100644 examples/projects.gmk.lmic_1.6_original create mode 100644 lora_gps_hat/debug.c create mode 100644 lora_gps_hat/debug.h create mode 100644 lora_gps_hat/gpio.c create mode 100644 lora_gps_hat/gpio.h create mode 100644 lora_gps_hat/hal.c diff --git a/README.md b/README.md index ad1f611..00446e6 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,21 @@ targeted to RPi and Dragino LoRA/GPS HAT. The goal was to keep the LMIC 1.6 sourcecode untouched, and just provide a Hardware Abstraction Layer (HAL) for Raspberry Pi and Dragino LoRa/GPS HAT. +## Installation + +### WiringPi +To control the RPi's GPI ports, the WiringPi GPIO interface library has to +be installed. On some operating systems WiringPi is already installed per +default. For instructions on manual installation please refer to the +following site: +http://wiringpi.com/download-and-install/ + +### Enable SPI interface +Per default, the SPI ports on the Raspberry Pi are disabled. You need to +manually enable them using raspi-config. +Follow the instructions given here: +https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md + ## Note on LMIC 1.6 license Text copied from https://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html @@ -16,4 +31,15 @@ IBM "LoRa WAN in C" is the LoRa WAN implementation of choice, and a perfect match to the IBM LRSC on the end device. It is provided as open source under the BSD License. +## Example "hello" +Directory: /examples/hello +Modifications neccessary: None + +This example does not use radio, it just periodically logs a counter value. +Can be used to checked if the timer implemenation on RPi works as expected. + + cd examples/hello + make clean + make + sudo ./build/hello.out diff --git a/examples/hello/build/aes.o b/examples/hello/build/aes.o new file mode 100644 index 0000000000000000000000000000000000000000..b1a2edaa4d0715b4602f7d443c10d96e06ccf962 GIT binary patch literal 10612 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 literal 0 HcmV?d00001 diff --git a/examples/hello/build/hal.o b/examples/hello/build/hal.o new file mode 100644 index 0000000000000000000000000000000000000000..657dc44a45f32b92d9929f285592b1c2f0dc5626 GIT binary patch literal 7452 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 literal 0 HcmV?d00001 diff --git a/examples/hello/build/lmic.o b/examples/hello/build/lmic.o new file mode 100644 index 0000000000000000000000000000000000000000..2844d18b71161cf7c3f0ba8b3a30882a5d258aca GIT binary patch literal 31720 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 literal 0 HcmV?d00001 diff --git a/examples/hello/build/main.o b/examples/hello/build/main.o new file mode 100644 index 0000000000000000000000000000000000000000..d345b104302b4278ce8dce37a09b72b578c884d9 GIT binary patch literal 1840 zcmcIkL2naR5T5m}g9E8*q69*drlv|!5X!P3QxO!ThBOd04Jr``4v4U}7heW%H+2-?N2QPWH9s*?h~|eEj$5_VKL` zp~>9DD+~MO)P6T*z5RZB`}K8ay)Dkq?Q7s>eq)QdIh8Ycq z8rJ>F;g9x;l!K^nwt&VLW@gS5#uwejN~!7wg`z!apPV@198Dsbc2MJbZmBB95ro+< zrKcxn^cs6J{nmgnXdE<$j6=pJnPGFp814Do5W8`=7P%#0R8MeOM|ID)Bk%i2?1~$? zVwV~XvFl+%%3-bM1<-;p^6U#2uS_%|w|qzJ>BR-xjiP$B)Qr3a&d_b?d9mc(c3L-g zO_PX;PufheB$rO0exKqN(18B&E}hvOGbP)lXQdzV3VaQoK?knyyi9QJ_b)uLM0Yxu z=mfEB${t;)cuyC{^r*}Tupj-$fs8djh4^%epF?~(#lJzUjk88g8~F`QfaJ?vJpE3n zKZ5gqQ*fT=N1!(9zi0v^U+?0-b#bY=)xa*xn9H%1v5HiKYILg^lqGB|-S(pCdNkXt zD)P0rx{J(vcO?vFS2J ztKu-J?UaGmn}HvOE4;=J@R320Ux^1qo)8a;JS7f^{7F2N%tr=;@diAD5qnDn|A&a* ztA()`!Hdoj@nVOFpTdcwBAg%A{a^bGg;*kbnu>^vOeoV+&e`gPf2Hz&LEy!>70X$N zW6Bqb>tEM$su!fVmUs-#`gEP%i@J^-#B7ma62^XbTpiPOr;%YD>uL8v3UQQtQKL^Q zOtK;yOr}iJOUU7DykcyuJD~|s*X>8F??CxE1ebv_T}RY+pi~5TizNSJ*n{`T!}*NU N{l*~tj+{2#?>`>*E=&Lb literal 0 HcmV?d00001 diff --git a/examples/hello/build/oslmic.o b/examples/hello/build/oslmic.o new file mode 100644 index 0000000000000000000000000000000000000000..952c670c9fa4db7fc86d782a88eedfd0a56972ed GIT binary patch literal 2416 zcma)7O>7%Q6n^X7q;3*mDK2$m6ILZ4Bbvp9f>KVYQYe9hpR_$7RVr&|g_rmz@@^%N zkU)e37epmEa4DD@2M!UZ9;k#W4jedC2yy6%#H<9NNO0>3^L@Ls?$oL(UNnC1d+(b! z@6F6k-hFoYIm0j{6GJL;6Ny~flSIajCaNNnk{5Y??hkA0qn)CB5sTgH=bc{v-@)Kd zeaMHGe@~_;E@M*dZJW~DX3W}}iv>BRuCDClWipi;zuOk=HnvewlXcdV_8zs(FD-_GjJt2J5EJbK96 zrTChvkMp_atn&Y?`O(jWpnlG?kT>hmVxy{08@X-tQ$RoDokboS`LDpX(MQ24#d&8l zrY+bvfjwVE4d@|vhn{YrC-!e+KIiB)=<64?^@~ng!)L07FSQyhRYUPM^)ysHcWd=n z*#837&sFQca*wd)wd}0YUN+-#jX!!O*Y8k2w=dg2o(<2A^Vwq$wOHz0apn^j6xQ>< zPOi1ODp@GY9VjbMhXt2j*K)aXsH*UJW|xrn-??UBBr@{#%i_YhL7uTMI*R z>z!81Z^PH_M813Sr89G33J-)i)dQsF3YUd+AOp3krNB`z6`DdU<&0Ags5fgv9 zm}2q6NCd9~*p}d1*2EH9Lu4>s8TyPQeptiz!9IZzVdNBlYFK2-FKC$gE@+tReX3!` zU%>~KN;?0vh8Zsm+Zs+x=%(OiYhnss2u)1cBM&Id9`>Q$hqX9sx!Ic}y*@P(Ul_qJ zs5wPw<~uVIKL>mXv zqtijlPl!=aUk{m~-t@ihqStKJc!QZ^EeO3@(_dPBHB7MI9zyW3(vY1(=3LW#U6k1A zY$TKG4ZprlMmK?B)AzZDctfOozXI`u;$e^Z0UJ4)XFl?T((hBugX z7l-#;@TI1LR%9>6LJGyk3sc=y8AQ(Odi?KV8}vGqf_0p0=} ZeDC&Sun!x9d#C4{$CL33e3@kH{s+oR>EQqX literal 0 HcmV?d00001 diff --git a/examples/hello/build/radio.o b/examples/hello/build/radio.o new file mode 100644 index 0000000000000000000000000000000000000000..f11893ca067ab89761dd7fff53beabeab3758801 GIT binary patch literal 7580 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 +#include + +#include "lmic.h" +#include "debug.h" + +void debug_init () { + fprintf(stdout, "%09d Debug: Initializing\n", osticks2ms(hal_ticks())); +} + +void debug_str (const char* str) { + fprintf(stdout, "%09d Debug: %s\n", osticks2ms(hal_ticks()), str); +} + +void debug_val (const char* label, u4_t val) { + fprintf(stdout, "%09d Debug: Label '%s' value 0x%x\n", osticks2ms(hal_ticks()), label, val); +} + +void debug_led (int val) { + // fprintf(stdout, "Debug: Set LED to 0x%02x\n", val); +} + +void debug_event (int ev) { + static const char* evnames[] = { + [EV_SCAN_TIMEOUT] = "SCAN_TIMEOUT", + [EV_BEACON_FOUND] = "BEACON_FOUND", + [EV_BEACON_MISSED] = "BEACON_MISSED", + [EV_BEACON_TRACKED] = "BEACON_TRACKED", + [EV_JOINING] = "JOINING", + [EV_JOINED] = "JOINED", + [EV_RFU1] = "RFU1", + [EV_JOIN_FAILED] = "JOIN_FAILED", + [EV_REJOIN_FAILED] = "REJOIN_FAILED", + [EV_TXCOMPLETE] = "TXCOMPLETE", + [EV_LOST_TSYNC] = "LOST_TSYNC", + [EV_RESET] = "RESET", + [EV_RXCOMPLETE] = "RXCOMPLETE", + [EV_LINK_DEAD] = "LINK_DEAD", + [EV_LINK_ALIVE] = "LINK_ALIVE", + [EV_SCAN_FOUND] = "SCAN_FOUND", + [EV_TXSTART] = "EV_TXSTART", + }; + debug_str((ev < sizeof(evnames)/sizeof(evnames[0])) ? evnames[ev] : "EV_UNKNOWN" ); +} + +void debug_buf (const u1_t* buf, int len) { + fprintf(stdout, "%09d Debug: Buffer received. length=%d\n", osticks2ms(hal_ticks()), len); +} diff --git a/lora_gps_hat/debug.h b/lora_gps_hat/debug.h new file mode 100644 index 0000000..e495be6 --- /dev/null +++ b/lora_gps_hat/debug.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014-2016 IBM Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// intialize debug library +void debug_init (void); + +// set LED state +void debug_led (int val); + +// write character to USART +void debug_char (char c); + +// write byte as two hex digits to USART +void debug_hex (u1_t b); + +// write buffer as hex dump to USART +void debug_buf (const u1_t* buf, int len); + +// write 32-bit integer as eight hex digits to USART +void debug_uint (u4_t v); + +// write 32-bit integer as signed decimal digits to USART +void debug_int (s4_t v); + +// write nul-terminated string to USART +void debug_str (const char* str); + +// write LMiC event name to USART +void debug_event (int ev); + +// write label and 32-bit value as hex to USART +void debug_val (const char* label, u4_t val); + +// write label and 32-bit value as signed decimal to USART +void debug_valdec (const char* label, s4_t val); + +// convert integer 'val' to ASCII string (bin/oct/dec/hex/base36) +// store string at 'buf', return number of characters written +int debug_fmt (char* buf, int max, s4_t val, int base, int width, char pad); diff --git a/lora_gps_hat/gpio.c b/lora_gps_hat/gpio.c new file mode 100644 index 0000000..5685531 --- /dev/null +++ b/lora_gps_hat/gpio.c @@ -0,0 +1,200 @@ +// +// BSD 3-Clause License +// +// Hardware Abstraction Layer (HAL) targeted to Raspberry Pi and +// Dragino LoRa/GPS HAT +// +// Copyright (c) 2017, Wolfgang Klenk +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gpio.h" + +/** + * Ask the kernel to export control of a GPIO to userspace by writing its number to file + * /sys/class/gpio/export. + */ +void gpioExportPin(int pin) { + static const char* fn = "/sys/class/gpio/export"; + int fd = open(fn, O_WRONLY); + if(fd < 0) { + perror(fn); + exit(1); + } + + char str_pin[16]; + snprintf(str_pin, 16, "%d", pin); + + size_t rc = write(fd, str_pin, strlen(str_pin)); + if(rc != strlen(str_pin)) { + perror("exportPin"); + exit(1); + } + + close(fd); +} + +/** + * Reverses the effect of exporting a GPIO to userspace by writing its number to file + * /sys/class/gpio/unexport. + */ +void gpioUnexportPin(int pin) { + static const char* fn = "/sys/class/gpio/unexport"; + int fd = open(fn, O_WRONLY); + if(fd < 0) { + perror(fn); + exit(1); + } + + char str_pin[16]; + snprintf(str_pin, 16, "%d", pin); + + size_t rc = write(fd, str_pin, strlen(str_pin)); + if(rc != strlen(str_pin)) { + // perror("gpioUnexportPin"); + // exit(1); + } + + close(fd); +} + +/** + * Sets the direction of a GPIO pin. + * Reads as either "in" or "out". This value may normally be written. + * Writing as "out" defaults to initializing the value as low. + * To ensure glitch free operation, values "low" and "high" may be written to + * configure the GPIO as an output with that initial value. + */ +void gpioSetPinDirection(int pin, const char* direction) { + + const int BUFSIZE = 64; + char fn[BUFSIZE]; + snprintf(fn, BUFSIZE, "/sys/class/gpio/gpio%d/direction", pin); + int fd = open(fn, O_WRONLY); + if(fd < 0) { + perror(fn); + exit(1); + } + + size_t rc = write(fd, direction, strlen(direction)); + if(rc != strlen(direction)) { + perror("gpioSetPinDirection"); + exit(1); + } + + close(fd); +} + +/** + * Sets the signal edge(s) that will make poll(2) on the "value" file return. + * Reads as either "none", "rising", "falling", or "both". + * This file exists only if the pin can be configured as an interrupt generating input pin. + */ +void gpioSetPinEdge(int pin, void* edge) { + + const int BUFSIZE = 64; + char fn[BUFSIZE]; + snprintf(fn, BUFSIZE, "/sys/class/gpio/gpio%d/edge", pin); + int fd = open(fn, O_WRONLY); + if(fd < 0) { + perror(fn); + exit(EXIT_FAILURE); + } + + size_t rc = write(fd, edge, strlen(edge)); + if(rc != strlen(edge)) { + perror("setPinEdge"); + exit(EXIT_FAILURE); + } + + + close(fd); +} + +int gpioWaitForInterrupt(const int *pins, size_t npins, int timeout_ms) { + + struct pollfd pl[npins]; + + const int BUFSIZE = 64; + char fn[BUFSIZE]; + + for (int i=0 ; i 0) { + rc |= (1< +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "lmic.h" +#include "gpio.h" + +// Note: WiringPi Pin Numbering Schema +const int WIRING_PI_PIN_NSS = 6; +const int WIRING_PI_PIN_RST = 0; +const int WIRING_PI_PIN_DIO[3] = { 7, 4, 5 }; + +// Note: BCM Pin Numbering Schema +const int BCM_PIN_DIO[3] = { 4, 23, 24 }; + +// Local function prototypes +void hal_time_init(); +void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result); + +// Used to store the current time +static struct timespec ts_start; + +static s4_t sleep_interval_ms = 0; + +void hal_init () { + hal_time_init(); + +#ifdef DEBUG_HAL + fprintf(stdout, "%09d HAL: Initializing ...\n", osticks2ms(hal_ticks())); +#endif + + wiringPiSetup(); + + // Pin Direction + pinMode(WIRING_PI_PIN_NSS, OUTPUT); + pinMode(WIRING_PI_PIN_RST, INPUT); + + // WiringPi is missing a feature to _blocking_ wait for pins change + // their values using the OS system call "poll". For this reason, we + // needed to implement it on our own. + for (int i=0 ; i<3 ; i++) { + gpioUnexportPin(BCM_PIN_DIO[i]); + } + + for (int i=0 ; i<3 ; i++) { + gpioExportPin(BCM_PIN_DIO[i]); + gpioSetPinDirection(BCM_PIN_DIO[i], GPIO_DIRECTION_IN); + gpioSetPinEdge(BCM_PIN_DIO[i], GPIO_EDGE_RISING); + } + + int rc = wiringPiSPISetup(0, 10000000); + if (rc < 0) { + fprintf(stderr, "HAL: Initialization of SPI failed: %s\n", strerror(errno)); + hal_failed(); + } + +} + +void hal_failed () { + fprintf(stderr, "%09d HAL: Failed. Aborting.\n", osticks2ms(hal_ticks())); + for (int i=0 ; i<3 ; i++) { + gpioUnexportPin(BCM_PIN_DIO[i]); + } + exit(EXIT_FAILURE); +} + +// set radio NSS pin to given value +void hal_pin_nss (u1_t val) { + digitalWrite(WIRING_PI_PIN_NSS, val==0 ? LOW : HIGH); +} + +// switch between radio RX/TX +void hal_pin_rxtx (u1_t val) { +#ifdef DEBUG_HAL + val > 0 ? fprintf(stdout, "%09d HAL: Sending ...\n", osticks2ms(hal_ticks()), val) : fprintf(stdout, "%09d HAL: Receiving ...\n", osticks2ms(hal_ticks()), val); +#endif + + // Nothing to do. There is no such pin in the Lora/GPS HAT module. +} + +// set radio RST pin to given value (or keep floating!) +void hal_pin_rst (u1_t val) { +#ifdef DEBUG_HAL + fprintf(stdout, "%09d HAL: Set radio RST pin to 0x%02x\n", osticks2ms(hal_ticks()), val); +#endif + + if(val == 0 || val == 1) { // drive pin + pinMode(WIRING_PI_PIN_RST, OUTPUT); + digitalWrite(WIRING_PI_PIN_RST, val==0 ? LOW : HIGH); + } else { // keep pin floating + pinMode(WIRING_PI_PIN_RST, INPUT); + } +} + +// perform 8-bit SPI transaction. +// write given byte outval to radio, read byte from radio and return value. +u1_t hal_spi (u1_t out) { + static u1_t isAddress = 0x01; + static u1_t address = 0x00; + u1_t value = out; + + if (isAddress) { + address = out; + } + + u1_t rc = wiringPiSPIDataRW(0, &out, 1); + if (rc < 0) { + fprintf(stderr, "HAL: Cannot send data on SPI: %s\n", strerror(errno)); + hal_failed(); + } + +/* + if (!isAddress && (address != 0x2c)) { + if (address & 0x80) { + fprintf(stdout, "%09d HAL: SPI write to address 0x%02x value 0x%02x\n", osticks2ms(hal_ticks()), address & 0x7F, value); + fprintf(stdout, " writeReg(0x%02x, 0x%02x);\n", address & 0x7F, value); + } else { + fprintf(stdout, "%09d HAL: SPI read from address 0x%02x value 0x%02x\n", osticks2ms(hal_ticks()), address, out); + } + } +*/ + + isAddress = !isAddress; + + return out; +} + +void hal_disableIRQs () { +} + +void hal_enableIRQs () { +} + +// store current timer value of the system. +void hal_time_init() { + int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &ts_start); + if (rc < 0) { + fprintf(stderr, "HAL: Cannot initialize timer: %s\n", strerror(errno)); + hal_failed(); + } +} + +// return 32 bit system time in ticks. +// OSTICKS_PER_SEC has to be defined, else the default 32768 is used. +// OSTICKS_PER_SEC must be in range [10000:64516]. One tick must be 15.5us .. 100us long. +u4_t hal_ticks () { + + struct timespec ts; + int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + if (rc < 0) { + fprintf(stderr, "HAL: Cannot get current time: %s\n", strerror(errno)); + hal_failed(); + } + + struct timespec ts_diff; + timespec_diff(&ts_start, &ts, &ts_diff); + + ostime_t ticks_sec = sec2osticks(ts_diff.tv_sec); + ostime_t ticks_nsec = us2osticks(ts_diff.tv_nsec / 1000); + + u4_t ticks = ticks_sec + ticks_nsec; + + return ticks; +} + +// busy wait until timestamp (in ticks) is reached +void hal_waitUntil (u4_t target_ticks) { +#ifdef DEBUG_HAL + fprintf(stdout, "%09d HAL: Wait until %09d ms\n", osticks2ms(hal_ticks()), osticks2ms(target_ticks)); +#endif + + // TODO: Deal with tick counter overflow + + u4_t current_ticks = hal_ticks(); + s4_t diff_ticks = target_ticks - current_ticks; + + if (diff_ticks > 0) { + s4_t diff_us = osticks2us(diff_ticks); + usleep(diff_us); + } +} + +void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result) +{ + if ((stop->tv_nsec - start->tv_nsec) < 0) { + result->tv_sec = stop->tv_sec - start->tv_sec - 1; + result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000; + } else { + result->tv_sec = stop->tv_sec - start->tv_sec; + result->tv_nsec = stop->tv_nsec - start->tv_nsec; + } +} + +// Used for scheduled jobs: +// If target time is reached, then 1 is returned and the scheduled job is executed. +// If 0 is returned, then control goes back into the LMIC main loop. +u1_t hal_checkTimer (u4_t target_ticks) { + + u4_t current_ticks = hal_ticks(); + s4_t diff_ticks = target_ticks - current_ticks; + s4_t diff_ms = osticks2ms(diff_ticks); + + if (diff_ticks <= 0) { // Reached target ticks + return 1; // Execute scheduled job + } else if (diff_ms < 21) { + // We have not reached the target ticks, but we also don't + // want to execute the scheduled job now. By returning 0 the code + // will continue looping in the LMIC main loop. + sleep_interval_ms = 0; + return 0; + } else { + sleep_interval_ms = diff_ms - 20; + assert(sleep_interval_ms > 0); + + // Use (diff_ms - 20) as timeout, to reduce the risk that the linux OS + // causes the timeout longer as desired. + // Let the code actively loop in the LMIC main loop until the final target time is reached. + + return 0; // Will cause a "sleep" in the LMIC main loop + } +} + +void hal_sleep () { + if (sleep_interval_ms > 0) { + int rc = gpioWaitForInterrupt(BCM_PIN_DIO, 3, sleep_interval_ms); + if(rc < 0) { + fprintf(stderr, "HAL: Cannot poll: %s\n", strerror(errno)); + hal_failed(); + } + + sleep_interval_ms = 0; + + if (rc > 0) { + if (rc & 0x01) radio_irq_handler(0); + if (rc & 0x02) radio_irq_handler(1); + if (rc & 0x04) radio_irq_handler(2); + } + } else { + // We need to check if one of the DIO ports where set to HIGH + // to signal an interrupt condition. + for (int i=0 ; i<3 ; i++) { + if (HIGH == digitalRead(WIRING_PI_PIN_DIO[i])) { + radio_irq_handler(i); + } + } + } +} +