RadioLib
Universal wireless communication library for Arduino
libtockHal.h
1 /*
2  RadioLib Non-Arduino Tock Library helper functions
3 
4  Licensed under the MIT License
5 
6  Copyright (c) 2023 Alistair Francis <alistair@alistair23.me>
7 
8  Permission is hereby granted, free of charge, to any person obtaining a copy
9  of this software and associated documentation files (the "Software"), to deal
10  in the Software without restriction, including without limitation the rights
11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  copies of the Software, and to permit persons to whom the Software is
13  furnished to do so, subject to the following conditions:
14 
15  The above copyright notice and this permission notice shall be included in all
16  copies or substantial portions of the Software.
17 
18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  SOFTWARE.
25 */
26 
27 #ifndef TOCK_HAL_H
28 #define TOCK_HAL_H
29 
30 // include RadioLib
31 #include <RadioLib.h>
32 
33 // include all the dependencies
34 #include "libtock/net/lora_phy.h"
35 #include "libtock/net/syscalls/lora_phy_syscalls.h"
36 #include "libtock-sync/net/lora_phy.h"
37 #include "libtock/peripherals/gpio.h"
38 #include "libtock-sync/services/alarm.h"
39 #include "libtock/kernel/read_only_state.h"
40 
41 #define RADIO_BUSY 1
42 #define RADIO_DIO_1 2
43 #define RADIO_DIO_3 3
44 #define RADIO_RESET 4
45 // Skip the chips select as Tock handles this for us
46 #define RADIO_NSS RADIOLIB_NC
47 
48 // define Arduino-style macros
49 #define PIN_LOW (0x0)
50 #define PIN_HIGH (0x1)
51 #define PIN_INPUT (0x01)
52 #define PIN_OUTPUT (0x03)
53 #define PIN_RISING (0x01)
54 #define PIN_FALLING (0x02)
55 
56 typedef void (*gpioIrqFn)(void);
57 
58 gpioIrqFn gpio_funcs[4] = { NULL, NULL, NULL, NULL};
59 uint32_t frequency = 0;
60 
61 /*
62  * Get the the timer frequency in Hz.
63  */
64 int alarm_internal_frequency(uint32_t* frequency) {
65  syscall_return_t rval = command(0x0, 1, 0, 0);
66  return tock_command_return_u32_to_returncode(rval, frequency);
67 }
68 
69 int alarm_internal_read(uint32_t* time) {
70  syscall_return_t rval = command(0x0, 2, 0, 0);
71  return tock_command_return_u32_to_returncode(rval, time);
72 }
73 
74 static void lora_phy_gpio_Callback (int gpioPin,
75  __attribute__ ((unused)) int arg2,
76  __attribute__ ((unused)) int arg3,
77  void* userdata)
78 {
79  gpioIrqFn fn = gpio_funcs[gpioPin - 1];
80 
81  if (fn != NULL ) {
82  fn();
83  }
84 }
85 
86 class TockHal : public RadioLibHal {
87  public:
88  // default constructor - initializes the base HAL and any needed private members
89  TockHal()
90  : RadioLibHal(PIN_INPUT, PIN_OUTPUT, PIN_LOW, PIN_HIGH, PIN_RISING, PIN_FALLING) {
91  }
92 
93  void init() override {
94  }
95 
96  void term() override {
97  }
98 
99  // GPIO-related methods (pinMode, digitalWrite etc.) should check
100  // RADIOLIB_NC as an alias for non-connected pins
101  void pinMode(uint32_t pin, uint32_t mode) override {
102  if(pin == RADIOLIB_NC) {
103  return;
104  }
105 
106  if (mode == PIN_OUTPUT) {
107  libtock_lora_phy_gpio_enable_output(pin);
108  } else if (mode == PIN_INPUT) {
109  libtock_lora_phy_gpio_enable_input(pin, libtock_pull_down);
110  }
111  }
112 
113  void digitalWrite(uint32_t pin, uint32_t value) override {
114  if(pin == RADIOLIB_NC) {
115  return;
116  }
117 
118  if (value) {
119  libtock_lora_phy_gpio_set(pin);
120  } else {
121  libtock_lora_phy_gpio_clear(pin);
122  }
123  }
124 
125  uint32_t digitalRead(uint32_t pin) override {
126  int value;
127 
128  if(pin == RADIOLIB_NC) {
129  return 0;
130  }
131 
132  libtock_lora_phy_gpio_read(pin, &value);
133 
134  return value;
135  }
136 
137  void attachInterrupt(uint32_t interruptNum, gpioIrqFn interruptCb, uint32_t mode) override {
138  if(interruptNum == RADIOLIB_NC) {
139  return;
140  }
141 
142  gpio_funcs[interruptNum - 1] = interruptCb;
143  libtock_lora_phy_gpio_command_interrupt_callback(lora_phy_gpio_Callback, NULL);
144 
145  // set GPIO as input and enable interrupts on it
146  libtock_lora_phy_gpio_enable_input(interruptNum, libtock_pull_down);
147  libtock_lora_phy_gpio_enable_interrupt(interruptNum, libtock_change);
148  }
149 
150  void detachInterrupt(uint32_t interruptNum) override {
151  if(interruptNum == RADIOLIB_NC) {
152  return;
153  }
154 
155  gpio_funcs[interruptNum - 1] = NULL;
156  libtock_lora_phy_gpio_disable_interrupt(interruptNum);
157  libtock_lora_phy_gpio_enable_input(interruptNum, libtock_pull_down);
158  }
159 
160  void delay(unsigned long ms) override {
161 #if !defined(RADIOLIB_CLOCK_DRIFT_MS)
162  libtocksync_alarm_delay_ms(ms);
163 #else
164  libtocksync_alarm_delay_ms(ms * 1000 / (1000 + RADIOLIB_CLOCK_DRIFT_MS));
165 #endif
166  }
167 
168  void delayMicroseconds(unsigned long us) override {
169 #if !defined(RADIOLIB_CLOCK_DRIFT_MS)
170  libtocksync_alarm_delay_ms(us / 1000);
171 #else
172  libtocksync_alarm_delay_ms((us * 1000 / (1000 + RADIOLIB_CLOCK_DRIFT_MS)) / 1000);
173 #endif
174  }
175 
176  unsigned long millis() override {
177  uint32_t now;
178  unsigned long ms;
179 
180  if (frequency == 0) {
181  alarm_internal_frequency(&frequency);
182  }
183 
184  alarm_internal_read(&now);
185 
186  ms = now / (frequency / 1000);
187 
188 #if !defined(RADIOLIB_CLOCK_DRIFT_MS)
189  return ms;
190 #else
191  return ms * 1000 / (1000 + RADIOLIB_CLOCK_DRIFT_MS);
192 #endif
193  }
194 
195  unsigned long micros() override {
196  return millis() / 1000;
197  }
198 
199  long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
200  return 0;
201  }
202 
203  void spiBegin() {
204  }
205 
207  }
208 
209  void spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
210  libtocksync_lora_phy_read_write(out, in, len);
211  }
212 
214  }
215 
216  void spiEnd() {
217  }
218 
219  void yield() {
220  ::yield_no_wait();
221  }
222 
223  private:
224 };
225 
226 #endif
Hardware abstraction library base interface.
Definition: Hal.h:13
RadioLibHal(const uint32_t input, const uint32_t output, const uint32_t low, const uint32_t high, const uint32_t rising, const uint32_t falling)
Default constructor.
Definition: Hal.cpp:3
Definition: libtockHal.h:86
void spiBegin()
SPI initialization method.
Definition: libtockHal.h:203
void spiEnd()
SPI termination method.
Definition: libtockHal.h:216
unsigned long millis() override
Get number of milliseconds since start. Must be implemented by the platform-specific hardware abstrac...
Definition: libtockHal.h:176
uint32_t digitalRead(uint32_t pin) override
Digital read method. Must be implemented by the platform-specific hardware abstraction!
Definition: libtockHal.h:125
unsigned long micros() override
Get number of microseconds since start. Must be implemented by the platform-specific hardware abstrac...
Definition: libtockHal.h:195
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override
Measure the length of incoming digital pulse in microseconds. Must be implemented by the platform-spe...
Definition: libtockHal.h:199
void term() override
Module termination method. This will be called by all radio modules when the destructor is called....
Definition: libtockHal.h:96
void spiTransfer(uint8_t *out, size_t len, uint8_t *in)
Method to transfer buffer over SPI.
Definition: libtockHal.h:209
void attachInterrupt(uint32_t interruptNum, gpioIrqFn interruptCb, uint32_t mode) override
Method to attach function to an external interrupt. Must be implemented by the platform-specific hard...
Definition: libtockHal.h:137
void yield()
Yield method, called from long loops in multi-threaded environment (to prevent blocking other threads...
Definition: libtockHal.h:219
void spiBeginTransaction()
Method to start SPI transaction.
Definition: libtockHal.h:206
void delay(unsigned long ms) override
Blocking wait function. Must be implemented by the platform-specific hardware abstraction!
Definition: libtockHal.h:160
void digitalWrite(uint32_t pin, uint32_t value) override
Digital write method. Must be implemented by the platform-specific hardware abstraction!
Definition: libtockHal.h:113
void init() override
Module initialization method. This will be called by all radio modules at the beginning of startup....
Definition: libtockHal.h:93
void detachInterrupt(uint32_t interruptNum) override
Method to detach function from an external interrupt. Must be implemented by the platform-specific ha...
Definition: libtockHal.h:150
void delayMicroseconds(unsigned long us) override
Blocking microsecond wait function. Must be implemented by the platform-specific hardware abstraction...
Definition: libtockHal.h:168
void pinMode(uint32_t pin, uint32_t mode) override
GPIO pin mode (input/output/...) configuration method. Must be implemented by the platform-specific h...
Definition: libtockHal.h:101
void spiEndTransaction()
Method to end SPI transaction.
Definition: libtockHal.h:213