watch library: implement SPI
This commit is contained in:
		
							parent
							
								
									1b1bba2de0
								
							
						
					
					
						commit
						a11275d84c
					
				| @ -3,40 +3,10 @@ | |||||||
| #include <peripheral_clk_config.h> | #include <peripheral_clk_config.h> | ||||||
| #include "watch.h" | #include "watch.h" | ||||||
| 
 | 
 | ||||||
| // NOTE: as of this writing (10/25/21) there is no SPI controller functionality in the watch library.
 | // this is a very basic app to confirm that SPI is working, tested with board OSO-MISC-21-017 and a GD25Q16C Flash chip.
 | ||||||
| // this is a very basic app to confirm that SPI is working, tested with board OSO-MISC-21-001 and a GD25Q16C Flash chip.
 |  | ||||||
| // The updated SPI Flash sensor board design is OSO-MISC-21-017 (it's easier to build, 0603 passives instead of 0402's).
 |  | ||||||
| 
 |  | ||||||
| struct io_descriptor *io; |  | ||||||
| struct spi_m_sync_descriptor SPI_0; |  | ||||||
| 
 | 
 | ||||||
| void app_init(void) { | void app_init(void) { | ||||||
|     // SPI_0_CLOCK_init
 |     watch_enable_spi(); | ||||||
|     hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_CORE, CONF_GCLK_SERCOM3_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); |  | ||||||
|     hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_SLOW, CONF_GCLK_SERCOM3_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); |  | ||||||
|     hri_mclk_set_APBCMASK_SERCOM3_bit(MCLK); |  | ||||||
| 
 |  | ||||||
|     spi_m_sync_init(&SPI_0, SERCOM3); |  | ||||||
| 
 |  | ||||||
|     // SPI_0_PORT_init
 |  | ||||||
|     gpio_set_pin_level(A3, true); |  | ||||||
|     gpio_set_pin_direction(A3, GPIO_DIRECTION_OUT); |  | ||||||
|     gpio_set_pin_function(A3, GPIO_PIN_FUNCTION_OFF); |  | ||||||
| 
 |  | ||||||
|     gpio_set_pin_level(A2, false); |  | ||||||
|     gpio_set_pin_direction(A2, GPIO_DIRECTION_OUT); |  | ||||||
|     gpio_set_pin_function(A2, PINMUX_PB02C_SERCOM3_PAD0); |  | ||||||
| 
 |  | ||||||
|     gpio_set_pin_direction(A4, GPIO_DIRECTION_IN); |  | ||||||
|     gpio_set_pin_pull_mode(A4, GPIO_PULL_OFF); |  | ||||||
|     gpio_set_pin_function(A4, PINMUX_PB00C_SERCOM3_PAD2); |  | ||||||
| 
 |  | ||||||
|     gpio_set_pin_level(A1, false); |  | ||||||
|     gpio_set_pin_direction(A1, GPIO_DIRECTION_OUT); |  | ||||||
|     gpio_set_pin_function(A1, PINMUX_PB01C_SERCOM3_PAD3); |  | ||||||
| 
 |  | ||||||
|     spi_m_sync_get_io_descriptor(&SPI_0, &io); |  | ||||||
|     spi_m_sync_enable(&SPI_0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void app_wake_from_backup(void) { | void app_wake_from_backup(void) { | ||||||
| @ -51,20 +21,23 @@ void app_prepare_for_standby(void) { | |||||||
| void app_wake_from_standby(void) { | void app_wake_from_standby(void) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint8_t get_id_command[4] = {0x9F}; |  | ||||||
| 
 | 
 | ||||||
| bool app_loop(void) { | bool app_loop(void) { | ||||||
|     watch_set_pin_level(A3, false); |     uint8_t get_id_command[1] = {0x9F}; | ||||||
|     io_write(io, get_id_command, 1); |  | ||||||
|     uint8_t buf[3] = {0}; |     uint8_t buf[3] = {0}; | ||||||
| 
 | 
 | ||||||
|  |     watch_set_pin_level(A3, false); | ||||||
|  | 
 | ||||||
|     // should print 0, 0, 0
 |     // should print 0, 0, 0
 | ||||||
|  |     watch_spi_send(get_id_command, 1); | ||||||
|     printf("blank: %x, %x, %x\n", buf[0], buf[1], buf[2]); |     printf("blank: %x, %x, %x\n", buf[0], buf[1], buf[2]); | ||||||
|     io_read(io, buf, 3); | 
 | ||||||
|     watch_set_pin_level(A3, true); |  | ||||||
|     // should print c8, 40, 15
 |     // should print c8, 40, 15
 | ||||||
|  |     watch_spi_receive(buf, 3); | ||||||
|     printf("ident: %x, %x, %x\n", buf[0], buf[1], buf[2]); |     printf("ident: %x, %x, %x\n", buf[0], buf[1], buf[2]); | ||||||
| 
 | 
 | ||||||
|  |     watch_set_pin_level(A3, true); | ||||||
|  | 
 | ||||||
|     delay_ms(100); |     delay_ms(100); | ||||||
| 
 | 
 | ||||||
|     return false; |     return false; | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								make.mk
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								make.mk
									
									
									
									
									
								
							| @ -85,6 +85,7 @@ SRCS += \ | |||||||
|   $(TOP)/watch-library/hardware/watch/watch_adc.c \
 |   $(TOP)/watch-library/hardware/watch/watch_adc.c \
 | ||||||
|   $(TOP)/watch-library/hardware/watch/watch_gpio.c \
 |   $(TOP)/watch-library/hardware/watch/watch_gpio.c \
 | ||||||
|   $(TOP)/watch-library/hardware/watch/watch_i2c.c \
 |   $(TOP)/watch-library/hardware/watch/watch_i2c.c \
 | ||||||
|  |   $(TOP)/watch-library/hardware/watch/watch_spi.c \
 | ||||||
|   $(TOP)/watch-library/hardware/watch/watch_uart.c \
 |   $(TOP)/watch-library/hardware/watch/watch_uart.c \
 | ||||||
|   $(TOP)/watch-library/hardware/watch/watch_deepsleep.c \
 |   $(TOP)/watch-library/hardware/watch/watch_deepsleep.c \
 | ||||||
|   $(TOP)/watch-library/hardware/watch/watch_private.c \
 |   $(TOP)/watch-library/hardware/watch/watch_private.c \
 | ||||||
| @ -152,6 +153,7 @@ SRCS += \ | |||||||
|   $(TOP)/watch-library/simulator/watch/watch_adc.c \
 |   $(TOP)/watch-library/simulator/watch/watch_adc.c \
 | ||||||
|   $(TOP)/watch-library/simulator/watch/watch_gpio.c \
 |   $(TOP)/watch-library/simulator/watch/watch_gpio.c \
 | ||||||
|   $(TOP)/watch-library/simulator/watch/watch_i2c.c \
 |   $(TOP)/watch-library/simulator/watch/watch_i2c.c \
 | ||||||
|  |   $(TOP)/watch-library/simulator/watch/watch_spi.c \
 | ||||||
|   $(TOP)/watch-library/simulator/watch/watch_uart.c \
 |   $(TOP)/watch-library/simulator/watch/watch_uart.c \
 | ||||||
|   $(TOP)/watch-library/simulator/watch/watch_deepsleep.c \
 |   $(TOP)/watch-library/simulator/watch/watch_deepsleep.c \
 | ||||||
|   $(TOP)/watch-library/simulator/watch/watch_private.c \
 |   $(TOP)/watch-library/simulator/watch/watch_private.c \
 | ||||||
|  | |||||||
| @ -15,6 +15,8 @@ struct slcd_sync_descriptor SEGMENT_LCD_0; | |||||||
| 
 | 
 | ||||||
| struct i2c_m_sync_desc I2C_0; | struct i2c_m_sync_desc I2C_0; | ||||||
| 
 | 
 | ||||||
|  | struct spi_m_sync_descriptor SPI_0; | ||||||
|  | 
 | ||||||
| void I2C_0_PORT_init(void) { | void I2C_0_PORT_init(void) { | ||||||
| 
 | 
 | ||||||
| 	gpio_set_pin_pull_mode(SDA, | 	gpio_set_pin_pull_mode(SDA, | ||||||
| @ -50,6 +52,68 @@ void I2C_0_init(void) { | |||||||
| 	I2C_0_PORT_init(); | 	I2C_0_PORT_init(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SPI_0_PORT_init(void) { | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_level(A2, | ||||||
|  | 	                   // <y> Initial level
 | ||||||
|  | 	                   // <id> pad_initial_level
 | ||||||
|  | 	                   // <false"> Low
 | ||||||
|  | 	                   // <true"> High
 | ||||||
|  | 	                   false); | ||||||
|  | 
 | ||||||
|  | 	// Set pin direction to output
 | ||||||
|  | 	gpio_set_pin_direction(A2, GPIO_DIRECTION_OUT); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_function(A2, PINMUX_PB02C_SERCOM3_PAD0); | ||||||
|  | 
 | ||||||
|  | 	// Set pin direction to input
 | ||||||
|  | 	gpio_set_pin_direction(A4, GPIO_DIRECTION_IN); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_pull_mode(A4, | ||||||
|  | 	                       // <y> Pull configuration
 | ||||||
|  | 	                       // <id> pad_pull_config
 | ||||||
|  | 	                       // <GPIO_PULL_OFF"> Off
 | ||||||
|  | 	                       // <GPIO_PULL_UP"> Pull-up
 | ||||||
|  | 	                       // <GPIO_PULL_DOWN"> Pull-down
 | ||||||
|  | 	                       GPIO_PULL_OFF); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_function(A4, PINMUX_PB00C_SERCOM3_PAD2); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_level(A1, | ||||||
|  | 	                   // <y> Initial level
 | ||||||
|  | 	                   // <id> pad_initial_level
 | ||||||
|  | 	                   // <false"> Low
 | ||||||
|  | 	                   // <true"> High
 | ||||||
|  | 	                   false); | ||||||
|  | 
 | ||||||
|  | 	// Set pin direction to output
 | ||||||
|  | 	gpio_set_pin_direction(A1, GPIO_DIRECTION_OUT); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_function(A1, PINMUX_PB01C_SERCOM3_PAD3); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_pin_level(A3, | ||||||
|  | 	                   // <y> Initial level
 | ||||||
|  | 	                   // <id> pad_initial_level
 | ||||||
|  | 	                   // <false"> Low
 | ||||||
|  | 	                   // <true"> High
 | ||||||
|  | 	                   true); | ||||||
|  | 
 | ||||||
|  | 	// Set pin direction to output
 | ||||||
|  | 	gpio_set_pin_direction(A3, GPIO_DIRECTION_OUT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SPI_0_CLOCK_init(void) { | ||||||
|  | 	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_CORE, CONF_GCLK_SERCOM3_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); | ||||||
|  | 	hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_SLOW, CONF_GCLK_SERCOM3_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); | ||||||
|  | 	hri_mclk_set_APBCMASK_SERCOM3_bit(MCLK); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SPI_0_init(void) { | ||||||
|  | 	SPI_0_CLOCK_init(); | ||||||
|  | 	spi_m_sync_init(&SPI_0, SERCOM3); | ||||||
|  | 	SPI_0_PORT_init(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void delay_driver_init(void) { | void delay_driver_init(void) { | ||||||
| 	delay_init(SysTick); | 	delay_init(SysTick); | ||||||
| } | } | ||||||
|  | |||||||
| @ -43,12 +43,18 @@ extern struct i2c_m_sync_desc I2C_0; | |||||||
| 
 | 
 | ||||||
| extern struct usart_sync_descriptor USART_0; | extern struct usart_sync_descriptor USART_0; | ||||||
| 
 | 
 | ||||||
|  | extern struct spi_m_sync_descriptor SPI_0; | ||||||
|  | 
 | ||||||
| extern struct slcd_sync_descriptor SEGMENT_LCD_0; | extern struct slcd_sync_descriptor SEGMENT_LCD_0; | ||||||
| 
 | 
 | ||||||
| void I2C_0_CLOCK_init(void); | void I2C_0_CLOCK_init(void); | ||||||
| void I2C_0_init(void); | void I2C_0_init(void); | ||||||
| void I2C_0_PORT_init(void); | void I2C_0_PORT_init(void); | ||||||
| 
 | 
 | ||||||
|  | void SPI_0_PORT_init(void); | ||||||
|  | void SPI_0_CLOCK_init(void); | ||||||
|  | void SPI_0_init(void); | ||||||
|  | 
 | ||||||
| void delay_driver_init(void); | void delay_driver_init(void); | ||||||
| 
 | 
 | ||||||
| void EXTERNAL_IRQ_0_init(void); | void EXTERNAL_IRQ_0_init(void); | ||||||
|  | |||||||
							
								
								
									
										46
									
								
								watch-library/hardware/watch/watch_spi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								watch-library/hardware/watch/watch_spi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | |||||||
|  | /*
 | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2022 Joey Castillo | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "watch_spi.h" | ||||||
|  | 
 | ||||||
|  | struct io_descriptor *spi_io; | ||||||
|  | 
 | ||||||
|  | void watch_enable_spi(void) { | ||||||
|  |     SPI_0_init(); | ||||||
|  |     spi_m_sync_get_io_descriptor(&SPI_0, &spi_io); | ||||||
|  |     spi_m_sync_enable(&SPI_0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_disable_spi(void) { | ||||||
|  |     spi_m_sync_disable(&SPI_0); | ||||||
|  |     spi_io = NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_spi_send(uint8_t *buf, uint16_t length) { | ||||||
|  | 	io_write(spi_io, buf, length); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void watch_spi_receive(uint8_t *buf, uint16_t length) { | ||||||
|  | 	io_read(spi_io, buf, length); | ||||||
|  | } | ||||||
| @ -60,6 +60,7 @@ | |||||||
| #include "watch_adc.h" | #include "watch_adc.h" | ||||||
| #include "watch_gpio.h" | #include "watch_gpio.h" | ||||||
| #include "watch_i2c.h" | #include "watch_i2c.h" | ||||||
|  | #include "watch_spi.h" | ||||||
| #include "watch_uart.h" | #include "watch_uart.h" | ||||||
| #include "watch_deepsleep.h" | #include "watch_deepsleep.h" | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										59
									
								
								watch-library/shared/watch/watch_spi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								watch-library/shared/watch/watch_spi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | /*
 | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2022 Joey Castillo | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef _WATCH_SPI_H_INCLUDED | ||||||
|  | #define _WATCH_SPI_H_INCLUDED | ||||||
|  | ////< @file watch_spi.h
 | ||||||
|  | 
 | ||||||
|  | #include "watch.h" | ||||||
|  | 
 | ||||||
|  | /** @addtogroup spi SPI Controller Driver
 | ||||||
|  |   * @brief This section covers functions related to the SAM L22's built-in SPI driver, including | ||||||
|  |   *        configuring the SPI bus and writing to / reading from devices. | ||||||
|  |   */ | ||||||
|  | /// @{
 | ||||||
|  | /** @brief Enables the SPI peripheral. Call this before attempting to interface with SPI devices.
 | ||||||
|  |   */ | ||||||
|  | void watch_enable_spi(void); | ||||||
|  | 
 | ||||||
|  | /** @brief Disables the SPI peripheral.
 | ||||||
|  |   */ | ||||||
|  | void watch_disable_spi(void); | ||||||
|  | 
 | ||||||
|  | /** @brief Sends a series of values to a device on the SPI bus.
 | ||||||
|  |   * @param buf A series of unsigned bytes; the data you wish to transmit. | ||||||
|  |   * @param length The number of bytes in buf that you wish to send. | ||||||
|  |   * @note This function does not manage the chip select pin (usually A3). | ||||||
|  |   */ | ||||||
|  | void watch_spi_send(uint8_t *buf, uint16_t length); | ||||||
|  | 
 | ||||||
|  | /** @brief Receives a series of values from a device on the SPI bus.
 | ||||||
|  |   * @param buf Storage for the incoming bytes; on return, it will contain the received data. | ||||||
|  |   * @param length The number of bytes that you wish to receive. | ||||||
|  |   * @note This function does not manage the chip select pin (usually A3). | ||||||
|  |   */ | ||||||
|  | void watch_spi_receive(uint8_t *buf, uint16_t length); | ||||||
|  | 
 | ||||||
|  | /// @}
 | ||||||
|  | #endif | ||||||
							
								
								
									
										33
									
								
								watch-library/simulator/watch/watch_spi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								watch-library/simulator/watch/watch_spi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | /*
 | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2022 Joey Castillo | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "watch_spi.h" | ||||||
|  | 
 | ||||||
|  | void watch_enable_spi(void) {} | ||||||
|  | 
 | ||||||
|  | void watch_disable_spi(void) {} | ||||||
|  | 
 | ||||||
|  | void watch_spi_send(uint8_t *buf, uint16_t length) {} | ||||||
|  | 
 | ||||||
|  | void watch_spi_receive(uint8_t *buf, uint16_t length) {} | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user