src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/c_cpp_properties.json1
-rw-r--r--.vscode/settings.json11
-rw-r--r--README.md8
-rw-r--r--main/Kconfig.projbuild35
-rw-r--r--main/app_main.c13
-rw-r--r--main/include/bell.h10
-rw-r--r--main/include/led.h2
-rw-r--r--main/include/lock.h4
-rw-r--r--main/src/bell.c110
-rw-r--r--main/src/led.c15
-rw-r--r--main/src/lock.c27
11 files changed, 138 insertions, 98 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 9033567..516e65a 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -5,7 +5,6 @@
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "macos-gcc-x64",
- "compileCommands": "${workspaceFolder}/build/compile_commands.json",
"includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPath}/../esp-homekit-sdk/components/**",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8ccd8ea..09ca793 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -11,8 +11,15 @@
"files.associations": {
"stdio.h": "c",
"hap.h": "c",
- "freertos.h": "c"
+ "freertos.h": "c",
+ "intercom.h": "c",
+ "bell.h": "c",
+ "hap_apple_servs.h": "c",
+ "hap_apple_chars.h": "c",
+ "adc.h": "c"
},
"git.ignoreLimitWarning": true,
- "cmake.configureOnOpen": false
+ "cmake.configureOnOpen": false,
+ "idf.port": "/dev/cu.usbserial-01D93418",
+ "idf.flashType": "UART"
} \ No newline at end of file
diff --git a/README.md b/README.md
index 0959a02..dbcf294 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,7 @@ only measured by the ADC.
- r1 = 100kO
- r2 = 10kO + 2.2kO
+- 1.85V seems to be where high goes to low. - Probably remove the 2.2kO resister.
## Partition Sizing
@@ -62,9 +63,10 @@ phy_init, data, phy, , 0x1000,
factory, app, factory, , 0x180000, # Change from 1M to 0x180000
```
-
## Doorbell ADC Output
+An ESP32 GPIO pin cannot bt used for both interrupts and ADC sampling at the same time so two adjacent GPIO pins are bridged to take the same voltage, one for interrupt handling and the other to read the ADC.
+
```I (65813) HAP Intercom: Intercom bell ring value in range [2960]
I (66813) HAP Intercom: Intercom bell ring value in range [2966]
I (67813) HAP Intercom: Intercom bell ring value in range [2957]
@@ -96,3 +98,7 @@ I (92813) HAP Intercom: Intercom bell ring value in range [2959]
I (93813) HAP Intercom: Intercom bell ring value in range [2951]
I (94813) HAP Intercom: Intercom bell ring value in range [2949]
```
+
+## Building
+
+Use the [Espressif esp-ide](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html#step-2-get-esp-idf) to build. This also includes a custom fork of the [Espressif HAP SDK](https://github.com/espressif/esp-homekit-sdk) that adds HomeKit doorbell support. \ No newline at end of file
diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild
index 5230dca..2b74fc2 100644
--- a/main/Kconfig.projbuild
+++ b/main/Kconfig.projbuild
@@ -29,39 +29,4 @@ menu "HomeKit Intercom Configuration"
help
Milliseconds before locking intercom
- config HOMEKIT_INTERCOM_LOCK_GPIO_PIN
- int "Intercom lock GPIO pin number"
- range 0 39
- default 21
- help
- GPIO pin number to control lock relay.
-
- config HOMEKIT_INTERCOM_BELL_GPIO_PIN
- int "Intercom bell GPIO pin number"
- range 0 39
- default 33
- help
- GPIO pin number from which to read intercom bell signal.
-
- config HOMEKIT_INTERCOM_BELL_ADC1_CHANNEL
- int "Intercom bell ADC1 channel number"
- range 0 7
- default 5
- help
- ADC1 channel number from which to read intercom bell signal.
-
- config HOMEKIT_INTERCOM_WIFI_RESET_GPIO_PIN
- int "Intercom WIFI reset GPIO pin number"
- range 0 39
- default 0
- help
- GPIO pin number to reset wifi.
-
- config HOMEKIT_INTERCOM_LED_GPIO_PIN
- int "LED GPIO pin number"
- range 0 39
- default 13
- help
- GPIO pin number for LED.
-
endmenu
diff --git a/main/app_main.c b/main/app_main.c
index e1d42b4..bfd4d4f 100644
--- a/main/app_main.c
+++ b/main/app_main.c
@@ -14,7 +14,7 @@
#define INTERCOM_TASK_STACKSIZE 4 * 1024
#define INTERCOM_TASK_NAME "hap_intercom"
-static void intercom_thread_entry(void *p)
+static void intercom_init(void *p)
{
hap_init(HAP_TRANSPORT_WIFI); /* Initialize the HAP core */
@@ -30,16 +30,13 @@ static void intercom_thread_entry(void *p)
.cid = HAP_CID_DOOR,
};
- ESP_LOGI(TAG, "GPIO Pins [BELL: %d, ADC1: %d, LOCK: %d, LED: %d]", CONFIG_HOMEKIT_INTERCOM_BELL_GPIO_PIN, CONFIG_HOMEKIT_INTERCOM_BELL_ADC1_CHANNEL, CONFIG_HOMEKIT_INTERCOM_LOCK_GPIO_PIN, CONFIG_HOMEKIT_INTERCOM_LED_GPIO_PIN);
-
hap_acc_t *intercom_accessory = hap_acc_create(&cfg);
- /* Add a dummy Product Data */
uint8_t product_data[] = {'E', 'S', 'P', '3', '2', 'H', 'A', 'P'};
hap_acc_add_product_data(intercom_accessory, product_data, sizeof(product_data));
- hap_acc_add_serv(intercom_accessory, intercom_bell_init(CONFIG_HOMEKIT_INTERCOM_BELL_GPIO_PIN));
- hap_acc_add_serv(intercom_accessory, intercom_lock_init(CONFIG_HOMEKIT_INTERCOM_LOCK_GPIO_PIN));
- intercom_led_init(CONFIG_HOMEKIT_INTERCOM_LED_GPIO_PIN);
+ hap_acc_add_serv(intercom_accessory, intercom_bell_init());
+ hap_acc_add_serv(intercom_accessory, intercom_lock_init());
+ intercom_led_init();
hap_add_accessory(intercom_accessory); /* Add the Accessory to the HomeKit Database */
@@ -80,5 +77,5 @@ static void intercom_thread_entry(void *p)
void app_main()
{
- xTaskCreate(intercom_thread_entry, INTERCOM_TASK_NAME, INTERCOM_TASK_STACKSIZE, NULL, INTERCOM_TASK_PRIORITY, NULL);
+ xTaskCreate(intercom_init, INTERCOM_TASK_NAME, INTERCOM_TASK_STACKSIZE, NULL, INTERCOM_TASK_PRIORITY, NULL);
}
diff --git a/main/include/bell.h b/main/include/bell.h
index 35a618e..41f133a 100644
--- a/main/include/bell.h
+++ b/main/include/bell.h
@@ -4,10 +4,14 @@
bool is_bell_ringing(int val);
-void IRAM_ATTR intercom_bell_isr(void *arg);
+void intercom_bell_read(void *p);
-void intercom_bell_ring();
+void IRAM_ATTR intercom_bell_isr(void *arg);
void intercom_bell_timer_cb(TimerHandle_t timer);
-hap_serv_t *intercom_bell_init(uint32_t key_gpio_pin);
+void intercom_bell_isr_gpio_init();
+
+void intercom_bell_adc_gpio_init();
+
+hap_serv_t *intercom_bell_init();
diff --git a/main/include/led.h b/main/include/led.h
index 98248e6..ea10f58 100644
--- a/main/include/led.h
+++ b/main/include/led.h
@@ -2,4 +2,4 @@
int intercom_led_identify(hap_acc_t *ha);
-void intercom_led_init(uint32_t key_gpio_pin); \ No newline at end of file
+void intercom_led_init(); \ No newline at end of file
diff --git a/main/include/lock.h b/main/include/lock.h
index d26a222..aca9b67 100644
--- a/main/include/lock.h
+++ b/main/include/lock.h
@@ -12,4 +12,6 @@ int intercom_lock_write_cb(hap_write_data_t write_data[], int count, void *serv_
void intercom_lock_timer_cb(TimerHandle_t timer);
-hap_serv_t *intercom_lock_init(uint32_t key_gpio_pin);
+void intercom_lock_gpio_init();
+
+hap_serv_t *intercom_lock_init();
diff --git a/main/src/bell.c b/main/src/bell.c
index 985ca4e..730d031 100644
--- a/main/src/bell.c
+++ b/main/src/bell.c
@@ -1,8 +1,11 @@
#include <freertos/FreeRTOS.h>
#include <freertos/timers.h>
+#include <freertos/task.h>
+#include <freertos/portmacro.h>
#include <esp_log.h>
#include <driver/gpio.h>
#include <driver/adc.h>
+#include <soc/adc_channel.h>
#include <hap.h>
#include <hap_apple_servs.h>
#include <hap_apple_chars.h>
@@ -12,30 +15,64 @@
static hap_val_t HAP_PROGRAMMABLE_SWITCH_EVENT_SINGLE_PRESS = {.u = 0};
+#define INTERCOM_BELL_TASK_PRIORITY 1
+#define INTERCOM_BELL_TASK_STACKSIZE 4 * 1024
+#define INTERCOM_BELL_TASK_NAME "hap_intercom_bell"
+
+static TaskHandle_t intercom_bell_read_task;
+
volatile bool is_intercom_bell_blocked;
static TimerHandle_t intercom_bell_timer; // ignore new bells until timer triggered
static hap_char_t *intercom_bell_current_state;
bool is_bell_ringing(int val)
{
+ ESP_LOGI(TAG, "Intercom bell rang with value %d", val);
return 2340 < val && val < 2360;
}
-
-void IRAM_ATTR intercom_bell_isr(void *arg)
+int read_adc()
{
- if (is_intercom_bell_blocked)
- return;
+ return adc1_get_raw(ADC1_GPIO33_CHANNEL);
+}
- // TODO: Can ADC1 be read from ISR?
- int val = adc1_get_raw(CONFIG_HOMEKIT_INTERCOM_BELL_ADC1_CHANNEL);
+int read_adc_avg()
+{
+ //new average = old average + (next data - old average) / next count
+ int avg = 0;
+ for (int i = 1; i < 10; i++)
+ {
+ avg = avg + ((read_adc() - avg) / i);
+ }
+ return avg;
+}
- if (!is_bell_ringing(val))
- return;
+void intercom_bell_read(void *p)
+{
+ ESP_LOGI(TAG, "Intercom bell task started");
+ for (;;)
+ {
+ ESP_LOGI(TAG, "Intercom bell task waiting");
+ ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+ ESP_LOGI(TAG, "Intercom bell task triggered");
+ if (is_bell_ringing(read_adc()))
+ {
+ ESP_LOGI(TAG, "Intercom bell HAP ring");
+ hap_char_update_val(intercom_bell_current_state, &HAP_PROGRAMMABLE_SWITCH_EVENT_SINGLE_PRESS);
+ is_intercom_bell_blocked = true;
+ xTimerReset(intercom_bell_timer, pdFALSE);
+ }
+ }
+}
- // TODO: Can hap function be called from an ISR?
- hap_char_update_val(intercom_bell_current_state, &HAP_PROGRAMMABLE_SWITCH_EVENT_SINGLE_PRESS);
- is_intercom_bell_blocked = true;
- xTimerResetFromISR(intercom_bell_timer, pdFALSE);
+void IRAM_ATTR intercom_bell_isr(void *arg)
+{
+ if (!is_intercom_bell_blocked)
+ {
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ configASSERT(intercom_bell_read_task != NULL);
+ vTaskNotifyGiveFromISR(intercom_bell_read_task, &xHigherPriorityTaskWoken);
+ portYIELD_FROM_ISR();
+ }
}
void intercom_bell_timer_cb(TimerHandle_t timer)
@@ -44,31 +81,50 @@ void intercom_bell_timer_cb(TimerHandle_t timer)
is_intercom_bell_blocked = false;
}
-hap_serv_t *intercom_bell_init(uint32_t key_gpio_pin)
+void intercom_bell_isr_gpio_init()
{
- is_intercom_bell_blocked = false;
- intercom_bell_timer = xTimerCreate("intercom_bell_timer", pdMS_TO_TICKS(CONFIG_HOMEKIT_INTERCOM_LOCK_TIMEOUT), pdFALSE, 0, intercom_bell_timer_cb);
-
- hap_serv_t *intercom_bell_service = hap_serv_doorbell_create(0);
- hap_serv_add_char(intercom_bell_service, hap_char_name_create("Intercom Bell"));
- intercom_bell_current_state = hap_serv_get_char_by_uuid(intercom_bell_service, HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT);
-
+ // Configure ISR GPIO Pin 27
gpio_config_t io_conf;
-
- io_conf.intr_type = GPIO_INTR_ANYEDGE; /* Interrupt for rising edge */
- io_conf.pin_bit_mask = 1ULL << key_gpio_pin; /* Bit mask of the pins */
+ io_conf.intr_type = GPIO_INTR_NEGEDGE; /* Interrupt for falling edge */
+ io_conf.pin_bit_mask = GPIO_SEL_27; /* Bit mask of the pins */
io_conf.mode = GPIO_MODE_INPUT; /* Set as input mode */
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; /* Disable internal pull-up */
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; /* Enable internal pull-down */
+ gpio_config(&io_conf); /* Set the GPIO configuration */
- gpio_config(&io_conf); /* Set the GPIO configuration */
+ gpio_install_isr_service(0); /* Install gpio isr service */
+ gpio_isr_handler_add(GPIO_NUM_27, intercom_bell_isr, (void *)0); /* Hook isr handler for specified gpio pin */
+}
- gpio_install_isr_service(ESP_INTR_FLAG_EDGE | ESP_INTR_FLAG_LOWMED); /* Install gpio isr service */
- gpio_isr_handler_add(key_gpio_pin, intercom_bell_isr, (void *)key_gpio_pin); /* Hook isr handler for specified gpio pin */
+void intercom_bell_adc_gpio_init()
+{
+ // Configure ADC1 Channel 5, GPIO Pin 33
+ gpio_config_t io_conf;
+ io_conf.intr_type = GPIO_INTR_DISABLE; /* Interrupt for falling edge */
+ io_conf.pin_bit_mask = GPIO_SEL_33; /* Bit mask of the pins */
+ io_conf.mode = GPIO_MODE_INPUT; /* Set as input mode */
+ io_conf.pull_up_en = GPIO_PULLUP_DISABLE; /* Disable internal pull-up */
+ io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; /* Enable internal pull-down */
+ gpio_config(&io_conf); /* Set the GPIO configuration */
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html#_CPPv425adc1_config_channel_atten14adc1_channel_t11adc_atten_t
adc1_config_width(ADC_WIDTH_BIT_12); /* The value read is 12 bits wide (range 0-4095). */
- adc1_config_channel_atten(CONFIG_HOMEKIT_INTERCOM_BELL_ADC1_CHANNEL, ADC_ATTEN_DB_11);
+ adc1_config_channel_atten(ADC1_GPIO33_CHANNEL, ADC_ATTEN_DB_11);
+}
+
+hap_serv_t *intercom_bell_init()
+{
+ xTaskCreate(intercom_bell_read, INTERCOM_BELL_TASK_NAME, INTERCOM_BELL_TASK_STACKSIZE, NULL, INTERCOM_BELL_TASK_PRIORITY, &intercom_bell_read_task);
+
+ is_intercom_bell_blocked = false;
+ intercom_bell_timer = xTimerCreate("intercom_bell_timer", pdMS_TO_TICKS(CONFIG_HOMEKIT_INTERCOM_LOCK_TIMEOUT), pdFALSE, 0, intercom_bell_timer_cb);
+
+ hap_serv_t *intercom_bell_service = hap_serv_doorbell_create(0);
+ hap_serv_add_char(intercom_bell_service, hap_char_name_create("Intercom Bell"));
+ intercom_bell_current_state = hap_serv_get_char_by_uuid(intercom_bell_service, HAP_CHAR_UUID_PROGRAMMABLE_SWITCH_EVENT);
+
+ intercom_bell_isr_gpio_init();
+ intercom_bell_adc_gpio_init();
return intercom_bell_service;
}
diff --git a/main/src/led.c b/main/src/led.c
index 714e0f7..63513f6 100644
--- a/main/src/led.c
+++ b/main/src/led.c
@@ -7,30 +7,31 @@
#include <led.h>
#include <intercom.h>
+#define LED_ON 1
+#define LED_OFF 0
+
int intercom_led_identify(hap_acc_t *ha)
{
ESP_LOGI(TAG, "Accessory identified");
for (int i = 0; i < 3; i++)
{
- gpio_set_level(CONFIG_HOMEKIT_INTERCOM_LED_GPIO_PIN, 1);
+ gpio_set_level(GPIO_NUM_13, LED_ON);
vTaskDelay(pdMS_TO_TICKS(500));
- gpio_set_level(CONFIG_HOMEKIT_INTERCOM_LED_GPIO_PIN, 0);
+ gpio_set_level(GPIO_NUM_13, LED_OFF);
vTaskDelay(pdMS_TO_TICKS(500));
}
return HAP_SUCCESS;
}
-void intercom_led_init(uint32_t key_gpio_pin)
+void intercom_led_init()
{
gpio_config_t io_conf;
-
io_conf.intr_type = GPIO_INTR_DISABLE; /* Interrupt for falling edge */
- io_conf.pin_bit_mask = 1ULL << key_gpio_pin; /* Bit mask of the pins */
+ io_conf.pin_bit_mask = GPIO_SEL_13; /* Bit mask of the pins */
io_conf.mode = GPIO_MODE_OUTPUT; /* Set as input mode */
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; /* Disable internal pull-up */
io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; /* Enable internal pull-down */
-
- gpio_config(&io_conf); /* Set the GPIO configuration */
+ gpio_config(&io_conf); /* Set the GPIO configuration */
} \ No newline at end of file
diff --git a/main/src/lock.c b/main/src/lock.c
index ead0401..558968b 100644
--- a/main/src/lock.c
+++ b/main/src/lock.c
@@ -30,7 +30,7 @@ static hap_char_t *intercom_lock_target_state;
void intercom_lock_unsecure()
{
ESP_LOGI(TAG, "Intercom lock unsecure");
- gpio_set_level(CONFIG_HOMEKIT_INTERCOM_LOCK_GPIO_PIN, INTERCOM_LOCK_GPIO_UNLOCKED);
+ gpio_set_level(GPIO_NUM_21, INTERCOM_LOCK_GPIO_UNLOCKED);
hap_char_update_val(intercom_lock_current_state, &HAP_VAL_LOCK_CURRENT_STATE_UNSECURED);
xTimerReset(intercom_lock_timer, 10);
}
@@ -38,7 +38,7 @@ void intercom_lock_unsecure()
void intercom_lock_secure()
{
ESP_LOGI(TAG, "Intercom lock secure");
- gpio_set_level(CONFIG_HOMEKIT_INTERCOM_LOCK_GPIO_PIN, INTERCOM_LOCK_GPIO_LOCKED);
+ gpio_set_level(GPIO_NUM_21, INTERCOM_LOCK_GPIO_LOCKED);
hap_char_update_val(intercom_lock_current_state, &HAP_VAL_LOCK_CURRENT_STATE_SECURED);
}
@@ -82,7 +82,18 @@ void intercom_lock_timer_cb(TimerHandle_t timer)
hap_char_update_val(intercom_lock_target_state, &HAP_VAL_LOCK_TARGET_STATE_SECURED);
}
-hap_serv_t *intercom_lock_init(uint32_t key_gpio_pin)
+void intercom_lock_gpio_init()
+{
+ gpio_config_t io_conf;
+ io_conf.intr_type = GPIO_INTR_DISABLE; /* Disable interrupt */
+ io_conf.pin_bit_mask = GPIO_SEL_21; /* Bit mask of the pins */
+ io_conf.mode = GPIO_MODE_OUTPUT; /* Set as input mode */
+ io_conf.pull_up_en = GPIO_PULLUP_DISABLE; /* Disable internal pull-up */
+ io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; /* Enable internal pull-down */
+ gpio_config(&io_conf);
+}
+
+hap_serv_t *intercom_lock_init()
{
hap_serv_t *intercom_lock_service = hap_serv_lock_mechanism_create(HAP_VAL_LOCK_CURRENT_STATE_SECURED.u, HAP_LOCK_TARGET_STATE_SECURED);
hap_serv_add_char(intercom_lock_service, hap_char_name_create("Intercom Lock"));
@@ -94,15 +105,7 @@ hap_serv_t *intercom_lock_init(uint32_t key_gpio_pin)
intercom_lock_timer = xTimerCreate("intercom_lock_timer", pdMS_TO_TICKS(CONFIG_HOMEKIT_INTERCOM_LOCK_TIMEOUT), pdFALSE, 0, intercom_lock_timer_cb);
- gpio_config_t io_conf;
-
- io_conf.intr_type = GPIO_INTR_DISABLE; /* Disable interrupt */
- io_conf.pin_bit_mask = 1ULL << key_gpio_pin; /* Bit mask of the pins */
- io_conf.mode = GPIO_MODE_OUTPUT; /* Set as input mode */
- io_conf.pull_up_en = GPIO_PULLUP_DISABLE; /* Disable internal pull-up */
- io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; /* Enable internal pull-down */
-
- gpio_config(&io_conf); /* Set the GPIO configuration */
+ intercom_lock_gpio_init();
return intercom_lock_service;
}