5
5
*
6
6
* Copyright (c) 2016 Sandeep Mistry All right reserved.
7
7
* Copyright (c) 2017 hathach
8
+ * Copyright (c) 2018 Artur Pacholec
8
9
*
9
10
* Permission is hereby granted, free of charge, to any person obtaining a copy
10
11
* of this software and associated documentation files (the "Software"), to deal
29
30
#include "py/mperrno.h"
30
31
#include "py/runtime.h"
31
32
32
- #include "pins.h"
33
- #include "nrf.h"
33
+ #include "nrfx_twim.h"
34
+ #include "nrf_gpio.h"
35
+
36
+ #define INST_NO 0
37
+
38
+ static uint8_t twi_error_to_mp (const nrfx_err_t err ) {
39
+ switch (err ) {
40
+ case NRFX_ERROR_DRV_TWI_ERR_ANACK :
41
+ return MP_ENODEV ;
42
+ case NRFX_ERROR_BUSY :
43
+ return MP_EBUSY ;
44
+ case NRFX_ERROR_DRV_TWI_ERR_DNACK :
45
+ case NRFX_ERROR_INVALID_ADDR :
46
+ return MP_EIO ;
47
+ default :
48
+ break ;
49
+ }
50
+
51
+ return 0 ;
52
+ }
34
53
35
- void common_hal_busio_i2c_construct (busio_i2c_obj_t * self , const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout ) {
36
- if (scl -> pin == sda -> pin ) {
54
+ void common_hal_busio_i2c_construct (busio_i2c_obj_t * self , const mcu_pin_obj_t * scl , const mcu_pin_obj_t * sda , uint32_t frequency , uint32_t timeout ) {
55
+ if (scl -> pin == sda -> pin )
37
56
mp_raise_ValueError ("Invalid pins" );
38
- }
39
57
40
- NRF_GPIO -> PIN_CNF [scl -> pin ] = ((uint32_t )GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos )
41
- | ((uint32_t )GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos )
42
- | ((uint32_t )GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos )
43
- | ((uint32_t )GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos )
44
- | ((uint32_t )GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos );
45
-
46
- NRF_GPIO -> PIN_CNF [sda -> pin ] = ((uint32_t )GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos )
47
- | ((uint32_t )GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos )
48
- | ((uint32_t )GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos )
49
- | ((uint32_t )GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos )
50
- | ((uint32_t )GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos );
51
-
52
- // 1 for I2C, 0 for SPI
53
- self -> twi = NRF_TWIM1 ;
54
-
55
- if ( frequency < 100000 ) {
56
- self -> twi -> FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100 ;
57
- }else if ( frequency < 250000 ) {
58
- self -> twi -> FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250 ;
59
- }else {
60
- self -> twi -> FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400 ;
58
+ const nrfx_twim_t instance = NRFX_TWIM_INSTANCE (INST_NO );
59
+ self -> twim = instance ;
60
+
61
+ nrfx_twim_config_t config = NRFX_TWIM_DEFAULT_CONFIG ;
62
+ config .scl = NRF_GPIO_PIN_MAP (scl -> port , scl -> pin );
63
+ config .sda = NRF_GPIO_PIN_MAP (sda -> port , sda -> pin );
64
+
65
+ // change freq. only if it's less than the default 400K
66
+ if (frequency < 100000 ) {
67
+ config .frequency = NRF_TWIM_FREQ_100K ;
68
+ } else if (frequency < 250000 ) {
69
+ config .frequency = NRF_TWIM_FREQ_250K ;
61
70
}
62
71
63
- self -> twi -> ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos );
72
+ nrfx_err_t err = nrfx_twim_init (& self -> twim , & config , NULL , NULL );
73
+
74
+ // A soft reset doesn't uninit the driver so we might end up with a invalid state
75
+ if (err == NRFX_ERROR_INVALID_STATE ) {
76
+ nrfx_twim_uninit (& self -> twim );
77
+ err = nrfx_twim_init (& self -> twim , & config , NULL , NULL );
78
+ }
64
79
65
- self -> twi -> PSEL . SCL = scl -> pin ;
66
- self -> twi -> PSEL . SDA = sda -> pin ;
80
+ if ( err != NRFX_SUCCESS )
81
+ mp_raise_OSError ( MP_EIO ) ;
67
82
83
+ self -> inited = true;
68
84
}
69
85
70
86
bool common_hal_busio_i2c_deinited (busio_i2c_obj_t * self ) {
71
- return self -> twi -> ENABLE == 0 ;
87
+ return ! self -> inited ;
72
88
}
73
89
74
90
void common_hal_busio_i2c_deinit (busio_i2c_obj_t * self ) {
75
- if (common_hal_busio_i2c_deinited (self )) {
91
+ if (common_hal_busio_i2c_deinited (self ))
76
92
return ;
77
- }
78
-
79
- uint8_t scl_pin = self -> twi -> PSEL .SCL ;
80
- uint8_t sda_pin = self -> twi -> PSEL .SDA ;
81
93
82
- self -> twi -> ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos );
83
- self -> twi -> PSEL .SCL = (TWIM_PSEL_SCL_CONNECT_Disconnected << TWIM_PSEL_SCL_CONNECT_Pos );
84
- self -> twi -> PSEL .SDA = (TWIM_PSEL_SDA_CONNECT_Disconnected << TWIM_PSEL_SDA_CONNECT_Pos );
94
+ nrfx_twim_uninit (& self -> twim );
85
95
86
- reset_pin (scl_pin );
87
- reset_pin (sda_pin );
96
+ self -> inited = false;
88
97
}
89
98
99
+ // nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API
90
100
bool common_hal_busio_i2c_probe (busio_i2c_obj_t * self , uint8_t addr ) {
91
- // Write no data when just probing
92
- return 0 == common_hal_busio_i2c_write (self , addr , NULL , 0 , true);
101
+ NRF_TWIM_Type * reg = self -> twim .p_twim ;
102
+ bool found = true;
103
+
104
+ nrfx_twim_enable (& self -> twim );
105
+
106
+ nrf_twim_address_set (reg , addr );
107
+ nrf_twim_tx_buffer_set (reg , NULL , 0 );
108
+
109
+ nrf_twim_task_trigger (reg , NRF_TWIM_TASK_RESUME );
110
+
111
+ nrf_twim_task_trigger (reg , NRF_TWIM_TASK_STARTTX );
112
+ while (nrf_twim_event_check (reg , NRF_TWIM_EVENT_TXSTARTED ) == 0 &&
113
+ nrf_twim_event_check (reg , NRF_TWIM_EVENT_ERROR ) == 0 );
114
+ nrf_twim_event_clear (reg , NRF_TWIM_EVENT_TXSTARTED );
115
+
116
+ nrf_twim_task_trigger (reg , NRF_TWIM_TASK_STOP );
117
+ while (nrf_twim_event_check (reg , NRF_TWIM_EVENT_STOPPED ) == 0 );
118
+ nrf_twim_event_clear (reg , NRF_TWIM_EVENT_STOPPED );
119
+
120
+ if (nrf_twim_event_check (reg , NRF_TWIM_EVENT_ERROR )) {
121
+ nrf_twim_event_clear (reg , NRF_TWIM_EVENT_ERROR );
122
+
123
+ nrf_twim_errorsrc_get_and_clear (reg );
124
+ found = false;
125
+ }
126
+
127
+ nrfx_twim_disable (& self -> twim );
128
+
129
+ return found ;
93
130
}
94
131
95
132
bool common_hal_busio_i2c_try_lock (busio_i2c_obj_t * self ) {
@@ -112,96 +149,23 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
112
149
}
113
150
114
151
uint8_t common_hal_busio_i2c_write (busio_i2c_obj_t * self , uint16_t addr , const uint8_t * data , size_t len , bool stopBit ) {
115
- NRF_TWIM_Type * twi = self -> twi ;
116
-
117
- twi -> ADDRESS = addr ;
118
- twi -> TASKS_RESUME = 1 ;
119
-
120
- twi -> TXD .PTR = (uint32_t ) data ;
121
- twi -> TXD .MAXCNT = len ;
122
-
123
- twi -> TASKS_STARTTX = 1 ;
124
-
125
- // Wait for TX started
126
- while (!twi -> EVENTS_TXSTARTED && !twi -> EVENTS_ERROR ) {}
127
- twi -> EVENTS_TXSTARTED = 0 ;
128
-
129
- // Wait for TX complete
130
- if ( len )
131
- {
132
- while (!twi -> EVENTS_LASTTX && !twi -> EVENTS_ERROR ) {}
133
- twi -> EVENTS_LASTTX = 0x0UL ;
134
- }
135
-
136
- if (stopBit || twi -> EVENTS_ERROR )
137
- {
138
- twi -> TASKS_STOP = 0x1UL ;
139
- while (!twi -> EVENTS_STOPPED );
140
- twi -> EVENTS_STOPPED = 0x0UL ;
141
- }
142
- else
143
- {
144
- twi -> TASKS_SUSPEND = 0x1UL ;
145
- while (!twi -> EVENTS_SUSPENDED );
146
- twi -> EVENTS_SUSPENDED = 0x0UL ;
147
- }
148
-
149
- if (twi -> EVENTS_ERROR )
150
- {
151
- twi -> EVENTS_ERROR = 0x0UL ;
152
- uint32_t error = twi -> ERRORSRC ;
153
- twi -> ERRORSRC = error ;
154
-
155
- return error ;
156
- }
157
-
158
- return 0 ;
159
- }
160
-
161
- uint8_t common_hal_busio_i2c_read (busio_i2c_obj_t * self , uint16_t addr , uint8_t * data , size_t len ) {
162
- NRF_TWIM_Type * twi = self -> twi ;
163
-
164
- if (len == 0 ) return 0 ;
165
- bool stopBit = true; // should be a parameter
152
+ if (len == 0 )
153
+ return common_hal_busio_i2c_probe (self , addr ) ? 0 : MP_ENODEV ;
166
154
167
- twi -> ADDRESS = addr ;
168
- twi -> TASKS_RESUME = 0x1UL ;
155
+ nrfx_twim_enable (& self -> twim );
156
+ const nrfx_err_t err = nrfx_twim_tx (& self -> twim , addr , data , len , !stopBit );
157
+ nrfx_twim_disable (& self -> twim );
169
158
170
- twi -> RXD .PTR = (uint32_t ) data ;
171
- twi -> RXD .MAXCNT = len ;
172
-
173
- twi -> TASKS_STARTRX = 0x1UL ;
174
-
175
- while (!twi -> EVENTS_RXSTARTED && !twi -> EVENTS_ERROR );
176
- twi -> EVENTS_RXSTARTED = 0x0UL ;
177
-
178
- while (!twi -> EVENTS_LASTRX && !twi -> EVENTS_ERROR );
179
- twi -> EVENTS_LASTRX = 0x0UL ;
180
-
181
- if (stopBit || twi -> EVENTS_ERROR )
182
- {
183
- twi -> TASKS_STOP = 0x1UL ;
184
- while (!twi -> EVENTS_STOPPED );
185
- twi -> EVENTS_STOPPED = 0x0UL ;
186
- }
187
- else
188
- {
189
- twi -> TASKS_SUSPEND = 0x1UL ;
190
- while (!twi -> EVENTS_SUSPENDED );
191
- twi -> EVENTS_SUSPENDED = 0x0UL ;
192
- }
193
-
194
- if (twi -> EVENTS_ERROR )
195
- {
196
- twi -> EVENTS_ERROR = 0x0UL ;
197
- uint32_t error = twi -> ERRORSRC ;
198
- twi -> ERRORSRC = error ;
159
+ return twi_error_to_mp (err );
160
+ }
199
161
200
- return error ;
201
- }
162
+ uint8_t common_hal_busio_i2c_read (busio_i2c_obj_t * self , uint16_t addr , uint8_t * data , size_t len ) {
163
+ if (len == 0 )
164
+ return 0 ;
202
165
203
- // number of byte read
204
- // (void) _p_twim->RXD.AMOUNT;
166
+ nrfx_twim_enable (& self -> twim );
167
+ const nrfx_err_t err = nrfx_twim_rx (& self -> twim , addr , data , len );
168
+ nrfx_twim_disable (& self -> twim );
205
169
206
- return 0 ;
170
+ return twi_error_to_mp ( err ) ;
207
171
}
0 commit comments