diff --git a/include/main.h b/include/main.h index c0f1319..125e513 100644 --- a/include/main.h +++ b/include/main.h @@ -5,9 +5,8 @@ #define PUMP_COUNT (4) -extern uint8_t mac[6]; -static uint8_t pump_gpio_map[] = { 27, 26, 25, 23 }; +static xQueueHandle gpio_evt_queue = NULL; -#define GPIO_PUMP_PIN_SEL ((1ULL<chr->uuid); - - ESP_LOGI(TAG, "0x%02X (%d) access: %d", uuid16, uuid16, ctxt->op); - uint8_t value = 0; - gatt_svr_chr_write( - ctxt->om, - sizeof value, - sizeof value, - &value, NULL - ); + ESP_LOGI(TAG, "0x%02X access: %d", uuid16, ctxt->op); - uint8_t io = pump_gpio_map[uuid16 - 0x4201]; + if(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { + } else if(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + gatt_svr_chr_write( + ctxt->om, + sizeof value, + sizeof value, + &value, NULL + ); - ESP_LOGI(TAG, "gpio: %d value: %d", io, value); - ESP_LOGI(TAG, "idx: %d", uuid16 - 4201); + switch(uuid16) { + case CHAR_POUR: + if(value == 1) { + ESP_LOGI(TAG, "starting pump"); + pumps_run(); + } else { + pumps_stop(); + } + break; - gpio_set_level(io, value); + case CHAR_BUTTON: + break; + } + } + + return 0; +} + +static int svc_access_pump_enabled(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid); + uint8_t value = 0; + + ESP_LOGI(TAG, "0x%02X access: %d", uuid16, ctxt->op); + + uint8_t idx = uuid16 - (BLE_SERVICE_PUMP_ENABLED + 1); + + if(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + gatt_svr_chr_write( + ctxt->om, + sizeof value, + sizeof value, + &value, NULL + ); + + pumps_set_enabled(idx, value); + } else if(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { + uint8_t enabled = pumps_get_enabled(idx); + + ESP_LOGI(TAG, "pumps_enabled[%d] = %d", idx, enabled); + os_mbuf_append(ctxt->om, &enabled, sizeof enabled); + } + + return 0; +} + +static int svc_access_pump_duration(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { + uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid); + uint8_t idx = uuid16 - (BLE_SERVICE_PUMP_DURATION + 1); + uint8_t value = 0; + + ESP_LOGI(TAG, "0x%02X access: %d", uuid16, ctxt->op); + + if(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + gatt_svr_chr_write( + ctxt->om, + sizeof value, + sizeof value, + &value, NULL + ); + + pumps_set_time(idx, value); + } else if(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { + uint8_t duration = pumps_get_time(idx); + + ESP_LOGI(TAG, "pumps_duration[%d] = %d", idx, duration); + os_mbuf_append(ctxt->om, &duration, sizeof duration); + } return 0; } static int svc_access_pump_state(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid); + uint8_t idx = uuid16 - (BLE_SERVICE_PUMP_ENABLED + 1); if(ctxt->op != BLE_GATT_ACCESS_OP_READ_CHR) { - ESP_LOGW(TAG, "attempting non-read op on write only characteristics"); + ESP_LOGW(TAG, "attempting non-read op on read only characteristics"); return 1; } @@ -139,22 +247,6 @@ static int svc_access_pump_state(uint16_t conn_handle, uint16_t attr_handle, str return 0; } -static int ble_svc_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid); - - esp_err_t err = ble_gatts_count_cfg(service_defs); - - ESP_LOGI(TAG, "0x%02X access: %d", uuid16, ctxt->op); - - switch(uuid16) { - case 0x2901: - os_mbuf_append(ctxt->om, "hello", 5); - break; - } - - return 0; -} - static void ble_advertise(void) { struct ble_gap_adv_params adv_params; struct ble_hs_adv_fields fields; @@ -242,6 +334,7 @@ static int ble_gap_event(struct ble_gap_event *event, void *arg) { break; case BLE_GAP_EVENT_SUBSCRIBE: + /* ESP_LOGI(TAG, "handling BLE_GAP_EVENT_SUBSCRIBE"); ESP_LOGI(TAG, "attr_handle: %d", event->subscribe.attr_handle); ESP_LOGI(TAG, "callback_handler_count: %d", callback_handler_count); @@ -256,6 +349,7 @@ static int ble_gap_event(struct ble_gap_event *event, void *arg) { } } break; + */ case BLE_GAP_EVENT_CONN_UPDATE: ESP_LOGI(TAG, "BLE_GAP_EVENT_CONN_UPDATE, conn_handle: %d status: %d", diff --git a/main/main.c b/main/main.c index 38a202c..4f79209 100644 --- a/main/main.c +++ b/main/main.c @@ -4,7 +4,6 @@ #include "freertos/task.h" #include "freertos/queue.h" #include "driver/uart.h" -#include "driver/gpio.h" #include "esp_log.h" #include "esp_debug_helpers.h" #include "nvs_flash.h" @@ -14,12 +13,14 @@ #include "console.h" #include "ble.h" #include "user_button.h" +#include "pumps.h" static const char *TAG = "BARBACK"; uint8_t mac[6]; void app_main(void) { +/* esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); @@ -27,33 +28,23 @@ void app_main(void) { } ESP_ERROR_CHECK( err ); - nvs_handle_t nvs_handle; - err = nvs_open("config", NVS_READWRITE, &nvs_handle); + err = nvs_open("config", NVS_READWRITE, &config_handle); if (err != ESP_OK) { printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err)); } else { - ESP_LOGI(TAG, "nvs_handle: %d", nvs_handle); + ESP_LOGI(TAG, "config_handle: %d", config_handle); } +*/ esp_efuse_mac_get_default((uint8_t*)&mac); ESP_LOGI(TAG, "MAC: [%02X:%02X:%02X:%02X:%02X:%02X]", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - xTaskCreate(console_task, "console", 4048, NULL, tskIDLE_PRIORITY + 3, NULL); - + user_button_init(); + pumps_init(); ble_init(); -#ifdef CONFIG_LORCOMM_BUTTON_ACTION_ENABLED - //user_button_init(); -#endif - - gpio_config_t io_conf; - io_conf.intr_type = GPIO_PIN_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = GPIO_PUMP_PIN_SEL; - io_conf.pull_down_en = 1; - io_conf.pull_up_en = 0; - gpio_config(&io_conf); + xTaskCreate(console_task, "console", 4048, NULL, tskIDLE_PRIORITY + 3, NULL); while(1) { vTaskDelay(1000 / portTICK_PERIOD_MS); diff --git a/main/pumps.c b/main/pumps.c new file mode 100644 index 0000000..0fe77bf --- /dev/null +++ b/main/pumps.c @@ -0,0 +1,118 @@ +#include "string.h" +#include "freertos/FreeRTOS.h" +#include "freertos/timers.h" +#include "esp_log.h" +#include "driver/gpio.h" +#include "nvs_flash.h" + +#include "pumps.h" + +#define TAG "PUMP!" + +uint8_t running = 0; + +TimerHandle_t pump_timers[PUMPS]; +static uint8_t pumps_duration[PUMPS] = {0}; +static uint8_t pumps_enabled[PUMPS] = {0}; +static uint8_t pumps_state[PUMPS]; +static uint8_t safety = 1; + +uint8_t pumps_set_time(uint8_t idx, uint8_t time) { + if(idx > PUMPS) return PUMPS_ERR_OUT_IDX; + + ESP_LOGI(TAG, "duration update: %d = %d", idx, time); + + pumps_duration[idx] = time; + + return 0; +} + +uint8_t pumps_set_enabled(uint8_t idx, uint8_t value) { + uint8_t io = pump_gpio_map[idx]; + + value = (value ? 1 : 0); + + ESP_LOGD(TAG, "gpio: %d value: %d", io, value); + // invert IO + if(safety) + gpio_set_level(io, value); + + return pumps_enabled[idx] = value; +} + +uint8_t pumps_get_enabled(uint8_t idx) { + return pumps_enabled[idx] ? 1 : 0; +} + +uint8_t pumps_get_time(uint8_t idx) { + return pumps_duration[idx]; +} + +uint8_t pump_enable(int8_t i) { + return gpio_set_level(pump_gpio_map[i], 0); +} + +uint8_t pump_disable(int8_t i) { + return gpio_set_level(pump_gpio_map[i], 0); +} + +void pump_timer_done(TimerHandle_t timer) { + uint8_t idx = (pcTimerGetTimerName(timer) - 0x48); + ESP_LOGD(TAG, "pump done: %d", idx); + + running--; + + pumps_set_enabled(idx, 0); +} + +void pumps_stop() { + for(uint8_t i = 0; i < PUMPS; i++) { + if(pump_timers[i] != NULL) + xTimerStop(pump_timers[i], 0); + } +} + +void pumps_run() { + if(running > 0) return; + + for(uint8_t i = 0; i < PUMPS; i++) { + if(pumps_duration[i] == 0) continue; + + running++; + + pump_timers[i] = xTimerCreate((const char *)(0x48 + i), (pumps_duration[i] * 1000 / portTICK_PERIOD_MS), pdFALSE, (void*)0, pump_timer_done); + + xTimerStart(pump_timers[i], 0); + + pumps_set_enabled(i, 1); + } +} + +uint8_t pumps_init() { + gpio_config_t io_conf; + + // put the output high before initializing + // to prevent relays from clacking + for(uint8_t i = 0 ; i < 4; i++) { + gpio_set_level(pump_gpio_map[i], 0); + } + + io_conf.intr_type = GPIO_PIN_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = GPIO_PUMP_PIN_SEL; + io_conf.pull_down_en = 1; + io_conf.pull_up_en = 0; + gpio_config(&io_conf); + + // zero out pump enabled, duration + memset(&pumps_enabled, 0, sizeof(uint8_t) * PUMPS); + memset(&pumps_duration, 10, sizeof(uint8_t) * PUMPS); + + //uint32_t durations; + //esp_err_t err = nvs_get_i32(config_handle, "durations", &durations); + + ESP_LOGI(TAG, "pumps_enabled: %d %d %d %d", pumps_enabled[0], pumps_enabled[1], pumps_enabled[2], pumps_enabled[3]); + ESP_LOGI(TAG, "pumps_duration: %d %d %d %d", pumps_duration[0], pumps_duration[1], pumps_duration[2], pumps_duration[3]); + + return 0; +} diff --git a/main/user_button.c b/main/user_button.c index 119392e..b0cf5ec 100644 --- a/main/user_button.c +++ b/main/user_button.c @@ -3,37 +3,45 @@ #include "freertos/queue.h" #include "driver/gpio.h" -static xQueueHandle gpio_evt_queue = NULL; +#include "main.h" +#include "pumps.h" -static void IRAM_ATTR gpio_isr_handler(void* arg) -{ - uint32_t gpio_num = (uint32_t) arg; - xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); +#define GPIO_USER_BUTTON (19) + +static void IRAM_ATTR gpio_isr_handler(void* arg) { + uint32_t gpio_num = (uint32_t) arg; + + xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); } static void gpio_task_example(void* arg) { - uint32_t io_num; - for(;;) { - if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { - printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num)); - } + uint32_t io_num; + + for(;;) { + if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { + printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num)); + + pumps_run(); + // just a wee debounce + vTaskDelay(500 / portTICK_PERIOD_MS); } + } } void user_button_init() { - gpio_config_t io_conf; + gpio_config_t io_conf; - io_conf.intr_type = GPIO_PIN_INTR_NEGEDGE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1L << 0); - io_conf.pull_down_en = 0; - io_conf.pull_up_en = 0; + io_conf.intr_type = GPIO_PIN_INTR_NEGEDGE; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pin_bit_mask = (1ULL << GPIO_USER_BUTTON); + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 1; - gpio_config(&io_conf); + gpio_config(&io_conf); - gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); - xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL); + gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); + xTaskCreate(gpio_task_example, "gpio_task_example", 4096, NULL, 10, NULL); - gpio_install_isr_service(0); - gpio_isr_handler_add(0, gpio_isr_handler, (void*) 0); + gpio_install_isr_service(0); + gpio_isr_handler_add(GPIO_USER_BUTTON, gpio_isr_handler, (void*) 0); }