2525 * THE SOFTWARE.
2626 */
2727
28- //TODO
2928#include "shared-bindings/busio/SPI.h"
3029#include "py/mperrno.h"
3130#include "py/runtime.h"
3534
3635#include <stdio.h>
3736
38- //bool never_reset_sercoms[SERCOM_INST_NUM];
39- //
40- //void never_reset_sercom(Sercom* sercom) {
41- // // Reset all SERCOMs except the ones being used by on-board devices.
42- // Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
43- // for (int i = 0; i < SERCOM_INST_NUM; i++) {
44- // if (sercom_instances[i] == sercom) {
45- // never_reset_sercoms[i] = true;
46- // break;
47- // }
48- // }
49- //}
50- //
51- //void allow_reset_sercom(Sercom* sercom) {
52- // // Reset all SERCOMs except the ones being used by on-board devices.
53- // Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
54- // for (int i = 0; i < SERCOM_INST_NUM; i++) {
55- // if (sercom_instances[i] == sercom) {
56- // never_reset_sercoms[i] = false;
57- // break;
58- // }
59- // }
60- //}
61- //
62- //void reset_sercoms(void) {
63- // // Reset all SERCOMs except the ones being used by on-board devices.
64- // Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
65- // for (int i = 0; i < SERCOM_INST_NUM; i++) {
66- // if (never_reset_sercoms[i]) {
67- // continue;
68- // }
69- // #ifdef MICROPY_HW_APA102_SERCOM
70- // if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) {
71- // continue;
72- // }
73- // #endif
74- // // SWRST is same for all modes of SERCOMs.
75- // sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
76- // }
77- //}
78-
79- static void config_periph_pin (const mcu_periph_obj_t * periph ) {
37+ //arrays use 0 based numbering: SPI1 is stored at index 0
38+ #define MAX_SPI 4
39+ STATIC bool reserved_spi [MAX_SPI ];
40+ STATIC bool never_reset_spi [MAX_SPI ];
41+
42+ STATIC void config_periph_pin (const mcu_periph_obj_t * periph ) {
8043 IOMUXC_SetPinMux (
8144 periph -> pin -> mux_reg , periph -> mux_mode ,
8245 periph -> input_reg , periph -> input_idx ,
@@ -97,115 +60,153 @@ static void config_periph_pin(const mcu_periph_obj_t *periph) {
9760
9861#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (CLOCK_GetDiv(kCLOCK_LpspiDiv)))
9962
63+ void spi_reset (void ) {
64+ for (int i = 0 ; i < MAX_SPI ; i ++ ) {
65+ reserved_spi [i ] = false;
66+ }
67+ }
68+
10069void common_hal_busio_spi_construct (busio_spi_obj_t * self ,
10170 const mcu_pin_obj_t * clock , const mcu_pin_obj_t * mosi ,
10271 const mcu_pin_obj_t * miso ) {
10372
104- // TODO: Allow none mosi or miso
105-
106- const uint32_t sck_count = sizeof (mcu_spi_sck_list ) / sizeof (mcu_periph_obj_t );
107- const uint32_t miso_count = sizeof (mcu_spi_miso_list ) / sizeof (mcu_periph_obj_t );
108- const uint32_t mosi_count = sizeof (mcu_spi_mosi_list ) / sizeof (mcu_periph_obj_t );
73+ const uint32_t sck_count = MP_ARRAY_SIZE (mcu_spi_sck_list );
74+ const uint32_t miso_count = MP_ARRAY_SIZE (mcu_spi_miso_list );
75+ const uint32_t mosi_count = MP_ARRAY_SIZE (mcu_spi_mosi_list );
76+ bool spi_taken = false;
10977
110- for (uint32_t i = 0 ; i < sck_count ; ++ i ) {
111- if (mcu_spi_sck_list [i ].pin != clock )
78+ for (uint i = 0 ; i < sck_count ; i ++ ) {
79+ if (mcu_spi_sck_list [i ].pin != clock ) {
11280 continue ;
113-
114- for (uint32_t j = 0 ; j < miso_count ; ++ j ) {
115- if (mcu_spi_miso_list [j ].pin != miso )
116- continue ;
117-
118- if (mcu_spi_miso_list [j ].bank_idx != mcu_spi_sck_list [i ].bank_idx )
119- continue ;
120-
121- for (uint32_t k = 0 ; k < mosi_count ; ++ k ) {
122- if (mcu_spi_mosi_list [k ].pin != mosi )
81+ }
82+ //if both MOSI and MISO exist, loop search normally
83+ if ((mosi != NULL ) && (miso != NULL )) {
84+ for (uint j = 0 ; j < mosi_count ; j ++ ) {
85+ if ((mcu_spi_mosi_list [i ].pin != mosi )
86+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_mosi_list [j ].bank_idx )){
12387 continue ;
124-
125- if (mcu_spi_mosi_list [k ].bank_idx != mcu_spi_miso_list [j ].bank_idx )
88+ }
89+ for (uint k = 0 ; k < miso_count ; k ++ ) {
90+ if ((mcu_spi_miso_list [k ].pin != miso ) //everything needs the same index
91+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_miso_list [k ].bank_idx )) {
92+ continue ;
93+ }
94+ //keep looking if the SPI is taken, edge case
95+ if (reserved_spi [mcu_spi_sck_list [i ].bank_idx - 1 ]) {
96+ spi_taken = true;
97+ continue ;
98+ }
99+ //store pins if not
100+ self -> clock = & mcu_spi_sck_list [i ];
101+ self -> mosi = & mcu_spi_mosi_list [j ];
102+ self -> miso = & mcu_spi_miso_list [k ];
103+ break ;
104+ }
105+ if (self -> clock != NULL ) {
106+ break ; // Multi-level break to pick lowest peripheral
107+ }
108+ }
109+ if (self -> clock != NULL ) {
110+ break ;
111+ }
112+ // if just MISO, reduce search
113+ } else if (miso != NULL ) {
114+ for (uint j = 0 ; j < miso_count ; j ++ ) {
115+ if ((mcu_spi_miso_list [j ].pin != miso ) //only SCK and MISO need the same index
116+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_miso_list [j ].bank_idx )) {
126117 continue ;
127-
128- self -> clock_pin = & mcu_spi_sck_list [i ];
129- self -> miso_pin = & mcu_spi_miso_list [j ];
130- self -> mosi_pin = & mcu_spi_mosi_list [k ];
131-
118+ }
119+ if (reserved_spi [mcu_spi_sck_list [i ].bank_idx - 1 ]) {
120+ spi_taken = true;
121+ continue ;
122+ }
123+ self -> clock = & mcu_spi_sck_list [i ];
124+ self -> mosi = NULL ;
125+ self -> miso = & mcu_spi_miso_list [j ];
126+ break ;
127+ }
128+ if (self -> clock != NULL ) {
132129 break ;
133130 }
131+ // if just MOSI, reduce search
132+ } else if (mosi != NULL ) {
133+ for (uint j = 0 ; j < mosi_count ; j ++ ) {
134+ if ((mcu_spi_mosi_list [j ].pin != mosi ) //only SCK and MOSI need the same index
135+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_mosi_list [j ].bank_idx )) {
136+ continue ;
137+ }
138+ if (reserved_spi [mcu_spi_sck_list [i ].bank_idx - 1 ]) {
139+ spi_taken = true;
140+ continue ;
141+ }
142+ self -> clock = & mcu_spi_sck_list [i ];
143+ self -> mosi = & mcu_spi_mosi_list [j ];
144+ self -> miso = NULL ;
145+ break ;
146+ }
147+ if (self -> clock != NULL ) {
148+ break ;
149+ }
150+ } else {
151+ //throw an error immediately
152+ mp_raise_ValueError (translate ("Must provide MISO or MOSI pin" ));
134153 }
135154 }
136155
137- if (self -> clock_pin == NULL || self -> mosi_pin == NULL || self -> miso_pin == NULL ) {
138- mp_raise_RuntimeError ( translate ( "Invalid SPI pin selection" )) ;
156+ if (self -> clock != NULL && ( self -> mosi != NULL || self -> miso != NULL ) ) {
157+ self -> spi = mcu_spi_banks [ self -> clock -> bank_idx - 1 ] ;
139158 } else {
140- self -> spi = mcu_spi_banks [self -> clock_pin -> bank_idx - 1 ];
159+ if (spi_taken ) {
160+ mp_raise_ValueError (translate ("Hardware busy, try alternative pins" ));
161+ } else {
162+ mp_raise_ValueError (translate ("Invalid SPI pin selection" ));
163+ }
141164 }
142165
143- config_periph_pin (self -> mosi_pin );
144- config_periph_pin (self -> miso_pin );
145- config_periph_pin (self -> clock_pin );
166+ config_periph_pin (self -> clock );
167+ if (self -> mosi != NULL ) {
168+ config_periph_pin (self -> mosi );
169+ }
170+ if (self -> miso != NULL ) {
171+ config_periph_pin (self -> miso );
172+ }
173+ reserved_spi [self -> clock -> bank_idx - 1 ] = true;
146174
147175 lpspi_master_config_t config = { 0 };
148176 LPSPI_MasterGetDefaultConfig (& config );
149177
150178 // Always start at 250khz which is what SD cards need. They are sensitive to
151179 // SPI bus noise before they are put into SPI mode.
152180 config .baudRate = 250000 ;
153-
154181 LPSPI_MasterInit (self -> spi , & config , LPSPI_MASTER_CLK_FREQ );
155-
156182 LPSPI_Enable (self -> spi , false);
157183 uint32_t tcrPrescaleValue ;
158184 self -> baudrate = LPSPI_MasterSetBaudRate (self -> spi , config .baudRate , LPSPI_MASTER_CLK_FREQ , & tcrPrescaleValue );
159185 LPSPI_Enable (self -> spi , true);
160186
161- claim_pin (self -> clock_pin -> pin );
162-
163- // if (mosi_none) {
164- // self->MOSI_pin = NO_PIN;
165- // } else {
166- // gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_OUT);
167- // gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF);
168- // gpio_set_pin_function(mosi->number, mosi_pinmux);
169- // self->MOSI_pin = mosi->number;
170- claim_pin (self -> mosi_pin -> pin );
171- // }
172-
173- // if (miso_none) {
174- // self->MISO_pin = NO_PIN;
175- // } else {
176- // gpio_set_pin_direction(miso->number, GPIO_DIRECTION_IN);
177- // gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF);
178- // gpio_set_pin_function(miso->number, miso_pinmux);
179- // self->MISO_pin = miso->number;
180- claim_pin (self -> miso_pin -> pin );
181- // }
187+ claim_pin (self -> clock -> pin );
188+ if (self -> mosi != NULL ) {
189+ claim_pin (self -> mosi -> pin );
190+ }
191+ if (self -> miso != NULL ) {
192+ claim_pin (self -> miso -> pin );
193+ }
182194}
183195
184196void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
185- // never_reset_sercom(self->spi_desc.dev.prvt);
186-
187- // never_reset_pin_number(self->clock_pin);
188- // never_reset_pin_number(self->MOSI_pin);
189- // never_reset_pin_number(self->MISO_pin);
197+ // TODO
190198}
191199
192200bool common_hal_busio_spi_deinited (busio_spi_obj_t * self ) {
193- return self -> clock_pin == NULL ;
201+ return self -> clock == NULL ;
194202}
195203
196204void common_hal_busio_spi_deinit (busio_spi_obj_t * self ) {
197205 if (common_hal_busio_spi_deinited (self )) {
198206 return ;
199207 }
200208
201- // allow_reset_sercom(self->spi_desc.dev.prvt);
202-
203- // spi_m_sync_disable(&self->spi_desc);
204- // spi_m_sync_deinit(&self->spi_desc);
205- // reset_pin_number(self->clock_pin);
206- // reset_pin_number(self->MOSI_pin);
207- // reset_pin_number(self->MISO_pin);
208- self -> clock_pin = NULL ;
209+ self -> clock = NULL ;
209210}
210211
211212bool common_hal_busio_spi_configure (busio_spi_obj_t * self ,
@@ -260,6 +261,9 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
260261 if (len == 0 ) {
261262 return true;
262263 }
264+ if (self -> mosi == NULL ) {
265+ mp_raise_ValueError (translate ("No MOSI Pin" ));
266+ }
263267
264268 lpspi_transfer_t xfer = { 0 };
265269 xfer .txData = (uint8_t * )data ;
@@ -278,6 +282,9 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
278282 if (len == 0 ) {
279283 return true;
280284 }
285+ if (self -> miso == NULL ) {
286+ mp_raise_ValueError (translate ("No MISO Pin" ));
287+ }
281288
282289 LPSPI_SetDummyData (self -> spi , write_value );
283290
@@ -296,6 +303,9 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
296303 if (len == 0 ) {
297304 return true;
298305 }
306+ if (self -> miso == NULL || self -> mosi == NULL ) {
307+ mp_raise_ValueError (translate ("Missing MISO or MOSI Pin" ));
308+ }
299309
300310 LPSPI_SetDummyData (self -> spi , 0xFF );
301311
0 commit comments