%DASHBOARD{ section="dashboard_start" }% %DASHBOARD{ section="banner" image="%PUBURLPATH%/Cosmac/ForthSTM32WB/nucleo-header.jpg" title="Board Support Package for the Flipper Zero (STM32WB55 MCU)" titlestyle="color:#F00000;" }% %DASHBOARD{ section="box_start" title="Intro" width="485" height="200"}% TBD %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" title="Contents" width="460" height="200"}% %TOC% %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="600" }% ---+ Board Support Words Defaults: Digital port pins D0 to D4 are inputs with pull-up resistors. <pre> rgbled! ( rgb -- ) sets the RGB led ($ff0000 red, $00ff00 green, $0000ff blue) switch1? ( -- ? ) get switch1 (BACK), closed=TRUE switch2? ( -- ? ) get switch2 (OK), closed=TRUE switch3? ( -- ? ) get switch3 (RIGHT), closed=TRUE switch4? ( -- ? ) get switch4 (LEFT), closed=TRUE switch5? ( -- ? ) get switch5 (UP), closed=TRUE switch6? ( -- ? ) get switch6 (DOWN), closed=TRUE dport! ( n -- ) set the digital output port (D0=bit0 .. D15=bit15). dport@ ( -- n ) get the digital input/output port (D0=bit0 .. D15=bit15). dpin! ( n a -- ) set the digital output port pin (D0=0 .. D15=15) dpin@ ( a -- n ) get the digital input/output port pin dmod ( u a -- ) set the pin mode: 0 in, 1 in pull-up, 2 in pull-down, 3 out push pull, 4 out open drain, 5 out push pull PWM, 6 input capture, 7 output compare, 8 I2C EXTImod ( u a -- ) set for pin a (D2, D4, D7, D10) the EXTI mode u: 0 rising, 1 falling, 2 both edges, 3 none EXTIwait ( u a -- ) wait for EXTI interrupt on pin a (D2, D4, D7, D10), timeout u in [ms] pwmpin! ( u a -- ) set the digital output port pin a (D4=4, D11=11) to a PWM value u (0..1000). Default frequency is 1 kHz, TIMER1 pwmprescale ( u -- ) Set the PWM prescale for TIMER1. 32 kHz / prescale, default 32 -> PWM frequency 1 kHz ICOCprescale ( u -- ) set the input capture / output compare prescale for TIMER2. default 32 -> 32 MHz / 32 = 1 MHz, timer resolution 1 us ICOCperiod! ( u -- ) set the input capture / output compare (TIMER2) period. default $FFFFFFFF (4'294'967'295). When the up counter reaches the period, the counter is set to 0. For prescale 32 the maximum time is about 1 h 11 m ICOCcount! ( -- u ) set the input capture / output compare counter for TIMER2 ICOCcount@ ( u -- ) get the input capture / output compare counter for TIMER2 ICOCstart ( -- ) start the ICOC period ICOCstop ( -- ) stop the ICOC period OCmod ( u a -- ) set for pin a (D0, D1, D5) the Output Compare mode u: 0 frozen, 1 active level on match, 2 inactive level on match, 3 toggle on match, 4 forced active, 5 forced inactive OCstart ( u a -- ) start the output compare mode for pin a with pulse u OCstop ( a -- ) stop output compare for pin a ICstart ( u -- ) start input capture u: 0 rising edge, 1 falling edge, 2 both edges ICstop ( -- ) stop input capture waitperiod ( -- ) wait for the end of the TIMER2 period OCwait ( a -- ) wait for the end of output capture on pin a ICwait ( u -- u ) wait for the end of input capture with timeout u, returns counter u apin@ ( a -- u ) get the analog input port pin (A0 .. A2). Returns a 12 bit value (0..4095) vref@ ( -- u ) get the Vref voltage in mV (rather the VDDA) vbat@ ( -- u ) get the Vbat voltage in mV CPUtemp@ ( -- u ) get CPU temperature in degree Celsius I2Cput ( a # u -- ) put a message with length u (count in bytes) from buffer at a to the I2C slave device u I2Cget ( a # u -- ) get a message with length u from I2C slave device to buffer at a I2Cputget ( a #1 #2 u -- ) put a message with length #1 from buffer at a to the I2C slave device u and get a message with length #2 from device to buffer at a SPIget ( a # -- ) get a message with length # from SPI slave device to buffer at a SPIput ( a # -- ) put a message with length # from buffer at a to the SPI slave device SPIputget ( a #1 #2 -- ) put a message with length #1 from buffer at a to the SPI slave device and get a message with length #2 from device to buffer at a SPImutex ( -- a ) get the SPI mutex address </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="520" }% ---+ Using the Digital Port Pins (Input and Output) This example is very similar to the Cosmac.McForth#Knight_Rider program. =dport!= and =dport@= set and get all 16 digital pins (D0 to D15) at once. You have to press the _SW1_ push button til D0 is set to cancel the operation. <pre> 3 0 dmod \ set D0 to Output 3 1 dmod \ set D1 to Output 3 2 dmod \ set D2 to Output 3 3 dmod \ set D3 to Output 3 4 dmod \ set D4 to Output 3 5 dmod \ set D5 to Output 3 6 dmod \ set D6 to Output 3 7 dmod \ set D7 to Output </pre> <table> <tr> <td> <pre> : left ( -- ) 7 0 do dport@ shl dport! 100 osDelay drop loop ; </pre> </td> <td> <pre> : right ( -- ) 7 0 do dport@ shr dport! 100 osDelay drop loop ; </pre> </td> <td> <pre> : knightrider ( -- ) 1 dport! begin left right switch1? \ or key? until 0 dport! ; </pre> </td> </tr> </table> Single port pin variant (no side effects on port pins D8 to D15): <table> <tr> <td> <pre> : left ( -- ) 7 0 do 1 i dpin! 100 osDelay drop 0 i dpin! loop ; </pre> </td> <td> <pre> : right ( -- ) 8 1 do 1 8 i - dpin! 100 osDelay drop 0 8 i - dpin! loop ; </pre> </td> <td> <pre> : knigthrider ( -- ) begin left right switch1? until 0 0 dpin! ; </pre> </td> </tr> </table> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="650" }% ---+ Using the ADC (Analog Input Pins) =apin@ ( a -- u )= returns the ADC value (12 bit, 0 .. 4095) from one of the analog pins A0 to A5 (0 .. 5). Here I use the A0 to control the delay. <table> <tr> <td> <pre> : left ( -- ) 7 0 do 1 i dpin! 0 apin@ 10 / osDelay drop \ delay depends on A0 0 i dpin! loop ; </pre> </td> <td> <pre> : right ( -- ) 8 1 do 1 8 i - dpin! 0 apin@ 10 / osDelay drop \ delay depends on A0 0 8 i - dpin! loop ; </pre> </td> </tr> </table> To get an idea how fast the ADC, RTOS, and the Forth program are. The =left= or =right= word takes about 125 us, the =knightrider= loop about 50 us (no osDelay). Pretty fast for my opinion. CH1 yellow: D0 pin<br> CH2 blue: D1 pin<br> <img src="%ATTACHURLPATH%/TEK0012.png" alt="TEK0012.png" width="320" height="240" /> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="400" }% ---+ Using the PWM (Analog Output Pins) Only three port pins are supported so far. The 16 bit TIMER1 is used for the timebase, time resolution is 1 us (32 MHz !SysClk divided by 32). The PWM scale is from 0 (0 % duty cycle) to 1000 (100 % duty cycle), this results in a PWM frequency of 1 kHz. If you need higher PWM frequencies, decrease the divider and/or the scale. PWM port pins: D6 (!TIM1CH1), D9 (!TIM1CH2), D3 (!TIM1CH3) Simple test program to set brightness of a LED on pin D3 with a potentiometer on A0. Default PWM frequency is 1 kHz (prescaler set to 32). You can set the prescale with the word =pwmprescale= from 32 kHz (value 1) down to 0.5 Hz (64000). <pre> 5 3 dmod \ set D3 to PWM : pwm ( -- ) begin 0 apin@ 4 / 3 pwmpin! 10 osDelay drop switch1? until ; </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="500" }% ---+ Using Input Capture and Output Compare ---++ Time Base Default timer resolution is 1 us. The 32 bit TIMER2 is used as time base for Input Capture / Output Compare. For a 5 s period 5'000'000 cycles are needed. All channels (input capture / output compare) use the same time base. <pre> : period ( -- ) 5000000 ICOCperiod! \ 5 s period ICOCstart begin waitperiod cr .time key? until key drop ; </pre> ---++ Output Compare <pre> : oc-toggle ( -- ) 5000000 ICOCperiod! \ 5 s period ICOCstart 3 0 OCmod 1000000 0 OCstart \ toggle D0 after 1 s 3 1 OCmod 2000000 1 OCstart \ toggle D1 after 2 s 3 5 OCmod 3000000 5 OCstart \ toggle D5 after 3 s begin waitperiod cr .time key? until key drop ; </pre> When you abort (hit any key) the program, the timer still runs and controls the port pins. To stop the port pins: <pre> 0 OCstop 1 OCstop 5 OCstop </pre> Or change the prescale to make it faster or slower: <pre> 1 ICOCprescale </pre> ---++ Input Capture This sample program measures the time between the edges on port A2. if no event occurs within 2 seconds, "timeout" is issued. Hit any key to abort program. <pre> : ic-test ( -- ) 6 2 dmod \ input capture on A2 ICOCstart 2 ICstart \ both edges ICOCcount@ ( -- count ) begin 2000 \ 2 s timeout ICwait ( -- old-capture capture ) cr dup 0= if ." timeout" drop else dup rot ( -- capture capture old-capture ) - 1000 / . ." ms" then key? until key drop drop ICstop ; </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="400" }% ---+ Using EXTI line <pre> : exti-test ( -- ) 2 2 EXTImod \ both edges on D2 begin 2000 2 EXTIwait \ wait for edge on D2 with 2 s timeout cr 0= if 2 dpin@ if ." rising edge" else ." falling edge" then else ." timeout" then key? until key drop ; </pre> %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="box_start" width="992" height="800" }% ---+ Pinouts ---++ GPIO Ports * [[https://docs.flipper.net/gpio-and-modules][GPIO & modules]] %IMAGE{"%ATTACHURLPATH%/flipper-gpio.jpg" type="thumb" caption="Arduino left"}% | *Pin * | *Label* | *STM32WB55 pin* | *Arduino* | *Alternate Functions* | | 1 | +5V | | | | | 2 | A7 | PA7 | D11 | SPI1_MOSI, TIM1_CH2 (PWM) | | 3 | A6 | PA6 | D12 | SPI1_MISO | | 4 | A4 | PA4 | D10 | SPI1_CS | | 5 | B3 | PB3 | D13 | SPI1_CLK, SWO | | 6 | B2 | PB2 | D9 | TIM2_CH2 (output capture) | | 7 | C3 | PC3 | A2(D18) | | | 8 | GND | | | | | 9 | 3V3 | | | | | 10 | SWC | PA14 | D3 | SWCLK | | 11 | GND | | | | | 12 | SIO | PA13 | D2 | SWDIO | | 13 | TX | PB6 | D1 | | | 14 | RX | PB7 | D0 | | | 15 | C1 | PC1 | A1 (D17) | I2C3_SDA | | 16 | C0 | PC0 | A0 (D16) | I2C3_SCL | | 17 | 1W | PB14 | D4 | TIM1_CH2 (PWM) | | 18 | GND | | | | ---++ Push Buttons | *Signal name* | *STM32WB55 pin* | *Comment* | | SWITCH1 BACK | PC13 | WKUP2 RESET | | SWITCH2 OK | PH3 | | | SWITCH3 RIGHT | PB12 | | | SWITCH4 LEFT | PB11 | RESET | | SWITCH5 UP | PB10 | | | SWITCH6 DOWN | PC6 | | ---++ RGB LED | *Signal name* | *STM32W5MMG pin* | *Comment* | | D11 | PA7 | SPI1_MOSI | | RGB_SELECT | PH1 | RGB CS | PWM Driver Chip: [[https://www.ti.com/lit/ds/symlink/tlc59731.pdf][TLC59731]] SPI is used for the timing. 4 SPI bits are one pulse position bit. fCLK(SDI) = 20 kHz to 600 kHz, the max. frequency for the SPI is therefore 2.4 MHz, I choosed 2 MHz. It takes about 30 us to set one RGB-LED. ---++ UART VCP ST-LINK | *Signal name* | *STM32WB55 pin* | *Comment* | | UART_TX | PB6 | USART1_TX | | UART_RX | PB7 | USART1_RX | ---++ SPI OLED Display | *Signal name* | *STM32W5MMG pin* | *Comment* | | D13 | PA1 | SPI1_SCK | | D12 | PB4 | SPI1_MISO | | D11 | PA7 | SPI1_MOSI | | OLED_CS | PH0 | SPI1_NSS | | OLED_RST | PC8 | Reset OLED | | OLED_DC | PC9 | Data/Control | * https://github.com/STMicroelectronics/stm32-ssd1315/blob/main/ssd1315.c * https://files.seeedstudio.com/wiki/Grove-OLED-Display-0.96-SSD1315-/res/OEL%20Display%20Module.pdf ---++ microSD Adapter (SD Drive) | *SD pin* | *microSD pin* | *Name* | *Description* | *Ports* | | 1 | 2 | nCS | Card Select [CS] | PB2 | | 2 | 3 | DI | Serial Data In [MOSI] | PA7 | | 3 | - | VSS | Ground | GND | | 4 | 4 | VDD | Power 3.3 V | 3V3 | | 5 | 5 | CLK | Serial Clock [SCLK] | PA5 | | 6 | 6 | VSS | Ground | GND | | 7 | 7 | DO | Serial Data Out [MISO] | PA6 | | 8 | 8 | NC | Unused | | | 9 | 1 | NC | Unused | | %DASHBOARD{ section="box_end" }% %DASHBOARD{ section="dashboard_end" }% -- %USERSIG{PeterSchmid - 2023-10-28}% <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work by <a xmlns:cc="http://creativecommons.org/ns#" href="http://spyr.ch" property="cc:attributionName" rel="cc:attributionURL">Peter Schmid</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
Attachments
Attachments
Topic attachments
I
Attachment
History
Action
Size
Date
Who
Comment
jpg
flipper-gpio.jpg
r1
manage
745.7 K
2023-10-28 - 20:21
PeterSchmid
This topic: MecrispCube
>
WebHome
>
MecrispCubeFlipper
>
BoardSupportPackageFlipper
Topic revision: r2 - 2023-10-29 - PeterSchmid
Copyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki?
Send feedback