1+ #include "nrf_gpio.h"
2+ #include "nrf_gpiote.h"
3+ #include "sdk_common.h"
4+ #include "ble_l2cap.h"
5+ #include "app_error.h"
6+ #include "ble_helpers.h"
7+ #include "ble_srv_common.h"
8+ #include "nrf_log.h"
9+ #include "nrf_gpio.h"
10+ #include "nrf_drv_gpiote.h"
11+ #include "nrf_gpiote.h"
12+ #include "nrf_delay.h"
13+ #include "nrf_queue.h"
14+
15+ #include "nrfx_spim.h"
16+
17+ #define CUSTOM_FPC2534_BASE_CONFIGURATION_SERVICE {0xc5, 0x09, 0x41, 0x58, 0xf1, 0x14, 0x30, 0x78, 0x15, 0xd8, 0x47, 0x79, 0x30, 0x2a, 0x3f, 0x38}
18+ #define UUID_FPC2534 0x0000
19+
20+ #define PIN_SCK NRF_GPIO_PIN_MAP(1, 11)
21+ #define PIN_MISO NRF_GPIO_PIN_MAP(1, 13)
22+ #define PIN_MOSI NRF_GPIO_PIN_MAP(1, 15)
23+ #define PIN_CS NRF_GPIO_PIN_MAP(0, 2)
24+ #define PIN_RST NRF_GPIO_PIN_MAP(0, 31)
25+ #define PIN_IRQ NRF_GPIO_PIN_MAP(0, 29)
26+
27+ uint8_t fpc2534_custom_uuid_type ;
28+
29+ uint16_t fpc2534_connection_handle ;
30+
31+ uint16_t fpc2534_service_handle ;
32+ uint16_t fpc2534_write_characteristic_handle ;
33+ uint16_t fpc2534_read_characteristic_handle ;
34+ uint16_t fpc2534_read_cccd_handle ;
35+
36+ bool send_reads = false;
37+ bool ignore_gpio_irq = true;
38+ bool reading_header = false;
39+
40+ volatile bool waiting_for_transmission = false;
41+
42+ uint8_t spi_buf [251 ];
43+ nrfx_spim_t spi = NRFX_SPIM_INSTANCE (0 );
44+
45+ NRF_QUEUE_DEF (uint8_t , transmission_queue , 1024 , NRF_QUEUE_MODE_NO_OVERFLOW );
46+
47+ void irq_handler (nrf_drv_gpiote_pin_t pin , nrf_gpiote_polarity_t action ) {
48+ if (ignore_gpio_irq ) {
49+ return ;
50+ }
51+
52+ NRF_LOG_DEBUG ("data available! Reading header..." );
53+
54+ nrf_gpio_pin_clear (PIN_CS );
55+ nrf_delay_ms (1 );
56+
57+ reading_header = true;
58+
59+ nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (spi_buf , 8 );
60+ APP_ERROR_CHECK (nrfx_spim_xfer (& spi , & xfer , 0 ));
61+ }
62+
63+ void spi_handler (nrfx_spim_evt_t const * p_event , void * p_context ) {
64+ if (p_event -> xfer_desc .rx_length > 0 ) {
65+ if (reading_header ) {
66+ uint16_t length = spi_buf [6 ] + (spi_buf [7 ] << 8 );
67+ NRF_LOG_DEBUG ("Received header, indicating %d available" , length );
68+ // NRF_LOG_HEXDUMP_DEBUG(spi_buf, 8);
69+ nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (spi_buf + 8 , length ); // account for header (+8)
70+
71+ reading_header = false;
72+ APP_ERROR_CHECK (nrfx_spim_xfer (& spi , & xfer , 0 ));
73+ }else {
74+ uint16_t payload_length = p_event -> xfer_desc .rx_length + 8 ;
75+
76+ NRF_LOG_DEBUG ("Received %d payload" , p_event -> xfer_desc .rx_length );
77+ // NRF_LOG_HEXDUMP_DEBUG(spi_buf, payload_length);
78+ nrf_gpio_pin_set (PIN_CS );
79+
80+ if (!send_reads ) {
81+ return ;
82+ }
83+
84+ if (fpc2534_connection_handle == BLE_CONN_HANDLE_INVALID ) {
85+ return ;
86+ }
87+
88+ if (waiting_for_transmission ) {
89+ NRF_LOG_DEBUG ("waiting for transmission, queueing" );
90+ nrf_queue_write (& transmission_queue , spi_buf , payload_length );
91+ return ;
92+ }
93+
94+ ble_gatts_hvx_params_t params = {
95+ .handle = fpc2534_read_characteristic_handle ,
96+ .type = BLE_GATT_HVX_INDICATION ,
97+ .offset = 0 ,
98+ .p_len = & payload_length ,
99+ .p_data = spi_buf
100+ };
101+
102+ waiting_for_transmission = true;
103+
104+ ret_code_t err_code = sd_ble_gatts_hvx (
105+ fpc2534_connection_handle ,
106+ & params );
107+ APP_ERROR_CHECK (err_code );
108+ }
109+ return ;
110+ }
111+
112+
113+ nrf_gpio_pin_set (PIN_CS );
114+ }
115+
116+ void fpc2534_on_transmission (const ble_evt_t * p_ble_evt ) {
117+ if (p_ble_evt -> evt .gatts_evt .params .hvc .handle != fpc2534_read_characteristic_handle ) {
118+ return ;
119+ }
120+
121+ NRF_LOG_DEBUG ("transmission: %d %d" , p_ble_evt -> evt .gatts_evt .params .hvc .handle , fpc2534_read_characteristic_handle );
122+
123+ if (nrf_queue_is_empty (& transmission_queue )) {
124+ NRF_LOG_DEBUG ("no data queued" );
125+ waiting_for_transmission = false;
126+ return ;
127+ }
128+
129+ // read header
130+ nrf_queue_read (& transmission_queue , spi_buf , 8 );
131+ uint16_t length = spi_buf [6 ] + (spi_buf [7 ] << 8 );
132+ NRF_LOG_DEBUG ("another %d bytes queued" , length );
133+ nrf_queue_read (& transmission_queue , spi_buf + 8 , length );
134+
135+ uint16_t payload_length = length + 8 ;
136+
137+ ble_gatts_hvx_params_t params = {
138+ .handle = fpc2534_read_characteristic_handle ,
139+ .type = BLE_GATT_HVX_INDICATION ,
140+ .offset = 0 ,
141+ .p_len = & payload_length ,
142+ .p_data = spi_buf
143+ };
144+
145+ waiting_for_transmission = true;
146+
147+ ret_code_t err_code = sd_ble_gatts_hvx (
148+ fpc2534_connection_handle ,
149+ & params );
150+ APP_ERROR_CHECK (err_code );
151+ }
152+
153+ void fpc2534_init (){
154+ nrf_drv_gpiote_in_config_t drv_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI (false);
155+ APP_ERROR_CHECK (nrf_drv_gpiote_in_init (PIN_IRQ , & drv_config , irq_handler ));
156+ nrf_drv_gpiote_in_event_enable (PIN_IRQ , true);
157+
158+ nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG ;
159+ config .sck_pin = PIN_SCK ;
160+ config .miso_pin = PIN_MISO ;
161+ config .mosi_pin = PIN_MOSI ;
162+
163+ APP_ERROR_CHECK (nrfx_spim_init (& spi , & config , spi_handler , NULL ));
164+
165+ // reset
166+ nrf_gpio_cfg_output (PIN_RST );
167+ nrf_gpio_pin_clear (PIN_RST );
168+ nrf_delay_ms (10 );
169+ nrf_gpio_pin_set (PIN_RST );
170+ nrf_delay_ms (200 );
171+
172+ // CSn
173+ nrf_gpio_cfg_output (PIN_CS );
174+ nrf_gpio_pin_clear (PIN_CS );
175+
176+ nrf_delay_us (500 );
177+
178+ // request welcome message
179+ nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (spi_buf , 20 );
180+ APP_ERROR_CHECK (nrfx_spim_xfer (& spi , & xfer , 0 ));
181+
182+ ignore_gpio_irq = false;
183+
184+ ret_code_t err_code ;
185+
186+ ble_uuid128_t vs_uuid = {
187+ .uuid128 = CUSTOM_FPC2534_BASE_CONFIGURATION_SERVICE
188+ };
189+
190+ err_code = sd_ble_uuid_vs_add (& vs_uuid , & fpc2534_custom_uuid_type );
191+ APP_ERROR_CHECK (err_code );
192+
193+ ble_uuid_t ble_uuid = {
194+ .type = fpc2534_custom_uuid_type ,
195+ .uuid = UUID_FPC2534
196+ };
197+
198+ err_code = sd_ble_gatts_service_add (BLE_GATTS_SRVC_TYPE_PRIMARY , & ble_uuid , & fpc2534_service_handle );
199+ APP_ERROR_CHECK (err_code );
200+
201+ ble_helper_characteristic_init_t init = {
202+ .service_handle = fpc2534_service_handle ,
203+ .uuid = 0x0001 ,
204+ .uuid_type = fpc2534_custom_uuid_type ,
205+ .description_str = "SPI write" ,
206+ .is_writable = true,
207+ .max_length = sizeof (spi_buf ),
208+ .value_handle = & fpc2534_write_characteristic_handle ,
209+ };
210+ APP_ERROR_CHECK (ble_helper_characteristic_add (& init ));
211+
212+ ble_helper_characteristic_init_t init2 = {
213+ .service_handle = fpc2534_service_handle ,
214+ .uuid = 0x0002 ,
215+ .uuid_type = fpc2534_custom_uuid_type ,
216+ .description_str = "SPI response" ,
217+ .is_indicatable = true,
218+ .value_handle = & fpc2534_read_characteristic_handle ,
219+ .cccd_handle = & fpc2534_read_cccd_handle ,
220+ .max_length = 200 ,
221+ };
222+ APP_ERROR_CHECK (ble_helper_characteristic_add (& init2 ));
223+ }
224+
225+ void fpc2534_on_write_send (const ble_gatts_evt_write_t * write_evt ) {
226+ nrf_gpio_pin_clear (PIN_CS );
227+ nrf_delay_us (500 );
228+ nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX (write_evt -> data , write_evt -> len );
229+ APP_ERROR_CHECK (nrfx_spim_xfer (& spi , & xfer , 0 ));
230+ }
231+
232+ void fpc2534_on_write (const ble_evt_t * p_ble_evt )
233+ {
234+ const ble_gatts_evt_write_t * write_evt = & p_ble_evt
235+ -> evt
236+ .gatts_evt
237+ .params
238+ .write ;
239+
240+ uint16_t handle = write_evt -> handle ;
241+
242+ if (handle == fpc2534_read_cccd_handle )
243+ {
244+ send_reads = ble_srv_is_indication_enabled (write_evt -> data );
245+ NRF_LOG_DEBUG ("Enabled FPC2534 reads: %d" , send_reads );
246+ return ;
247+ }
248+ if (handle == fpc2534_write_characteristic_handle ) {
249+ fpc2534_on_write_send (write_evt );
250+ return ;
251+ }
252+ }
253+
254+ void fpc2534_on_ble_evt (const ble_evt_t * p_ble_evt )
255+ {
256+ switch (p_ble_evt -> header .evt_id )
257+ {
258+ case BLE_GAP_EVT_CONNECTED :
259+ fpc2534_connection_handle = p_ble_evt -> evt .gap_evt .conn_handle ;
260+ break ;
261+
262+ case BLE_GAP_EVT_DISCONNECTED :
263+ fpc2534_connection_handle = BLE_CONN_HANDLE_INVALID ;
264+ send_reads = false;
265+ break ;
266+
267+ case BLE_GATTS_EVT_HVC :
268+ fpc2534_on_transmission (p_ble_evt );
269+ break ;
270+
271+ case BLE_GATTS_EVT_WRITE :
272+ fpc2534_on_write (p_ble_evt );
273+ break ;
274+
275+ default :
276+ // No implementation needed.
277+ break ;
278+ }
279+ }
0 commit comments