Skip to content

Commit 82a1720

Browse files
Add MicroMod-WB5MMG / Sasquatch-WB5MMG variants, plus secure boot, plus secure firmware update
1 parent 5ef6cdb commit 82a1720

File tree

1 file changed

+302
-0
lines changed

1 file changed

+302
-0
lines changed

cores/arduino/wiring_analog.cpp

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
/*
2+
* Copyright (c) 2016-2022 Thomas Roell. All rights reserved.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to
6+
* deal with the Software without restriction, including without limitation the
7+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8+
* sell copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimers.
13+
* 2. Redistributions in binary form must reproduce the above copyright
14+
* notice, this list of conditions and the following disclaimers in the
15+
* documentation and/or other materials provided with the distribution.
16+
* 3. Neither the name of Thomas Roell, nor the names of its contributors
17+
* may be used to endorse or promote products derived from this Software
18+
* without specific prior written permission.
19+
*
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26+
* WITH THE SOFTWARE.
27+
*/
28+
29+
#include "Arduino.h"
30+
#include "wiring_private.h"
31+
32+
extern const unsigned int g_PWMInstances[PWM_INSTANCE_COUNT];
33+
34+
static stm32wb_tim_t __analog_pwm[PWM_INSTANCE_COUNT];
35+
static uint8_t __analog_channels[PWM_INSTANCE_COUNT];
36+
37+
static uint32_t __analog_readPeriod = 2000;
38+
static uint32_t __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_1 | STM32WB_ADC_OPTION_WIDTH_12);
39+
static uint32_t __analog_readWidth = 12;
40+
static uint32_t __analog_readResolution = 10;
41+
42+
static int __analog_writeResolution = 8;
43+
static int __analog_writeFrequency = 0;
44+
45+
void analogReference(eAnalogReference reference)
46+
{
47+
stm32wb_system_vref_configure((uint32_t)reference);
48+
}
49+
50+
void analogReadPeriod(float period)
51+
{
52+
if ((period >= 0.0f) && (period <= 40.0f)) {
53+
__analog_readPeriod = (int)(period * 1000.0f + 0.5f);
54+
}
55+
}
56+
57+
void analogReadSamples(int samples)
58+
{
59+
if (samples >= 256) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_256 | STM32WB_ADC_OPTION_WIDTH_16); __analog_readWidth = 16; }
60+
else if (samples >= 128) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_128 | STM32WB_ADC_OPTION_WIDTH_16); __analog_readWidth = 16; }
61+
else if (samples >= 64) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_64 | STM32WB_ADC_OPTION_WIDTH_16); __analog_readWidth = 16; }
62+
else if (samples >= 32) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_32 | STM32WB_ADC_OPTION_WIDTH_16); __analog_readWidth = 16; }
63+
else if (samples >= 16) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_16 | STM32WB_ADC_OPTION_WIDTH_16); __analog_readWidth = 16; }
64+
else if (samples >= 8) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_8 | STM32WB_ADC_OPTION_WIDTH_15); __analog_readWidth = 15; }
65+
else if (samples >= 4) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_4 | STM32WB_ADC_OPTION_WIDTH_14); __analog_readWidth = 14; }
66+
else if (samples >= 2) { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_2 | STM32WB_ADC_OPTION_WIDTH_13); __analog_readWidth = 13; }
67+
else { __analog_readOptions = (STM32WB_ADC_OPTION_RATIO_1 | STM32WB_ADC_OPTION_WIDTH_12); __analog_readWidth = 12; }
68+
}
69+
70+
void analogReadResolution(int resolution)
71+
{
72+
if ((resolution >= 1) && (resolution <= 16)) {
73+
__analog_readResolution = resolution;
74+
}
75+
}
76+
77+
uint32_t __attribute__((optimize("O3"))) analogRead(uint32_t pin)
78+
{
79+
uint8_t channels[1];
80+
uint16_t data[1];
81+
82+
if ((pin >= PINS_COUNT) || (g_APinDescription[pin].adc_channel == ADC_CHANNEL_NONE)) {
83+
return 0;
84+
}
85+
86+
if (g_APinDescription[pin].pwm_instance != PWM_INSTANCE_NONE) {
87+
__analogWriteDisable(pin);
88+
}
89+
90+
channels[0] = STM32WB_ADC_CHANNEL_1 + g_APinDescription[pin].adc_channel;
91+
92+
if (!stm32wb_adc_convert(&channels[0], &data[0], 1,__analog_readPeriod, (__analog_readOptions | STM32WB_ADC_OPTION_STOP))) {
93+
return 0;
94+
}
95+
96+
if (__analog_readResolution != __analog_readWidth) {
97+
return ((uint32_t)data[0] << __analog_readResolution) >> __analog_readWidth;
98+
}
99+
100+
return data[0];
101+
}
102+
103+
uint32_t __attribute__((optimize("O3"))) analogRead(uint32_t pin, bool stop)
104+
{
105+
uint8_t channels[1];
106+
uint16_t data[1];
107+
108+
if ((pin >= PINS_COUNT) || (g_APinDescription[pin].adc_channel == ADC_CHANNEL_NONE)) {
109+
return 0;
110+
}
111+
112+
if (g_APinDescription[pin].pwm_instance != PWM_INSTANCE_NONE) {
113+
__analogWriteDisable(pin);
114+
}
115+
116+
stm32wb_gpio_pin_configure(g_APinDescription[pin].pin, (STM32WB_GPIO_PUPD_NONE | STM32WB_GPIO_MODE_ANALOG));
117+
118+
channels[0] = STM32WB_ADC_CHANNEL_1 + g_APinDescription[pin].adc_channel;
119+
120+
if (!stm32wb_adc_convert(&channels[0], &data[0], 1,__analog_readPeriod, (__analog_readOptions | (stop ? STM32WB_ADC_OPTION_STOP : 0)))) {
121+
return 0;
122+
}
123+
124+
if (__analog_readResolution != __analog_readWidth) {
125+
return ((uint32_t)data[0] << __analog_readResolution) >> __analog_readWidth;
126+
}
127+
128+
return data[0];
129+
}
130+
131+
bool __attribute__((optimize("O3"))) analogRead(const uint8_t pins[], uint16_t data[], uint32_t count, bool stop)
132+
{
133+
uint32_t index, pin;
134+
uint8_t channels[8];
135+
136+
if (!count || (count > 8)) {
137+
return false;
138+
}
139+
140+
for (index = 0; index < count; index++) {
141+
pin = pins[index];
142+
143+
if ((pin >= PINS_COUNT) || (g_APinDescription[pin].adc_channel == ADC_CHANNEL_NONE)) {
144+
return false;
145+
}
146+
147+
if (g_APinDescription[pin].pwm_instance != PWM_INSTANCE_NONE) {
148+
__analogWriteDisable(pin);
149+
}
150+
151+
stm32wb_gpio_pin_configure(g_APinDescription[pin].pin, (STM32WB_GPIO_PUPD_NONE | STM32WB_GPIO_MODE_ANALOG));
152+
153+
channels[index] = STM32WB_ADC_CHANNEL_1 + g_APinDescription[pin].adc_channel;
154+
}
155+
156+
if (!stm32wb_adc_convert(&channels[0], &data[0], count, __analog_readPeriod, (__analog_readOptions | (stop ? STM32WB_ADC_OPTION_STOP : 0)))) {
157+
return false;
158+
}
159+
160+
if (__analog_readResolution != __analog_readWidth) {
161+
data[index] = ((uint32_t)data[index] << __analog_readResolution) >> __analog_readWidth;
162+
}
163+
164+
return true;
165+
}
166+
167+
void analogWriteResolution( int resolution )
168+
{
169+
if ((resolution >= 1) && (resolution <= 12)) {
170+
__analog_writeResolution = resolution;
171+
}
172+
}
173+
174+
void analogWriteFrequency( unsigned long frequency )
175+
{
176+
uint32_t instance, clock, carrier, modulus, prescale;
177+
178+
__analog_writeFrequency = frequency;
179+
180+
for (instance = 0; instance < PWM_INSTANCE_COUNT; instance++)
181+
{
182+
if (__analog_pwm[instance].state == STM32WB_TIM_STATE_ACTIVE)
183+
{
184+
clock = stm32wb_tim_clock(&__analog_pwm[instance]);
185+
186+
modulus = 4095;
187+
188+
if (__analog_writeFrequency)
189+
{
190+
carrier = __analog_writeFrequency * modulus;
191+
}
192+
else
193+
{
194+
carrier = 2000000;
195+
}
196+
197+
if (carrier > clock)
198+
{
199+
carrier = (clock / modulus) * modulus;
200+
}
201+
202+
prescale = (clock + (carrier - 1)) / carrier;
203+
204+
stm32wb_tim_stop(&__analog_pwm[instance]);
205+
stm32wb_tim_start(&__analog_pwm[instance], prescale, modulus -1);
206+
}
207+
}
208+
}
209+
210+
void analogWrite(uint32_t pin, uint32_t output)
211+
{
212+
uint32_t instance, clock, carrier, modulus, prescale;
213+
GPIO_TypeDef *GPIO;
214+
uint32_t bit;
215+
216+
// Handle the case the pin isn't usable as PIO
217+
if ((pin >= PINS_COUNT) || (g_APinDescription[pin].GPIO == NULL)) {
218+
return;
219+
}
220+
221+
if (__analog_writeResolution != 12) {
222+
output = (output * 4095) / ((1 << __analog_writeResolution) -1);
223+
}
224+
225+
if (output > 4095) {
226+
output = 4095;
227+
}
228+
229+
if (g_APinDescription[pin].pwm_instance != PWM_INSTANCE_NONE)
230+
{
231+
instance = g_APinDescription[pin].pwm_instance;
232+
233+
if (__analog_channels[instance] & (1u << g_APinDescription[pin].pwm_channel)) {
234+
stm32wb_tim_compare(&__analog_pwm[instance], g_APinDescription[pin].pwm_channel, output);
235+
} else {
236+
__analog_channels[instance] |= (1u << g_APinDescription[pin].pwm_channel);
237+
238+
if (__analog_pwm[instance].state == STM32WB_TIM_STATE_NONE) {
239+
stm32wb_tim_create(&__analog_pwm[instance], g_PWMInstances[instance], STM32WB_PWM_IRQ_PRIORITY);
240+
}
241+
242+
if (__analog_pwm[instance].state == STM32WB_TIM_STATE_INIT) {
243+
stm32wb_tim_enable(&__analog_pwm[instance], 0, NULL, NULL);
244+
245+
clock = stm32wb_tim_clock(&__analog_pwm[instance]);
246+
247+
modulus = 4095;
248+
249+
if (__analog_writeFrequency) {
250+
carrier = __analog_writeFrequency * modulus;
251+
} else {
252+
carrier = 2000000;
253+
}
254+
255+
if (carrier > clock) {
256+
carrier = (clock / modulus) * modulus;
257+
}
258+
259+
prescale = (clock + (carrier - 1)) / carrier;
260+
261+
stm32wb_tim_start(&__analog_pwm[instance], prescale, modulus -1);
262+
}
263+
264+
stm32wb_gpio_pin_configure(g_APinDescription[pin].pin, (STM32WB_GPIO_PUPD_NONE | STM32WB_GPIO_OSPEED_HIGH | STM32WB_GPIO_OTYPE_PUSHPULL | STM32WB_GPIO_MODE_ALTERNATE));
265+
266+
stm32wb_tim_channel(&__analog_pwm[instance], g_APinDescription[pin].pwm_channel, output, STM32WB_TIM_CONTROL_PWM);
267+
}
268+
269+
return;
270+
}
271+
272+
stm32wb_gpio_pin_configure(g_APinDescription[pin].pin, (STM32WB_GPIO_PUPD_NONE | STM32WB_GPIO_OSPEED_MEDIUM | STM32WB_GPIO_OTYPE_PUSHPULL | STM32WB_GPIO_MODE_OUTPUT));
273+
274+
GPIO = (GPIO_TypeDef*)g_APinDescription[pin].GPIO;
275+
bit = g_APinDescription[pin].bit;
276+
277+
if (output >= 2048) {
278+
GPIO->BSRR = bit;
279+
} else {
280+
GPIO->BRR = bit;
281+
}
282+
}
283+
284+
void __analogWriteDisable(uint32_t pin)
285+
{
286+
uint32_t instance;
287+
288+
instance = g_APinDescription[pin].pwm_instance;
289+
290+
if (__analog_channels[instance] & (1u << g_APinDescription[pin].pwm_channel)) {
291+
stm32wb_tim_channel(&__analog_pwm[instance], g_APinDescription[pin].pwm_channel, 0, STM32WB_TIM_CONTROL_DISABLE);
292+
293+
stm32wb_gpio_pin_configure(g_APinDescription[pin].pin, (STM32WB_GPIO_PUPD_NONE | STM32WB_GPIO_MODE_ANALOG));
294+
295+
__analog_channels[instance] &= ~(1u << g_APinDescription[pin].pwm_channel);
296+
297+
if (!__analog_channels[instance]) {
298+
stm32wb_tim_stop(&__analog_pwm[instance]);
299+
stm32wb_tim_disable(&__analog_pwm[instance]);
300+
}
301+
}
302+
}

0 commit comments

Comments
 (0)