RadioLib
Universal wireless communication library for Arduino
Loading...
Searching...
No Matches
PicoHal.h
1#ifndef PICO_HAL_H
2#define PICO_HAL_H
3
4// include RadioLib
5#include <RadioLib.h>
6
7// include the necessary Pico libraries
8#include <pico/stdlib.h>
9#include "hardware/spi.h"
10#include "hardware/timer.h"
11#include "hardware/pwm.h"
12#include "hardware/clocks.h"
13#include "pico/multicore.h"
14
15uint32_t toneLoopPin;
16unsigned int toneLoopFrequency;
17unsigned long toneLoopDuration;
18
19// pre-calculated pulse-widths for 1200 and 2200Hz
20// we do this to save calculation time (see https://github.com/khoih-prog/RP2040_PWM/issues/6)
21#define SLEEP_1200 416.666
22#define SLEEP_2200 227.272
23
24// === NOTE ===
25// The tone(...) implementation uses the second core on the RPi Pico. This is to diminish as much
26// jitter in the output tones as possible.
27
28void toneLoop(){
29 gpio_set_dir(toneLoopPin, GPIO_OUT);
30
31 uint32_t sleep_dur;
32 if (toneLoopFrequency == 1200) {
33 sleep_dur = SLEEP_1200;
34 } else if (toneLoopFrequency == 2200) {
35 sleep_dur = SLEEP_2200;
36 } else {
37 sleep_dur = 500000 / toneLoopFrequency;
38 }
39
40
41 // tone bitbang
42 while(1){
43 gpio_put(toneLoopPin, 1);
44 sleep_us(sleep_dur);
45 gpio_put(toneLoopPin, 0);
46 sleep_us(sleep_dur);
47 tight_loop_contents();
48 }
49}
50
51// create a new Raspberry Pi Pico hardware abstraction
52// layer using the Pico SDK
53// the HAL must inherit from the base RadioLibHal class
54// and implement all of its virtual methods
55class PicoHal : public RadioLibHal {
56public:
57 PicoHal(spi_inst_t *spiChannel, uint32_t misoPin, uint32_t mosiPin, uint32_t sckPin, uint32_t spiSpeed = 500 * 1000)
58 : RadioLibHal(GPIO_IN, GPIO_OUT, 0, 1, GPIO_IRQ_EDGE_RISE, GPIO_IRQ_EDGE_FALL),
59 _spiChannel(spiChannel),
60 _spiSpeed(spiSpeed),
61 _misoPin(misoPin),
62 _mosiPin(mosiPin),
63 _sckPin(sckPin){}
64
65 void init() override {
66 stdio_init_all();
67 spiBegin();
68 }
69
70 void term() override {
71 spiEnd();
72 }
73
74 // GPIO-related methods (pinMode, digitalWrite etc.) should check
75 // RADIOLIB_NC as an alias for non-connected pins
76 void pinMode(uint32_t pin, uint32_t mode) override {
77 if (pin == RADIOLIB_NC) {
78 return;
79 }
80
81 gpio_init(pin);
82 gpio_set_dir(pin, mode);
83 }
84
85 void digitalWrite(uint32_t pin, uint32_t value) override {
86 if (pin == RADIOLIB_NC) {
87 return;
88 }
89
90 gpio_put(pin, (bool)value);
91 }
92
93 uint32_t digitalRead(uint32_t pin) override {
94 if (pin == RADIOLIB_NC) {
95 return 0;
96 }
97
98 return gpio_get(pin);
99 }
100
101 void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override {
102 if (interruptNum == RADIOLIB_NC) {
103 return;
104 }
105
106 gpio_set_irq_enabled_with_callback(interruptNum, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, (gpio_irq_callback_t)interruptCb);
107 }
108
109 void detachInterrupt(uint32_t interruptNum) override {
110 if (interruptNum == RADIOLIB_NC) {
111 return;
112 }
113
114 gpio_set_irq_enabled_with_callback(interruptNum, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, NULL);
115 }
116
117 void delay(unsigned long ms) override {
118 sleep_ms(ms);
119 }
120
121 void delayMicroseconds(unsigned long us) override {
122 sleep_us(us);
123 }
124
125 unsigned long millis() override {
126 return to_ms_since_boot(get_absolute_time());
127 }
128
129 unsigned long micros() override {
130 return to_us_since_boot(get_absolute_time());
131 }
132
133 long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
134 if (pin == RADIOLIB_NC) {
135 return 0;
136 }
137
138 this->pinMode(pin, GPIO_IN);
139 uint32_t start = this->micros();
140 uint32_t curtick = this->micros();
141
142 while (this->digitalRead(pin) == state) {
143 if ((this->micros() - curtick) > timeout) {
144 return 0;
145 }
146 }
147
148 return (this->micros() - start);
149 }
150
151 void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) override {
152 // tones on the Pico are generated using bitbanging. This process is offloaded to the Pico's second core
153 multicore_reset_core1();
154 toneLoopPin = pin;
155 toneLoopFrequency = frequency;
156 toneLoopDuration = duration;
157 multicore_launch_core1(toneLoop);
158 }
159
160 void noTone(uint32_t pin) override {
161 multicore_reset_core1();
162 }
163
164 void spiBegin() {
165 spi_init(_spiChannel, _spiSpeed);
166 spi_set_format(_spiChannel, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
167
168 gpio_set_function(_sckPin, GPIO_FUNC_SPI);
169 gpio_set_function(_mosiPin, GPIO_FUNC_SPI);
170 gpio_set_function(_misoPin, GPIO_FUNC_SPI);
171 }
172
174
175 void spiTransfer(uint8_t *out, size_t len, uint8_t *in) {
176 spi_write_read_blocking(_spiChannel, out, in, len);
177 }
178
179 void yield() override {
180 tight_loop_contents();
181 }
182
184
185 void spiEnd() {
186 spi_deinit(_spiChannel);
187 }
188
189private:
190 // the HAL can contain any additional private members
191 spi_inst_t *_spiChannel;
192 uint32_t _spiSpeed;
193 uint32_t _misoPin;
194 uint32_t _mosiPin;
195 uint32_t _sckPin;
196};
197
198#endif
Definition PicoHal.h:55
void delay(unsigned long ms) override
Blocking wait function. Must be implemented by the platform-specific hardware abstraction!
Definition PicoHal.h:117
uint32_t digitalRead(uint32_t pin) override
Digital read method. Must be implemented by the platform-specific hardware abstraction!
Definition PicoHal.h:93
void term() override
Module termination method. This will be called by all radio modules when the destructor is called....
Definition PicoHal.h:70
void spiBeginTransaction()
Method to start SPI transaction.
Definition PicoHal.h:173
void detachInterrupt(uint32_t interruptNum) override
Method to detach function from an external interrupt. Must be implemented by the platform-specific ha...
Definition PicoHal.h:109
unsigned long micros() override
Get number of microseconds since start. Must be implemented by the platform-specific hardware abstrac...
Definition PicoHal.h:129
void spiBegin()
SPI initialization method.
Definition PicoHal.h:164
void delayMicroseconds(unsigned long us) override
Blocking microsecond wait function. Must be implemented by the platform-specific hardware abstraction...
Definition PicoHal.h:121
unsigned long millis() override
Get number of milliseconds since start. Must be implemented by the platform-specific hardware abstrac...
Definition PicoHal.h:125
void digitalWrite(uint32_t pin, uint32_t value) override
Digital write method. Must be implemented by the platform-specific hardware abstraction!
Definition PicoHal.h:85
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 PicoHal.h:133
void attachInterrupt(uint32_t interruptNum, void(*interruptCb)(void), uint32_t mode) override
Method to attach function to an external interrupt. Must be implemented by the platform-specific hard...
Definition PicoHal.h:101
void init() override
Module initialization method. This will be called by all radio modules at the beginning of startup....
Definition PicoHal.h:65
void tone(uint32_t pin, unsigned int frequency, unsigned long duration=0) override
Method to produce a square-wave with 50% duty cycle ("tone") of a given frequency at some pin.
Definition PicoHal.h:151
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 PicoHal.h:76
void spiEnd()
SPI termination method.
Definition PicoHal.h:185
void spiTransfer(uint8_t *out, size_t len, uint8_t *in)
Method to transfer buffer over SPI.
Definition PicoHal.h:175
void yield() override
Yield method, called from long loops in multi-threaded environment (to prevent blocking other threads...
Definition PicoHal.h:179
void spiEndTransaction()
Method to end SPI transaction.
Definition PicoHal.h:183
void noTone(uint32_t pin) override
Method to stop producing a tone.
Definition PicoHal.h:160
Hardware abstraction library base interface.
Definition Hal.h:13