Skip to content

Commit 3d87d93

Browse files
committed
pre v1.5 code cleaning and documentation
1 parent a20b903 commit 3d87d93

File tree

5 files changed

+66
-482
lines changed

5 files changed

+66
-482
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
- https://github.com/espressif/esp-idf/releases/tag/v5.5.2
44
- this fixes a few buffers overflows and other rare stuff in Bluedroid
55
- 1.5.x series is compatible with 1.3 to 1.5 PCBs (EDA subfolder)
6+
- new bespoke ADB RX driver has been developed based on the legacy RMT driver
7+
- the functionality is the same as the v1.4 one but it's more SDK future proof
68

79
## v1.4.11
810
- update to ESP-IDF v5.4.2

main/adb.c

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727
#include <freertos/ringbuf.h>
2828
#include <freertos/semphr.h>
2929
#include <freertos/task.h>
30-
#include "esp_log.h"
31-
#include "esp_system.h"
32-
#include "esp_chip_info.h"
33-
#include "esp_private/periph_ctrl.h"
34-
#include "soc/periph_defs.h"
35-
#include "soc/rmt_reg.h"
30+
#include <esp_log.h>
31+
#include <esp_system.h>
32+
#include <esp_chip_info.h>
33+
#include <esp_private/periph_ctrl.h>
34+
#include <soc/rmt_reg.h>
35+
#include <hal/rmt_types.h>
3636

3737
#include "adb.h"
3838
#include "led.h"
@@ -42,31 +42,36 @@
4242
/*
4343
* THEORY OF OPERATION *
4444
*
45-
* Quack scheduler is running at 250 Hz which give 4 ms running "slots"
45+
* Quack scheduler is running at 250 Hz which give 4 ms time "slots"
4646
*
4747
* TRANSMITTING *
4848
* It's done by toggling the GPIO in an active loop, which is less than ideal because
4949
* the RTOS may be scheduling stuff.
5050
*
5151
* For polling it's ok because the ADB command (TALK) can be send under 4ms so the task
5252
* shouldn't be rescheduled. For the initial setup it can be a little longer (up to 12 ms)
53-
* so there is risks of being rescheduled here. On can avoid most of it by putting the
54-
* transmitting task into high priority and only running others tasks as low priority.
53+
* so there is risks of being rescheduled here. One can avoid most of it by putting the
54+
* transmitting task into as priority and only running others tasks as low priority.
5555
*
5656
* RECEIVING *
5757
* since we can be scheduled anytime during reception, reception is done using the RMT
5858
* (Remote Control Transceiver) transceiver of the ESP32.
5959
*
60-
* Before ESP-IDF v5.0, it was donne using the RMT driver but this has been deprecated
61-
* a subset of it for this specific project has been reimplemented within the phy.* files
60+
* Before ESP-IDF v5.0, it was donne using the RMT driver but this has been deprecated.
61+
* A subset of it for this specific project has been reimplemented within the phy.* files
6262
* using the RMT HAL.
6363
*
64+
* The driver grab the ADB pulses for about 8ms, then pass then into a ringbuf,
65+
* which are then decoded in adb_rx_mouse(). the 8ms is a compromise to be able to poll
66+
* at a decent rate because the peripheral can't know when the transmission happens.
67+
* this limit us to about 20 bits
68+
*
6469
* Overall, in order to not push our luck this realistically limit the mouse protocol to
6570
* the simpler ones (classic 100 and 200 cpi)
6671
*/
6772

6873
/* defines */
69-
#define TAG "ADB"
74+
#define TAG "ADB_MGR"
7075

7176
/* globals */
7277
extern TaskHandle_t t_adb2hid;
@@ -77,9 +82,9 @@ extern QueueHandle_t q_qx, q_qy;
7782
/* static defines */
7883
static void adb_handle_button(bool action);
7984
static void adb_phy_reset(void);
80-
static bool adb_rx_isone(phy_item32_t cell);
81-
static bool adb_rx_isstop(phy_item32_t cell);
82-
static bool adb_rx_iszero(phy_item32_t cell);
85+
static bool adb_rx_isone(rmt_symbol_word_t cell);
86+
static bool adb_rx_isstop(rmt_symbol_word_t cell);
87+
static bool adb_rx_iszero(rmt_symbol_word_t cell);
8388
static uint16_t adb_rx_mouse(void);
8489
static void adb_rx_setup(void);
8590
static void adb_scan_macaj(void);
@@ -163,10 +168,12 @@ void adb_probe(void) {
163168

164169
adb_tx_cmd(ADB_MOUSE|ADB_TALK|ADB_REG3);
165170
register3 = adb_rx_mouse();
166-
ESP_LOGD("ADB", "Device $3 register3: %04x", register3);
171+
ESP_LOGD(TAG, "$3 register3: %04x", register3);
167172

168-
if (register3 && (register3 & ADB_H_ALL) == ADB_H_ERR)
173+
if (register3 && (register3 & ADB_H_ALL) == ADB_H_ERR) {
169174
ESP_LOGE(TAG, "Mouse failed self init test");
175+
xTaskNotify(t_red, LED_ONCE, eSetValueWithOverwrite);
176+
}
170177

171178
/*
172179
* try to unglue composite devices (Kensington)
@@ -381,7 +388,7 @@ void adb_task_host(void *pvParameters) {
381388
else
382389
state = ADB_S_KEEP;
383390
}
384-
ESP_LOGD("ADB", "Check mouse presence %04x", data);
391+
ESP_LOGD(TAG, "Checking $3: %04x", data);
385392
}
386393
}
387394
}
@@ -417,22 +424,22 @@ void adb_task_idle(void *pvParameters) {
417424
* units are in µs
418425
*/
419426

420-
static bool adb_rx_isone(phy_item32_t cell) {
427+
static bool adb_rx_isone(rmt_symbol_word_t cell) {
421428
if (cell.level0 == 0 && (cell.duration0 >= 22 && cell.duration0 <= 44) &&
422429
cell.level1 == 1 && (cell.duration1 >= 46 && cell.duration1 <= 86))
423430
return true;
424431
return false;
425432
}
426433

427-
static bool adb_rx_isstop(phy_item32_t cell) {
428-
/* high part of the well is lengh 0 because of RMT timeout (100µs+) */
434+
static bool adb_rx_isstop(rmt_symbol_word_t cell) {
435+
/* high part of the end cell is lengh 0 because of RMT timeout (100µs+) */
429436
if (cell.level0 == 0 && (cell.duration0 >= 46 && cell.duration0 <= 86) &&
430437
cell.level1 == 1 && cell.duration1 == 0)
431438
return true;
432439
return false;
433440
}
434441

435-
static bool adb_rx_iszero(phy_item32_t cell) {
442+
static bool adb_rx_iszero(rmt_symbol_word_t cell) {
436443
if (cell.level0 == 0 && (cell.duration0 >= 46 && cell.duration0 <= 86) &&
437444
cell.level1 == 1 && (cell.duration1 >= 22 && cell.duration1 <= 44))
438445
return true;
@@ -443,14 +450,14 @@ static uint16_t IRAM_ATTR adb_rx_mouse() {
443450
uint32_t phy_status;
444451
uint16_t data = 0;
445452
RingbufHandle_t rb = NULL;
446-
phy_item32_t* items = NULL;
453+
rmt_symbol_word_t* items = NULL;
447454
size_t rx_size = 0;
448455
size_t i;
449456

450457
phy_get_ringbuf_handle(&rb);
451458
configASSERT(rb != NULL);
452459
phy_rx_start(true);
453-
items = (phy_item32_t*)xRingbufferReceive(rb, &rx_size, pdMS_TO_TICKS(8));
460+
items = (rmt_symbol_word_t*)xRingbufferReceive(rb, &rx_size, pdMS_TO_TICKS(8));
454461

455462
phy_get_status(&phy_status);
456463
if (((phy_status >> RMT_STATE_CH0_S) & RMT_STATE_CH0_V) == 4)
@@ -461,7 +468,7 @@ static uint16_t IRAM_ATTR adb_rx_mouse() {
461468
return 0;
462469

463470
/*
464-
* Mouse response size in bits is events / sizeof(phy_item32_t) (4)
471+
* Mouse response size in bits is events / sizeof(rmt_symbol_word_t) (4)
465472
* start bit + 16 data bits + stop bit = 72 bytes in RMT buffer (18 bits received)
466473
*
467474
* Check start / stop bits and size.
@@ -479,18 +486,18 @@ static uint16_t IRAM_ATTR adb_rx_mouse() {
479486
xTaskNotify(t_yellow, LED_ONCE, eSetValueWithOverwrite);
480487
break;
481488
default:
482-
ESP_LOGD(TAG, "wrong size of %i bit(s)", rx_size / sizeof(phy_item32_t));
489+
ESP_LOGD(TAG, "wrong size of %i bit(s)", rx_size / sizeof(rmt_symbol_word_t));
483490
xTaskNotify(t_red, LED_ONCE, eSetValueWithOverwrite);
484491
}
485492

486493
/* check start and stop bits */
487-
if (! adb_rx_isone(*(items+0)) && (! adb_rx_isstop(*(items+(rx_size / sizeof(phy_item32_t) - 1))))) {
494+
if (! adb_rx_isone(*(items+0)) && (! adb_rx_isstop(*(items+(rx_size / sizeof(rmt_symbol_word_t) - 1))))) {
488495
xTaskNotify(t_red, LED_ONCE, eSetValueWithOverwrite);
489496
return 0;
490497
}
491498

492499
/* rebuild our data with RMT buffer */
493-
for (i = 1; i < ((rx_size / sizeof(phy_item32_t)) - 1); i++) {
500+
for (i = 1; i < ((rx_size / sizeof(rmt_symbol_word_t)) - 1); i++) {
494501
data <<= 1;
495502

496503
/* check that every data is either one or zero */

main/phy.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <freertos/ringbuf.h>
2828
#include <hal/rmt_hal.h>
2929
#include <hal/rmt_ll.h>
30+
#include <hal/rmt_types.h>
3031
#include <soc/io_mux_reg.h>
3132
#include <soc/rmt_periph.h>
3233

@@ -35,7 +36,7 @@
3536
#include "sdkconfig.h"
3637

3738
/* defines */
38-
static const char *TAG = "PHY(ADB)";
39+
static const char *TAG = "ADB_PHY";
3940

4041
/* spinlock for protecting concurrent register-level access only */
4142
#define PHY_ENTER_CRITICAL() portENTER_CRITICAL_SAFE(&(rmt_contex.rmt_spinlock))
@@ -47,7 +48,7 @@ typedef struct {
4748
_lock_t rmt_driver_isr_lock;
4849
/* Mutex lock for protecting concurrent register/unregister of RMT channels (ISR) */
4950
portMUX_TYPE rmt_spinlock;
50-
phy_isr_handle_t rmt_driver_intr_handle;
51+
intr_handle_t rmt_driver_intr_handle;
5152
/* Bitmask of installed drivers channels for protecting concurrent register/unregister of RMT channels (ISR) */
5253
uint8_t rmt_driver_channels;
5354
bool rmt_module_enabled;
@@ -63,7 +64,6 @@ static phy_contex_t rmt_contex = {
6364

6465
phy_config_t adb_rmt_rx;
6566
RingbufHandle_t phy_rx_buf = NULL;
66-
bool phy_driver_installed = false;
6767

6868
/* static defines */
6969
static void phy_driver_isr(void *arg);
@@ -92,16 +92,17 @@ esp_err_t phy_config(void) {
9292

9393
phy_module_enable();
9494

95-
ESP_RETURN_ON_ERROR(phy_set_gpio(adb_rmt_rx.gpio_num, adb_rmt_rx.flags & PHY_CHANNEL_FLAGS_INVERT_SIG), TAG, "set gpio for RMT driver failed");
96-
ESP_RETURN_ON_ERROR(phy_internal_config(&RMT, &adb_rmt_rx), TAG, "initialize RMT driver failed");
95+
ESP_RETURN_ON_ERROR(phy_set_gpio(adb_rmt_rx.gpio_num, adb_rmt_rx.flags & PHY_CHANNEL_FLAGS_INVERT_SIG), \
96+
TAG, "set gpio for RMT device failed");
97+
ESP_RETURN_ON_ERROR(phy_internal_config(&RMT, &adb_rmt_rx), TAG, "initialize ADB(PHY) driver failed");
9798

9899
return ESP_OK;
99100
}
100101

101102
esp_err_t phy_driver_install(size_t rx_buf_size, int intr_alloc_flags) {
102103
esp_err_t err = ESP_OK;
103104

104-
if (phy_driver_installed) {
105+
if (phy_rx_buf) {
105106
ESP_LOGD(TAG, "RMT driver already installed");
106107
return ESP_ERR_INVALID_STATE;
107108
}
@@ -133,7 +134,7 @@ esp_err_t phy_driver_install(size_t rx_buf_size, int intr_alloc_flags) {
133134

134135
static void IRAM_ATTR phy_driver_isr(void *arg) {
135136
uint32_t status = 0;
136-
phy_item32_t *addr = NULL;
137+
rmt_symbol_word_t *addr = NULL;
137138
rmt_hal_context_t *hal = (rmt_hal_context_t *)arg;
138139
BaseType_t HPTaskAwoken = pdFALSE;
139140

@@ -161,7 +162,7 @@ static void IRAM_ATTR phy_driver_isr(void *arg) {
161162
int item_len = rmt_ll_rx_get_memory_writer_offset(rmt_contex.hal.regs, PHY_CHANNEL_NUM);
162163
rmt_ll_rx_set_mem_owner(rmt_contex.hal.regs, PHY_CHANNEL_NUM, RMT_LL_MEM_OWNER_SW);
163164
if (phy_rx_buf) {
164-
addr = (phy_item32_t *)RMTMEM.chan[PHY_CHANNEL_NUM].data32;
165+
addr = (rmt_symbol_word_t *)RMTMEM.chan[PHY_CHANNEL_NUM].data32;
165166
BaseType_t res = xRingbufferSendFromISR(phy_rx_buf, (void *)addr, item_len * 4, &HPTaskAwoken);
166167
if (res == pdFALSE)
167168
ESP_DRAM_LOGE(TAG, "RMT RX buffer is full");
@@ -221,8 +222,9 @@ static esp_err_t phy_internal_config(rmt_dev_t *dev, const phy_config_t *phy_par
221222
uint32_t rmt_source_clk_hz;
222223
rmt_clock_source_t clk_src = RMT_BASECLK_DEFAULT;
223224

224-
ESP_RETURN_ON_FALSE(mem_cnt <= SOC_RMT_CHANNELS_PER_GROUP && mem_cnt > 0, ESP_ERR_INVALID_ARG, TAG, PHY_MEM_CNT_ERROR_STR);
225-
ESP_RETURN_ON_FALSE(clk_div > 0, ESP_ERR_INVALID_ARG, TAG, PHY_CLK_DIV_ERROR_STR);
225+
ESP_RETURN_ON_FALSE(mem_cnt <= SOC_RMT_CHANNELS_PER_GROUP && mem_cnt > 0, \
226+
ESP_ERR_INVALID_ARG, TAG, "Memory block number error");
227+
ESP_RETURN_ON_FALSE(clk_div > 0, ESP_ERR_INVALID_ARG, TAG, "Clock divider error");
226228

227229
PHY_ENTER_CRITICAL();
228230
rmt_ll_enable_mem_access_nonfifo(dev, true);
@@ -253,13 +255,14 @@ static esp_err_t phy_internal_config(rmt_dev_t *dev, const phy_config_t *phy_par
253255
return ESP_OK;
254256
}
255257

256-
esp_err_t phy_isr_deregister(phy_isr_handle_t handle) {
258+
esp_err_t phy_isr_deregister(intr_handle_t handle) {
257259
return esp_intr_free(handle);
258260
}
259261

260262
esp_err_t phy_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, intr_handle_t *handle) {
261-
ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TAG, PHY_ADDR_ERROR_STR);
262-
ESP_RETURN_ON_FALSE(rmt_contex.rmt_driver_channels == 0, ESP_FAIL, TAG, "RMT driver installed, can not install ISR handler");
263+
ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TAG, "ISR address error");
264+
ESP_RETURN_ON_FALSE(rmt_contex.rmt_driver_channels == 0, \
265+
ESP_FAIL, TAG, "RMT driver installed, can not install ISR handler");
263266

264267
return esp_intr_alloc(rmt_periph_signals.groups[0].irq, intr_alloc_flags, fn, arg, handle);
265268
}
@@ -277,7 +280,7 @@ void phy_get_status(uint32_t *status) {
277280

278281
/* disable RMT module */
279282
static void phy_module_disable(void) {
280-
/* to suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV */
283+
281284
int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
282285

283286
PHY_ENTER_CRITICAL();
@@ -291,9 +294,7 @@ static void phy_module_disable(void) {
291294

292295
/* enable RMT module */
293296
static void phy_module_enable(void) {
294-
/* to suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV */
295-
int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
296-
297+
PHY_DECLARE_ATOMIC();
297298
PHY_ENTER_CRITICAL();
298299
if (rmt_contex.rmt_module_enabled == false) {
299300
rmt_ll_enable_bus_clock(0, true);
@@ -327,7 +328,7 @@ esp_err_t phy_rx_stop(void) {
327328

328329
/* set GPIO matrix and GPIO pin for channel 0 */
329330
esp_err_t phy_set_gpio(gpio_num_t gpio_num, bool invert_signal) {
330-
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "PHY(ADB) invalid GPIO");
331+
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "invalid GPIO");
331332

332333
gpio_func_sel(gpio_num, PIN_FUNC_GPIO);
333334
gpio_set_direction(gpio_num, GPIO_MODE_INPUT);

main/phy.h

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,18 @@
3131
*/
3232

3333
/* defines */
34-
#define PHY_CHANNEL_NUM 0
35-
#define PHY_CHANNEL_FLAGS_INVERT_SIG (1 << 1) /* Invert RMT signal */
36-
#define PHY_ADDR_ERROR_STR "PHY(ADB) ADDRESS ERR"
37-
#define PHY_CLK_DIV_ERROR_STR "PHY(ADB) CLK DIV ERR"
38-
#define PHY_DEFAULT_CLK_DIV 80
39-
#define PHY_MEM_CNT_ERROR_STR "PHY(ADB) MEM BLOCK NUM ERR"
34+
#define PHY_CHANNEL_NUM 0
35+
#define PHY_CHANNEL_FLAGS_INVERT_SIG (1 << 1) /* Invert RMT signal */
36+
#define PHY_DEFAULT_CLK_DIV 80
4037

41-
/* structures */
42-
typedef intr_handle_t phy_isr_handle_t;
38+
/* to suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV */
39+
#define PHY_DECLARE_ATOMIC() int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused));
4340

4441
/* RMT RX specific configure parameters (main structure below) */
4542
typedef struct {
46-
uint16_t idle_threshold; /* RMT RX idle threshold */
47-
uint8_t filter_ticks_thresh; /* RMT filter tick number */
48-
bool filter_en; /* RMT receiver filter enable */
43+
uint16_t idle_threshold; /* RMT RX idle threshold */
44+
uint8_t filter_ticks_thresh; /* RMT filter tick number */
45+
bool filter_en; /* RMT receiver filter enable */
4946
} phy_rx_config_t;
5047

5148
/* structure of RMT configure parameters */
@@ -57,23 +54,10 @@ typedef struct {
5754
phy_rx_config_t rx_config; /* RMT RX parameter */
5855
} phy_config_t;
5956

60-
/* structure of data coming from the RMT device */
61-
typedef struct {
62-
union {
63-
struct {
64-
uint32_t duration0 : 15; /* Duration of level0 */
65-
uint32_t level0 : 1; /* Level of the first part */
66-
uint32_t duration1 : 15; /* Duration of level1 */
67-
uint32_t level1 : 1; /* Level of the second part */
68-
};
69-
uint32_t val; /* Equivalent unsigned value for the RMT item */
70-
};
71-
} phy_item32_t;
72-
7357
/* hardware memory layout */
7458
typedef struct {
7559
struct {
76-
volatile phy_item32_t data32[SOC_RMT_MEM_WORDS_PER_CHANNEL];
60+
volatile rmt_symbol_word_t data32[SOC_RMT_MEM_WORDS_PER_CHANNEL];
7761
} chan[SOC_RMT_CHANNELS_PER_GROUP];
7862
} phy_mem_t;
7963

@@ -83,11 +67,10 @@ esp_err_t phy_driver_install(size_t rx_buf_size, int intr_alloc_flags);
8367
esp_err_t phy_driver_uninstall(void);
8468
esp_err_t phy_get_ringbuf_handle(RingbufHandle_t *buf_handle);
8569
void phy_get_status(uint32_t *status);
86-
esp_err_t phy_isr_deregister(phy_isr_handle_t handle);
70+
esp_err_t phy_isr_deregister(intr_handle_t handle);
8771
esp_err_t phy_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, intr_handle_t *handle);
8872
esp_err_t phy_rx_start(bool rx_idx_rst);
8973
esp_err_t phy_rx_stop(void);
9074
esp_err_t phy_set_gpio(gpio_num_t gpio_num, bool invert_signal);
9175

92-
9376
#endif

0 commit comments

Comments
 (0)