4444
4545void common_hal_busio_spi_construct (busio_spi_obj_t * self ,
4646 const mcu_pin_obj_t * clock , const mcu_pin_obj_t * mosi ,
47- const mcu_pin_obj_t * miso , bool half_duplex , bool slave_mode ) {
47+ const mcu_pin_obj_t * miso , const mcu_pin_obj_t * ss , bool half_duplex , bool slave_mode ) {
4848 Sercom * sercom = NULL ;
4949 uint8_t sercom_index ;
5050 uint32_t clock_pinmux = 0 ;
5151 bool mosi_none = mosi == NULL ;
5252 bool miso_none = miso == NULL ;
5353 uint32_t mosi_pinmux = 0 ;
5454 uint32_t miso_pinmux = 0 ;
55+ uint32_t ss_pinmux = 0 ;
5556 uint8_t clock_pad = 0 ;
5657 uint8_t mosi_pad = 0 ;
5758 uint8_t miso_pad = 0 ;
@@ -96,35 +97,87 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
9697 if (!samd_peripherals_valid_spi_clock_pad (clock_pad )) {
9798 continue ;
9899 }
99- for (int j = 0 ; j < NUM_SERCOMS_PER_PIN ; j ++ ) {
100- if (!mosi_none ) {
101- if (sercom_index == mosi -> sercom [j ].index ) {
102- mosi_pinmux = PINMUX (mosi -> number , (j == 0 ) ? MUX_C : MUX_D );
103- mosi_pad = mosi -> sercom [j ].pad ;
104- dopo = samd_peripherals_get_spi_dopo (clock_pad , mosi_pad );
105- if (dopo > 0x3 ) {
106- continue ; // pad combination not possible
100+ if (slave_mode ) {
101+ // find miso_pad first, since it corresponds to dopo which takes limited values
102+ for (int j = 0 ; j < NUM_SERCOMS_PER_PIN ; j ++ ) {
103+ if (!miso_none ) {
104+ if (sercom_index == miso -> sercom [j ].index ) {
105+ miso_pinmux = PINMUX (miso -> number , (j == 0 ) ? MUX_C : MUX_D );
106+ miso_pad = miso -> sercom [j ].pad ;
107+ dopo = samd_peripherals_get_spi_dopo (clock_pad , miso_pad );
108+ if (dopo > 0x3 ) {
109+ continue ; // pad combination not possible
110+ }
111+ if (mosi_none ) {
112+ for (int m = 0 ; m < NUM_SERCOMS_PER_PIN ; m ++ ) {
113+ if (sercom_index == ss -> sercom [m ].index ) {
114+ ss_pinmux = PINMUX (ss -> number , (m == 0 ) ? MUX_C : MUX_D );
115+ sercom = potential_sercom ;
116+ break ;
117+ }
118+ }
119+ if (sercom != NULL ) {
120+ break ;
121+ }
122+ }
123+ } else {
124+ continue ;
107125 }
108- if (miso_none ) {
109- sercom = potential_sercom ;
110- break ;
126+ }
127+ if (!mosi_none ) {
128+ for (int k = 0 ; k < NUM_SERCOMS_PER_PIN ; k ++ ) {
129+ if (sercom_index == mosi -> sercom [k ].index ) {
130+ mosi_pinmux = PINMUX (mosi -> number , (k == 0 ) ? MUX_C : MUX_D );
131+ mosi_pad = mosi -> sercom [k ].pad ;
132+ for (int m = 0 ; m < NUM_SERCOMS_PER_PIN ; m ++ ) {
133+ if (sercom_index == ss -> sercom [m ].index ) {
134+ ss_pinmux = PINMUX (ss -> number , (m == 0 ) ? MUX_C : MUX_D );
135+ sercom = potential_sercom ;
136+ break ;
137+ }
138+ }
139+ if (sercom != NULL ) {
140+ break ;
141+ }
142+ }
111143 }
112- } else {
113- continue ;
144+ }
145+ if (sercom != NULL ) {
146+ break ;
114147 }
115148 }
116- if (!miso_none ) {
117- for (int k = 0 ; k < NUM_SERCOMS_PER_PIN ; k ++ ) {
118- if (sercom_index == miso -> sercom [k ].index ) {
119- miso_pinmux = PINMUX (miso -> number , (k == 0 ) ? MUX_C : MUX_D );
120- miso_pad = miso -> sercom [k ].pad ;
121- sercom = potential_sercom ;
122- break ;
149+ } else {
150+ // find mosi_pad first, since it corresponds to dopo which takes limited values
151+ for (int j = 0 ; j < NUM_SERCOMS_PER_PIN ; j ++ ) {
152+ if (!mosi_none ) {
153+ if (sercom_index == mosi -> sercom [j ].index ) {
154+ mosi_pinmux = PINMUX (mosi -> number , (j == 0 ) ? MUX_C : MUX_D );
155+ mosi_pad = mosi -> sercom [j ].pad ;
156+ dopo = samd_peripherals_get_spi_dopo (clock_pad , mosi_pad );
157+ if (dopo > 0x3 ) {
158+ continue ; // pad combination not possible
159+ }
160+ if (miso_none ) {
161+ sercom = potential_sercom ;
162+ break ;
163+ }
164+ } else {
165+ continue ;
123166 }
124167 }
125- }
126- if (sercom != NULL ) {
127- break ;
168+ if (!miso_none ) {
169+ for (int k = 0 ; k < NUM_SERCOMS_PER_PIN ; k ++ ) {
170+ if (sercom_index == miso -> sercom [k ].index ) {
171+ miso_pinmux = PINMUX (miso -> number , (k == 0 ) ? MUX_C : MUX_D );
172+ miso_pad = miso -> sercom [k ].pad ;
173+ sercom = potential_sercom ;
174+ break ;
175+ }
176+ }
177+ }
178+ if (sercom != NULL ) {
179+ break ;
180+ }
128181 }
129182 }
130183 if (sercom != NULL ) {
@@ -147,8 +200,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
147200 // the prototypical SERCOM.
148201
149202 hri_sercomspi_write_CTRLA_MODE_bf (sercom , slave_mode ? 2 : 3 );
203+ self -> slave_mode = slave_mode ;
150204 hri_sercomspi_write_CTRLA_DOPO_bf (sercom , dopo );
151- hri_sercomspi_write_CTRLA_DIPO_bf (sercom , miso_pad );
205+ hri_sercomspi_write_CTRLA_DIPO_bf (sercom , slave_mode ? mosi_pad : miso_pad );
152206
153207 // Always start at 250khz which is what SD cards need. They are sensitive to
154208 // SPI bus noise before they are put into SPI mode.
@@ -185,6 +239,14 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
185239 claim_pin (miso );
186240 }
187241
242+ if (slave_mode ) {
243+ gpio_set_pin_direction (ss -> number , slave_mode ? GPIO_DIRECTION_OUT : GPIO_DIRECTION_IN );
244+ gpio_set_pin_pull_mode (ss -> number , GPIO_PULL_OFF );
245+ gpio_set_pin_function (ss -> number , ss_pinmux );
246+ self -> SS_pin = ss -> number ;
247+ claim_pin (ss );
248+ }
249+
188250 spi_m_sync_enable (& self -> spi_desc );
189251}
190252
0 commit comments