2
0

gpio_exp.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /* GDS Example
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include "freertos/FreeRTOS.h"
  10. #include "freertos/task.h"
  11. #include "freertos/timers.h"
  12. #include "freertos/queue.h"
  13. #include "esp_task.h"
  14. #include "esp_log.h"
  15. #include "driver/gpio.h"
  16. #include "driver/i2c.h"
  17. #include "driver/spi_master.h"
  18. #include "gpio_exp.h"
  19. #define GPIO_EXP_INTR 0x100
  20. #define GPIO_EXP_WRITE 0x200
  21. /*
  22. shadow register is both output and input, so we assume that reading to the
  23. ports also reads the value set on output
  24. */
  25. typedef struct gpio_exp_s {
  26. uint32_t first, last;
  27. int intr;
  28. bool intr_pending;
  29. struct {
  30. struct gpio_exp_phy_s phy;
  31. spi_device_handle_t spi_handle;
  32. };
  33. uint32_t shadow, pending;
  34. TickType_t age;
  35. SemaphoreHandle_t mutex;
  36. uint32_t r_mask, w_mask;
  37. uint32_t pullup, pulldown;
  38. struct gpio_exp_isr_s {
  39. gpio_isr_t handler;
  40. void *arg;
  41. TimerHandle_t timer;
  42. } isr[32];
  43. struct gpio_exp_model_s const *model;
  44. } gpio_exp_t;
  45. typedef struct {
  46. enum { ASYNC_WRITE } type;
  47. int gpio;
  48. int level;
  49. gpio_exp_t *expander;
  50. } queue_request_t;
  51. static const char TAG[] = "gpio expander";
  52. static void IRAM_ATTR intr_isr_handler(void* arg);
  53. static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio);
  54. static esp_err_t mpr121_init(gpio_exp_t* self);
  55. static uint32_t mpr121_read(gpio_exp_t* self);
  56. static void mpr121_write(gpio_exp_t* self);
  57. static void pca9535_set_direction(gpio_exp_t* self);
  58. static uint32_t pca9535_read(gpio_exp_t* self);
  59. static void pca9535_write(gpio_exp_t* self);
  60. static uint32_t pca85xx_read(gpio_exp_t* self);
  61. static void pca85xx_write(gpio_exp_t* self);
  62. static esp_err_t mcp23017_init(gpio_exp_t* self);
  63. static void mcp23017_set_pull_mode(gpio_exp_t* self);
  64. static void mcp23017_set_direction(gpio_exp_t* self);
  65. static uint32_t mcp23017_read(gpio_exp_t* self);
  66. static void mcp23017_write(gpio_exp_t* self);
  67. static esp_err_t mcp23s17_init(gpio_exp_t* self);
  68. static void mcp23s17_set_pull_mode(gpio_exp_t* self);
  69. static void mcp23s17_set_direction(gpio_exp_t* self);
  70. static uint32_t mcp23s17_read(gpio_exp_t* self);
  71. static void mcp23s17_write(gpio_exp_t* self);
  72. static void aw9523_set_direction(gpio_exp_t* self);
  73. static uint32_t aw9523_read(gpio_exp_t* self);
  74. static void aw9523_write(gpio_exp_t* self);
  75. static void service_handler(void *arg);
  76. static void debounce_handler( TimerHandle_t xTimer );
  77. static esp_err_t i2c_write(uint8_t port, uint8_t addr, uint8_t reg, uint32_t data, int len);
  78. static uint32_t i2c_read(uint8_t port, uint8_t addr, uint8_t reg, int len);
  79. static spi_device_handle_t spi_config(struct gpio_exp_phy_s *phy);
  80. static esp_err_t spi_write(spi_device_handle_t handle, uint8_t addr, uint8_t reg, uint32_t data, int len);
  81. static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg, int len);
  82. static const struct gpio_exp_model_s {
  83. char *model;
  84. gpio_int_type_t trigger;
  85. esp_err_t (*init)(gpio_exp_t* self);
  86. uint32_t (*read)(gpio_exp_t* self);
  87. void (*write)(gpio_exp_t* self);
  88. void (*set_direction)(gpio_exp_t* self);
  89. void (*set_pull_mode)(gpio_exp_t* self);
  90. } registered[] = {
  91. { .model = "mpr121",
  92. .trigger = GPIO_INTR_LOW_LEVEL,
  93. .init = mpr121_init,
  94. .read = mpr121_read,
  95. .write = mpr121_write, },
  96. { .model = "pca9535",
  97. .trigger = GPIO_INTR_LOW_LEVEL,
  98. .set_direction = pca9535_set_direction,
  99. .read = pca9535_read,
  100. .write = pca9535_write, },
  101. { .model = "pca85xx",
  102. .trigger = GPIO_INTR_LOW_LEVEL,
  103. .read = pca85xx_read,
  104. .write = pca85xx_write, },
  105. { .model = "mcp23017",
  106. .trigger = GPIO_INTR_LOW_LEVEL,
  107. .init = mcp23017_init,
  108. .set_direction = mcp23017_set_direction,
  109. .set_pull_mode = mcp23017_set_pull_mode,
  110. .read = mcp23017_read,
  111. .write = mcp23017_write, },
  112. { .model = "mcp23s17",
  113. .trigger = GPIO_INTR_LOW_LEVEL,
  114. .init = mcp23s17_init,
  115. .set_direction = mcp23s17_set_direction,
  116. .set_pull_mode = mcp23s17_set_pull_mode,
  117. .read = mcp23s17_read,
  118. .write = mcp23s17_write, },
  119. { .model = "aw9523",
  120. .trigger = GPIO_INTR_LOW_LEVEL,
  121. .set_direction = aw9523_set_direction,
  122. .read = aw9523_read,
  123. .write = aw9523_write, },
  124. };
  125. static EXT_RAM_ATTR uint8_t n_expanders;
  126. static EXT_RAM_ATTR QueueHandle_t message_queue;
  127. static EXT_RAM_ATTR gpio_exp_t expanders[4];
  128. static EXT_RAM_ATTR TaskHandle_t service_task;
  129. /******************************************************************************
  130. * Retrieve base from an expander reference
  131. */
  132. uint32_t gpio_exp_get_base(gpio_exp_t *expander) {
  133. return expander->first;
  134. }
  135. /******************************************************************************
  136. * Retrieve reference from a GPIO
  137. */
  138. gpio_exp_t *gpio_exp_get_expander(int gpio) {
  139. int _gpio = gpio;
  140. return find_expander(NULL, &_gpio);
  141. }
  142. /******************************************************************************
  143. * Create an I2C expander
  144. */
  145. gpio_exp_t* gpio_exp_create(const gpio_exp_config_t *config) {
  146. gpio_exp_t *expander = expanders + n_expanders;
  147. if (config->base < GPIO_NUM_MAX || n_expanders == sizeof(expanders)/sizeof(gpio_exp_t)) {
  148. ESP_LOGE(TAG, "Base %d GPIO must be at least %d for %s or too many expanders %d", config->base, GPIO_NUM_MAX, config->model, n_expanders);
  149. return NULL;
  150. }
  151. // See if we know that model (expanders is zero-initialized)
  152. for (int i = 0; !expander->model && i < sizeof(registered)/sizeof(struct gpio_exp_model_s); i++) {
  153. if (strcasestr(config->model, registered[i].model)) expander->model = registered + i;
  154. }
  155. // well... try again
  156. if (!expander->model) {
  157. ESP_LOGE(TAG, "Unknown GPIO expansion chip %s", config->model);
  158. return NULL;
  159. }
  160. memcpy(&expander->phy, &config->phy, sizeof(struct gpio_exp_phy_s));
  161. // try to initialize the expander if required
  162. if (expander->model->init && expander->model->init(expander) != ESP_OK) {
  163. ESP_LOGE(TAG, "Cannot create GPIO expander %s, check i2c/spi configuration", config->model);
  164. return NULL;
  165. }
  166. n_expanders++;
  167. expander->first = config->base;
  168. expander->last = config->base + config->count - 1;
  169. expander->intr = config->intr;
  170. expander->mutex = xSemaphoreCreateMutex();
  171. // create a task to handle asynchronous requests (only write at this time)
  172. if (!message_queue) {
  173. // we allocate TCB but stack is static to avoid SPIRAM fragmentation
  174. StaticTask_t* xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  175. static EXT_RAM_ATTR StackType_t xStack[4*1024] __attribute__ ((aligned (4)));
  176. message_queue = xQueueCreate(4, sizeof(queue_request_t));
  177. service_task = xTaskCreateStatic(service_handler, "gpio_expander", sizeof(xStack), NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer);
  178. }
  179. // set interrupt if possible
  180. if (config->intr >= 0) {
  181. gpio_pad_select_gpio(config->intr);
  182. gpio_set_direction(config->intr, GPIO_MODE_INPUT);
  183. switch (expander->model->trigger) {
  184. case GPIO_INTR_NEGEDGE:
  185. case GPIO_INTR_LOW_LEVEL:
  186. gpio_set_pull_mode(config->intr, GPIO_PULLUP_ONLY);
  187. break;
  188. case GPIO_INTR_POSEDGE:
  189. case GPIO_INTR_HIGH_LEVEL:
  190. gpio_set_pull_mode(config->intr, GPIO_PULLDOWN_ONLY);
  191. break;
  192. default:
  193. gpio_set_pull_mode(config->intr, GPIO_PULLUP_PULLDOWN);
  194. break;
  195. }
  196. gpio_set_intr_type(config->intr, expander->model->trigger);
  197. gpio_isr_handler_add(config->intr, intr_isr_handler, expander);
  198. gpio_intr_enable(config->intr);
  199. }
  200. ESP_LOGI(TAG, "Create GPIO expander %s at base %u with intr %d at @%x on port/host %d/%d", config->model, config->base, config->intr, config->phy.addr, config->phy.port, config->phy.host);
  201. return expander;
  202. }
  203. /******************************************************************************
  204. * Add ISR handler for a GPIO
  205. */
  206. esp_err_t gpio_exp_isr_handler_add(int gpio, gpio_isr_t isr_handler, uint32_t debounce, void *arg, struct gpio_exp_s *expander) {
  207. if (gpio < GPIO_NUM_MAX && !expander) return gpio_isr_handler_add(gpio, isr_handler, arg);
  208. if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG;
  209. expander->isr[gpio].handler = isr_handler;
  210. expander->isr[gpio].arg = arg;
  211. if (debounce) expander->isr[gpio].timer = xTimerCreate("gpioExpDebounce", pdMS_TO_TICKS(debounce),
  212. pdFALSE, expander->isr + gpio, debounce_handler );
  213. return ESP_OK;
  214. }
  215. /******************************************************************************
  216. * Remove ISR handler for a GPIO
  217. */
  218. esp_err_t gpio_exp_isr_handler_remove(int gpio, struct gpio_exp_s *expander) {
  219. if (gpio < GPIO_NUM_MAX && !expander) return gpio_isr_handler_remove(gpio);
  220. if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG;
  221. if (expander->isr[gpio].timer) xTimerDelete(expander->isr[gpio].timer, portMAX_DELAY);
  222. memset(expander->isr + gpio, 0, sizeof(struct gpio_exp_isr_s));
  223. return ESP_OK;
  224. }
  225. /******************************************************************************
  226. * Set GPIO direction
  227. */
  228. esp_err_t gpio_exp_set_direction(int gpio, gpio_mode_t mode, gpio_exp_t *expander) {
  229. if (gpio < GPIO_NUM_MAX && !expander) return gpio_set_direction(gpio, mode);
  230. if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG;
  231. xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(portMAX_DELAY));
  232. if (mode == GPIO_MODE_INPUT) {
  233. expander->r_mask |= 1 << gpio;
  234. expander->shadow = expander->model->read(expander);
  235. expander->age = ~xTaskGetTickCount();
  236. } else {
  237. expander->w_mask |= 1 << gpio;
  238. }
  239. if (expander->r_mask & expander->w_mask) {
  240. xSemaphoreGive(expander->mutex);
  241. ESP_LOGE(TAG, "GPIO %d on expander base %u can't be r/w", gpio, expander->first);
  242. return ESP_ERR_INVALID_ARG;
  243. }
  244. // most expanders want unconfigured GPIO to be set to output
  245. if (expander->model->set_direction) expander->model->set_direction(expander);
  246. xSemaphoreGive(expander->mutex);
  247. return ESP_OK;
  248. }
  249. /******************************************************************************
  250. * Get GPIO level with cache
  251. */
  252. int gpio_exp_get_level(int gpio, int age, gpio_exp_t *expander) {
  253. if (gpio < GPIO_NUM_MAX && !expander) return gpio_get_level(gpio);
  254. if ((expander = find_expander(expander, &gpio)) == NULL) return -1;
  255. uint32_t now = xTaskGetTickCount();
  256. // return last thing we had if we can't get the mutex
  257. if (xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50)) == pdFALSE) {
  258. ESP_LOGW(TAG, "Can't get mutex for GPIO %d", expander->first + gpio);
  259. return (expander->shadow >> gpio) & 0x01;
  260. }
  261. // re-read the expander if data is too old
  262. if (age >= 0 && now - expander->age >= pdMS_TO_TICKS(age)) {
  263. uint32_t value = expander->model->read(expander);
  264. expander->pending |= (expander->shadow ^ value) & expander->r_mask;
  265. expander->shadow = value;
  266. expander->age = now;
  267. }
  268. // clear pending bit
  269. expander->pending &= ~(1 << gpio);
  270. xSemaphoreGive(expander->mutex);
  271. ESP_LOGD(TAG, "Get level for GPIO %u => read %x", expander->first + gpio, expander->shadow);
  272. return (expander->shadow >> gpio) & 0x01;
  273. }
  274. /******************************************************************************
  275. * Set GPIO level with cache
  276. */
  277. esp_err_t gpio_exp_set_level(int gpio, int level, bool direct, gpio_exp_t *expander) {
  278. if (gpio < GPIO_NUM_MAX && !expander) return gpio_set_level(gpio, level);
  279. if ((expander = find_expander(expander, &gpio)) == NULL) return ESP_ERR_INVALID_ARG;
  280. uint32_t mask = 1 << gpio;
  281. // very limited risk with lack of semaphore here
  282. if ((expander->w_mask & mask) == 0) {
  283. ESP_LOGW(TAG, "GPIO %d is not set for output", expander->first + gpio);
  284. return ESP_ERR_INVALID_ARG;
  285. }
  286. if (direct) {
  287. xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(portMAX_DELAY));
  288. level = level ? mask : 0;
  289. mask &= expander->shadow;
  290. // only write if shadow not up to date
  291. if ((mask ^ level) && expander->model->write) {
  292. expander->shadow = (expander->shadow & ~(mask | level)) | level;
  293. expander->model->write(expander);
  294. }
  295. xSemaphoreGive(expander->mutex);
  296. ESP_LOGD(TAG, "Set level %x for GPIO %u => wrote %x", level, expander->first + gpio, expander->shadow);
  297. } else {
  298. queue_request_t request = { .gpio = gpio, .level = level, .type = ASYNC_WRITE, .expander = expander };
  299. if (xQueueSend(message_queue, &request, 0) == pdFALSE) return ESP_ERR_INVALID_RESPONSE;
  300. // notify service task that will write it when it can
  301. xTaskNotify(service_task, GPIO_EXP_WRITE, eSetValueWithoutOverwrite);
  302. }
  303. return ESP_OK;
  304. }
  305. /******************************************************************************
  306. * Set GPIO pullmode
  307. */
  308. esp_err_t gpio_exp_set_pull_mode(int gpio, gpio_pull_mode_t mode, gpio_exp_t *expander) {
  309. if (gpio < GPIO_NUM_MAX && !expander) return gpio_set_pull_mode(gpio, mode);
  310. if ((expander = find_expander(expander, &gpio)) != NULL && expander->model->set_pull_mode) {
  311. expander->pullup &= ~(1 << gpio);
  312. expander->pulldown &= ~(1 << gpio);
  313. if (mode == GPIO_PULLUP_ONLY || mode == GPIO_PULLUP_PULLDOWN) expander->pullup |= 1 << gpio;
  314. if (mode == GPIO_PULLDOWN_ONLY || mode == GPIO_PULLUP_PULLDOWN) expander->pulldown |= 1 << gpio;
  315. expander->model->set_pull_mode(expander);
  316. return ESP_OK;
  317. }
  318. return ESP_ERR_INVALID_ARG;
  319. }
  320. /******************************************************************************
  321. * Wrapper function
  322. */
  323. esp_err_t gpio_set_pull_mode_x(int gpio, gpio_pull_mode_t mode) {
  324. if (gpio < GPIO_NUM_MAX) return gpio_set_pull_mode(gpio, mode);
  325. return gpio_exp_set_pull_mode(gpio, mode, NULL);
  326. }
  327. esp_err_t gpio_set_direction_x(int gpio, gpio_mode_t mode) {
  328. if (gpio < GPIO_NUM_MAX) return gpio_set_direction(gpio, mode);
  329. return gpio_exp_set_direction(gpio, mode, NULL);
  330. }
  331. int gpio_get_level_x(int gpio) {
  332. if (gpio < GPIO_NUM_MAX) return gpio_get_level(gpio);
  333. return gpio_exp_get_level(gpio, 10, NULL);
  334. }
  335. esp_err_t gpio_set_level_x(int gpio, int level) {
  336. if (gpio < GPIO_NUM_MAX) return gpio_set_level(gpio, level);
  337. return gpio_exp_set_level(gpio, level, false, NULL);
  338. }
  339. esp_err_t gpio_isr_handler_add_x(int gpio, gpio_isr_t isr_handler, void* args) {
  340. if (gpio < GPIO_NUM_MAX) return gpio_isr_handler_add(gpio, isr_handler, args);
  341. return gpio_exp_isr_handler_add(gpio, isr_handler, 0, args, NULL);
  342. }
  343. esp_err_t gpio_isr_handler_remove_x(int gpio) {
  344. if (gpio < GPIO_NUM_MAX) return gpio_isr_handler_remove(gpio);
  345. return gpio_exp_isr_handler_remove(gpio, NULL);
  346. }
  347. /****************************************************************************************
  348. * INTR low-level handler
  349. */
  350. static void IRAM_ATTR intr_isr_handler(void* arg) {
  351. gpio_exp_t *self = (gpio_exp_t*) arg;
  352. BaseType_t woken = pdFALSE;
  353. // edge interrupts do not work because of read/clear = potential short pulse
  354. gpio_intr_disable(self->intr);
  355. // activate all, including ourselves
  356. for (int i = 0; i < n_expanders; i++) if (expanders[i].intr == self->intr) expanders[i].intr_pending = true;
  357. xTaskNotifyFromISR(service_task, GPIO_EXP_INTR, eSetValueWithOverwrite, &woken);
  358. if (woken) portYIELD_FROM_ISR();
  359. ESP_EARLY_LOGD(TAG, "INTR for expander base %d", gpio_exp_get_base(self));
  360. }
  361. /****************************************************************************************
  362. * INTR debounce handler
  363. */
  364. static void debounce_handler( TimerHandle_t xTimer ) {
  365. struct gpio_exp_isr_s *isr = (struct gpio_exp_isr_s*) pvTimerGetTimerID (xTimer);
  366. isr->handler(isr->arg);
  367. }
  368. /****************************************************************************************
  369. * Service task
  370. */
  371. void service_handler(void *arg) {
  372. while (1) {
  373. queue_request_t request;
  374. uint32_t notif = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  375. // we have been notified of an interrupt
  376. if (notif == GPIO_EXP_INTR) {
  377. /* If we want a smarter bitmap of expanders with a pending interrupt
  378. we'll have to disable interrupts while clearing that bitmap. For
  379. now, a loop will do */
  380. for (int i = 0; i < n_expanders; i++) {
  381. gpio_exp_t *expander = expanders + i;
  382. // no interrupt for that gpio or not pending (safe as interrupt is disabled)
  383. if (expander->intr < 0 || !expander->intr_pending) continue;
  384. xSemaphoreTake(expander->mutex, pdMS_TO_TICKS(50));
  385. // read GPIOs and clear all pending status
  386. uint32_t value = expander->model->read(expander);
  387. expander->age = xTaskGetTickCount();
  388. // re-enable interrupt now that it has been cleared
  389. expander->intr_pending = false;
  390. gpio_intr_enable(expander->intr);
  391. uint32_t pending = expander->pending | ((expander->shadow ^ value) & expander->r_mask);
  392. expander->shadow = value;
  393. expander->pending = 0;
  394. xSemaphoreGive(expander->mutex);
  395. ESP_LOGD(TAG, "Handling GPIO %d reads 0x%04x and has 0x%04x pending", expander->first, expander->shadow, pending);
  396. for (int gpio = 31, clz = 0; pending && clz < 31; pending <<= (clz + 1)) {
  397. clz = __builtin_clz(pending);
  398. gpio -= clz;
  399. if (expander->isr[gpio].timer) xTimerReset(expander->isr[gpio].timer, 1); // todo 0
  400. else if (expander->isr[gpio].handler) expander->isr[gpio].handler(expander->isr[gpio].arg);
  401. }
  402. }
  403. }
  404. // check if we have some other pending requests
  405. while (xQueueReceive(message_queue, &request, 0) == pdTRUE) {
  406. esp_err_t err = gpio_exp_set_level(request.gpio, request.level, true, request.expander);
  407. if (err != ESP_OK) ESP_LOGW(TAG, "Can't execute async GPIO %d write request (%d)", request.gpio, err);
  408. }
  409. }
  410. }
  411. /****************************************************************************************
  412. * Find the expander related to base
  413. */
  414. static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio) {
  415. // a mutex would be better, but risk is so small...
  416. for (int i = 0; !expander && i < n_expanders; i++) {
  417. if (*gpio >= expanders[i].first && *gpio <= expanders[i].last) expander = expanders + i;
  418. }
  419. // normalize GPIO number
  420. if (expander && *gpio >= expander->first) *gpio -= expander->first;
  421. return expander;
  422. }
  423. /****************************************************************************************
  424. DRIVERS
  425. ****************************************************************************************/
  426. /****************************************************************************************
  427. * MPR121 family : init, direction, read and write
  428. */
  429. static esp_err_t mpr121_init(gpio_exp_t* self) {
  430. static const struct {
  431. uint8_t addr;
  432. uint8_t data;
  433. } mpr121_init_table[] = {
  434. { 0x80, 0x63 }, /* Soft reset */
  435. { 0x2b, 0x01 }, { 0x2c, 0x01 }, { 0x2d, 0x10 }, { 0x2e, 0x20 }, /* MHDR, NHDR, NCLR, FDLR */
  436. { 0x2f, 0x01 }, { 0x30, 0x01 }, { 0x31, 0x10 }, { 0x32, 0x20 }, /* MHDF, NHDF, NCLF, FDLF */
  437. { 0x33, 0x01 }, { 0x34, 0x10 }, { 0x35, 0xff }, /* NHDT, NCLT, FDLT */
  438. { 0x5b, 0x11 }, { 0x5c, 0xff }, { 0x5d, 0x30 }, /* DTR, AFE1, AFE2 */
  439. { 0x7b, 0x00 }, { 0x7c, 0x00 }, { 0x7d, 0x00 }, { 0x7e, 0x00 }, { 0x7f, 0x00 },/* ACCR0, ACCR1, USL, LSL, TL */
  440. { 0x41, 0x28 }, { 0x42, 0x14 }, /* ELE0: Touch Threshold, Release Threshold */
  441. { 0x43, 0x28 }, { 0x44, 0x14 }, /* ELE1: Touch Threshold, Release Threshold */
  442. { 0x45, 0x28 }, { 0x46, 0x14 }, /* ELE2: Touch Threshold, Release Threshold */
  443. { 0x47, 0x28 }, { 0x48, 0x14 }, /* ELE3: Touch Threshold, Release Threshold */
  444. { 0x49, 0x28 }, { 0x4a, 0x14 }, /* ELE4: Touch Threshold, Release Threshold */
  445. { 0x4b, 0x28 }, { 0x4c, 0x14 }, /* ELE5: Touch Threshold, Release Threshold */
  446. { 0x4d, 0x28 }, { 0x4e, 0x14 }, /* ELE6: Touch Threshold, Release Threshold */
  447. { 0x4f, 0x28 }, { 0x50, 0x14 }, /* ELE7: Touch Threshold, Release Threshold */
  448. { 0x51, 0x28 }, { 0x52, 0x14 }, /* ELE8: Touch Threshold, Release Threshold */
  449. { 0x53, 0x28 }, { 0x54, 0x14 }, /* ELE9: Touch Threshold, Release Threshold */
  450. { 0x55, 0x28 }, { 0x56, 0x14 }, /* ELE10: Touch Threshold, Release Threshold */
  451. { 0x57, 0x28 }, { 0x58, 0x14 }, /* ELE11: Touch Threshold, Release Threshold */
  452. { 0x5e, 0xcc }, /* ECR - must be set last */
  453. { 0, 0 }
  454. };
  455. esp_err_t err = 0;
  456. for (int i = 0; mpr121_init_table[i].addr; i++) {
  457. err |= i2c_write(self->phy.port, self->phy.addr, mpr121_init_table[i].addr, mpr121_init_table[i].data, 1);
  458. }
  459. return err;
  460. }
  461. static uint32_t mpr121_read(gpio_exp_t* self) {
  462. // only return the lower 12 bits of the pin status registers
  463. return i2c_read(self->phy.port, self->phy.addr, 0x00, 2) & 0x0fff;
  464. }
  465. static void mpr121_write(gpio_exp_t* self) {
  466. ESP_LOGE(TAG, "MPR121 GPIO write not implemented");
  467. }
  468. /****************************************************************************************
  469. * PCA9535 family : direction, read and write
  470. */
  471. static void pca9535_set_direction(gpio_exp_t* self) {
  472. i2c_write(self->phy.port, self->phy.addr, 0x06, self->r_mask, 2);
  473. }
  474. static uint32_t pca9535_read(gpio_exp_t* self) {
  475. return i2c_read(self->phy.port, self->phy.addr, 0x00, 2);
  476. }
  477. static void pca9535_write(gpio_exp_t* self) {
  478. i2c_write(self->phy.port, self->phy.addr, 0x02, self->shadow, 2);
  479. }
  480. /****************************************************************************************
  481. * PCA85xx family : read and write
  482. */
  483. static uint32_t pca85xx_read(gpio_exp_t* self) {
  484. // must return the full set of pins, not just inputs
  485. uint32_t data = i2c_read(self->phy.port, self->phy.addr, 0xff, 2);
  486. return (data & self->r_mask) | (self->shadow & ~self->r_mask);
  487. }
  488. static void pca85xx_write(gpio_exp_t* self) {
  489. /*
  490. There is no good option with this chip: normally, unused pin should be set to input
  491. to avoid any conflict but then they float and create tons of suprious. So option 1 is
  492. to le tthem float and option 2 is to set them as output to 0.
  493. In addition, setting an output pin to 1 equals is making it an input and if this is
  494. use to short a led (e.g.) instead of being the sink, the it generates a spurious
  495. */
  496. // option 1
  497. // i2c_write(self->phy.port, self->phy.addr, 0xff, (self->shadow & self->w_mask) | ~self->w_mask, 2);
  498. // option 2
  499. i2c_write(self->phy.port, self->phy.addr, 0xff, (self->shadow & self->w_mask) | self->r_mask, 2);
  500. }
  501. /****************************************************************************************
  502. * MCP23017 family : init, direction, read and write
  503. */
  504. static esp_err_t mcp23017_init(gpio_exp_t* self) {
  505. /*
  506. 0111 x10x = same bank, mirrot single int, no sequentµial, open drain, active low
  507. not sure about this funny change of mapping of the control register itself, really?
  508. */
  509. esp_err_t err = i2c_write(self->phy.port, self->phy.addr, 0x05, 0x74, 1);
  510. err |= i2c_write(self->phy.port, self->phy.addr, 0x0a, 0x74, 1);
  511. // no interrupt on comparison or on change
  512. err |= i2c_write(self->phy.port, self->phy.addr, 0x04, 0x00, 2);
  513. err |= i2c_write(self->phy.port, self->phy.addr, 0x08, 0x00, 2);
  514. return err;
  515. }
  516. static void mcp23017_set_direction(gpio_exp_t* self) {
  517. // default to input and set real input to generate interrupt
  518. i2c_write(self->phy.port, self->phy.addr, 0x00, ~self->w_mask, 2);
  519. i2c_write(self->phy.port, self->phy.addr, 0x04, self->r_mask, 2);
  520. }
  521. static void mcp23017_set_pull_mode(gpio_exp_t* self) {
  522. i2c_write(self->phy.port, self->phy.addr, 0x0c, self->pullup, 2);
  523. }
  524. static uint32_t mcp23017_read(gpio_exp_t* self) {
  525. // read the pins value, not the stored one @interrupt
  526. return i2c_read(self->phy.port, self->phy.addr, 0x12, 2);
  527. }
  528. static void mcp23017_write(gpio_exp_t* self) {
  529. i2c_write(self->phy.port, self->phy.addr, 0x12, self->shadow, 2);
  530. }
  531. /****************************************************************************************
  532. * MCP23s17 family : init, direction, read and write
  533. */
  534. static esp_err_t mcp23s17_init(gpio_exp_t* self) {
  535. if ((self->spi_handle = spi_config(&self->phy)) == NULL) return ESP_ERR_INVALID_ARG;
  536. /*
  537. 0111 x10x = same bank, mirrot single int, no sequentµial, open drain, active low
  538. not sure about this funny change of mapping of the control register itself, really?
  539. */
  540. esp_err_t err = spi_write(self->spi_handle, self->phy.addr, 0x05, 0x74, 1);
  541. err |= spi_write(self->spi_handle, self->phy.addr, 0x0a, 0x74, 1);
  542. // no interrupt on comparison or on change
  543. err |= spi_write(self->spi_handle, self->phy.addr, 0x04, 0x00, 2);
  544. err |= spi_write(self->spi_handle, self->phy.addr, 0x08, 0x00, 2);
  545. return err;
  546. }
  547. static void mcp23s17_set_direction(gpio_exp_t* self) {
  548. // default to input and set real input to generate interrupt
  549. spi_write(self->spi_handle, self->phy.addr, 0x00, ~self->w_mask, 2);
  550. spi_write(self->spi_handle, self->phy.addr, 0x04, self->r_mask, 2);
  551. }
  552. static void mcp23s17_set_pull_mode(gpio_exp_t* self) {
  553. spi_write(self->spi_handle, self->phy.addr, 0x0c, self->pullup, 2);
  554. }
  555. static uint32_t mcp23s17_read(gpio_exp_t* self) {
  556. // read the pins value, not the stored one @interrupt
  557. return spi_read(self->spi_handle, self->phy.addr, 0x12, 2);
  558. }
  559. static void mcp23s17_write(gpio_exp_t* self) {
  560. spi_write(self->spi_handle, self->phy.addr, 0x12, self->shadow, 2);
  561. }
  562. /****************************************************************************************
  563. * AW9523 family : direction, read and write
  564. */
  565. static void aw9523_set_direction(gpio_exp_t* self) {
  566. i2c_write(self->phy.port, self->phy.addr, 0x04, self->r_mask, 2);
  567. i2c_write(self->phy.port, self->phy.addr, 0x06, ~self->r_mask, 2);
  568. }
  569. static uint32_t aw9523_read(gpio_exp_t* self) {
  570. // Reading both registers in one go does not seem to reset IRQ correctly
  571. uint8_t port1 = i2c_read(self->phy.port, self->phy.addr, 0x00, 1);
  572. return (i2c_read(self->phy.port, self->phy.addr, 0x01, 1) << 8) | port1;
  573. }
  574. static void aw9523_write(gpio_exp_t* self) {
  575. i2c_write(self->phy.port, self->phy.addr, 0x02, self->shadow, 2);
  576. }
  577. /***************************************************************************************
  578. I2C low level
  579. ***************************************************************************************/
  580. /****************************************************************************************
  581. * I2C write up to 32 bits
  582. */
  583. static esp_err_t i2c_write(uint8_t port, uint8_t addr, uint8_t reg, uint32_t data, int len) {
  584. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  585. i2c_master_start(cmd);
  586. i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
  587. if (reg != 0xff) i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
  588. // works with our endianness
  589. if (len > 1) i2c_master_write(cmd, (uint8_t*) &data, len, I2C_MASTER_NACK);
  590. else i2c_master_write_byte(cmd, data, I2C_MASTER_NACK);
  591. i2c_master_stop(cmd);
  592. esp_err_t ret = i2c_master_cmd_begin(port, cmd, 100 / portTICK_RATE_MS);
  593. i2c_cmd_link_delete(cmd);
  594. if (ret != ESP_OK) {
  595. ESP_LOGW(TAG, "I2C write failed");
  596. }
  597. return ret;
  598. }
  599. /****************************************************************************************
  600. * I2C read up to 32 bits
  601. */
  602. static uint32_t i2c_read(uint8_t port, uint8_t addr, uint8_t reg, int len) {
  603. uint32_t data = 0;
  604. i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  605. i2c_master_start(cmd);
  606. // when using a register, write it's value then the device address again
  607. if (reg != 0xff) {
  608. i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, I2C_MASTER_NACK);
  609. i2c_master_write_byte(cmd, reg, I2C_MASTER_NACK);
  610. i2c_master_start(cmd);
  611. i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK);
  612. } else {
  613. i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_READ, I2C_MASTER_NACK);
  614. }
  615. // works with our endianness
  616. if (len > 1) i2c_master_read(cmd, (uint8_t*) &data, len, I2C_MASTER_LAST_NACK);
  617. else i2c_master_read_byte(cmd, (uint8_t*) &data, I2C_MASTER_NACK);
  618. i2c_master_stop(cmd);
  619. esp_err_t ret = i2c_master_cmd_begin(port, cmd, 100 / portTICK_RATE_MS);
  620. i2c_cmd_link_delete(cmd);
  621. if (ret != ESP_OK) {
  622. ESP_LOGW(TAG, "I2C read failed");
  623. }
  624. return data;
  625. }
  626. /***************************************************************************************
  627. SPI low level
  628. ***************************************************************************************/
  629. /****************************************************************************************
  630. * SPI device addition
  631. */
  632. static spi_device_handle_t spi_config(struct gpio_exp_phy_s *phy) {
  633. spi_device_interface_config_t config = { };
  634. spi_device_handle_t handle = NULL;
  635. config.command_bits = config.address_bits = 8;
  636. config.clock_speed_hz = phy->speed ? phy->speed : SPI_MASTER_FREQ_8M;
  637. config.spics_io_num = phy->cs_pin;
  638. config.queue_size = 1;
  639. config.flags = SPI_DEVICE_NO_DUMMY;
  640. spi_bus_add_device( phy->host, &config, &handle );
  641. ESP_LOGI(TAG, "SPI expander initialized on host:%d with cs:%d and speed:%dHz", phy->host, phy->cs_pin, config.clock_speed_hz);
  642. return handle;
  643. }
  644. /****************************************************************************************
  645. * SPI write up to 32 bits
  646. */
  647. static esp_err_t spi_write(spi_device_handle_t handle, uint8_t addr, uint8_t reg, uint32_t data, int len) {
  648. spi_transaction_t transaction = { };
  649. // rx_buffer is NULL, nothing to receive
  650. transaction.flags = SPI_TRANS_USE_TXDATA;
  651. transaction.cmd = addr << 1;
  652. transaction.addr = reg;
  653. transaction.tx_data[0] = data; transaction.tx_data[1] = data >> 8;
  654. transaction.length = len * 8;
  655. // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
  656. return spi_device_polling_transmit(handle, &transaction);
  657. }
  658. /****************************************************************************************
  659. * SPI read up to 32 bits
  660. */
  661. static uint32_t spi_read(spi_device_handle_t handle, uint8_t addr, uint8_t reg, int len) {
  662. spi_transaction_t *transaction = heap_caps_calloc(1, sizeof(spi_transaction_t), MALLOC_CAP_DMA);
  663. // tx_buffer is NULL, nothing to transmit except cmd/addr
  664. transaction->flags = SPI_TRANS_USE_RXDATA;
  665. transaction->cmd = (addr << 1) | 0x01;
  666. transaction->addr = reg;
  667. transaction->length = len * 8;
  668. // only do polling as we don't have contention on SPI (otherwise DMA for transfers > 16 bytes)
  669. spi_device_polling_transmit(handle, transaction);
  670. uint32_t data = *(uint32_t*) transaction->rx_data;
  671. free(transaction);
  672. return data;
  673. }