mirror of
https://github.com/demik/quack.git
synced 2024-12-22 20:30:48 +00:00
ADB Parsing 90% done, quadrature output issues
This commit is contained in:
parent
a878a80bc0
commit
bffdd20de2
156
main/adb.c
156
main/adb.c
@ -39,15 +39,46 @@
|
||||
/* globals */
|
||||
rmt_config_t adb_rmt_rx = RMT_DEFAULT_CONFIG_RX(GPIO_ADB, RMT_RX_CHANNEL);
|
||||
extern TaskHandle_t t_green, t_blue, t_yellow, t_red;
|
||||
extern TaskHandle_t t_click, t_qx, t_qy;
|
||||
|
||||
/* static defines */
|
||||
static void adb_handle_button(bool action);
|
||||
static bool adb_rx_isone(rmt_item32_t cell);
|
||||
static bool adb_rx_isstop(rmt_item32_t cell);
|
||||
static bool adb_rx_iszero(rmt_item32_t cell);
|
||||
static uint16_t adb_rx_mouse();
|
||||
static void adb_rx_setup(void);
|
||||
static bool adb_rx_tlt(void);
|
||||
static void adb_tx_as(void);
|
||||
static void adb_tx_one(void);
|
||||
static void adb_tx_setup(void);
|
||||
static void adb_tx_zero(void);
|
||||
|
||||
/* functions */
|
||||
static void adb_handle_button(bool action) {
|
||||
static bool status = ADB_B_UP; // Keep state. Click is active low
|
||||
|
||||
if (status == ADB_B_UP && action == ADB_B_UP)
|
||||
return ;
|
||||
if (status == ADB_B_DOWN && action == ADB_B_DOWN)
|
||||
return ;
|
||||
|
||||
/* release button */
|
||||
if (status == ADB_B_DOWN && action == ADB_B_UP) {
|
||||
xTaskNotify(t_click, 0, eSetValueWithOverwrite);
|
||||
status = ADB_B_UP;
|
||||
ESP_LOGD("ADB", "ADB button released");
|
||||
return ;
|
||||
}
|
||||
|
||||
/* press button */
|
||||
if (status == ADB_B_UP && action == ADB_B_DOWN) {
|
||||
xTaskNotify(t_click, 1, eSetValueWithOverwrite);
|
||||
status = ADB_B_DOWN;
|
||||
ESP_LOGD("ADB", "ADB button pressed");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
void adb_init(void) {
|
||||
/* initialise */
|
||||
@ -71,7 +102,9 @@ void adb_init(void) {
|
||||
}
|
||||
|
||||
void adb_task_host(void *pvParameters) {
|
||||
/* Classic Apple Mouse Protocol is 16 bits long */
|
||||
uint16_t data;
|
||||
int8_t move = 0;
|
||||
|
||||
/* put green led to steady if BT is disabled. Otherwise BT init will do it */
|
||||
if (gpio_get_level(GPIO_BTOFF) == 0)
|
||||
@ -85,6 +118,34 @@ void adb_task_host(void *pvParameters) {
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
adb_tx_cmd(ADB_MOUSE|ADB_TALK|ADB_REG0);
|
||||
data = adb_rx_mouse();
|
||||
|
||||
if (data) {
|
||||
/* click is active low */
|
||||
if (! (data & ADB_CMP_B1) || (! (data & ADB_CMP_B2)))
|
||||
adb_handle_button(ADB_B_DOWN);
|
||||
else
|
||||
adb_handle_button(ADB_B_UP);
|
||||
|
||||
move = (data & ADB_CMD_MX) >> 0;
|
||||
if (move & 0x40) {
|
||||
move &= ~0x40;
|
||||
move |= 0x80;
|
||||
move += 64;
|
||||
}
|
||||
|
||||
if (move)
|
||||
xTaskNotify(t_qx, move, eSetValueWithOverwrite);
|
||||
|
||||
move = (data & ADB_CMD_MY) >> 8;
|
||||
if (move & 0x40) {
|
||||
move &= ~0x40;
|
||||
move |= 0x80;
|
||||
move += 64;
|
||||
}
|
||||
|
||||
if (move)
|
||||
xTaskNotify(t_qy, move, eSetValueWithOverwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +159,37 @@ int dur( uint32_t level, uint32_t duration ) {
|
||||
else { return -1.0 * duration; }
|
||||
}
|
||||
|
||||
/*
|
||||
* some ADB mouses are using cells as short as 24µs+49µs, try to get that...
|
||||
* spec allow ±30% variance
|
||||
*
|
||||
* units are in µs
|
||||
*/
|
||||
|
||||
static bool adb_rx_isone(rmt_item32_t cell) {
|
||||
if (cell.level0 == 0 && (cell.duration0 >= 22 && cell.duration0 <= 44) &&
|
||||
cell.level1 == 1 && (cell.duration1 >= 46 && cell.duration1 <= 86))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool adb_rx_isstop(rmt_item32_t cell) {
|
||||
/* high part of the well is lengh 0 because of RMT timeout (100µs+) */
|
||||
if (cell.level0 == 0 && (cell.duration0 >= 46 && cell.duration0 <= 86) &&
|
||||
cell.level1 == 1 && cell.duration1 == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool adb_rx_iszero(rmt_item32_t cell) {
|
||||
if (cell.level0 == 0 && (cell.duration0 >= 46 && cell.duration0 <= 86) &&
|
||||
cell.level1 == 1 && (cell.duration1 >= 22 && cell.duration1 <= 44))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t adb_rx_mouse() {
|
||||
uint16_t data = 0;
|
||||
RingbufHandle_t rb = NULL;
|
||||
rmt_item32_t* items = NULL;
|
||||
size_t rx_size = 0;
|
||||
@ -108,19 +199,59 @@ static uint16_t adb_rx_mouse() {
|
||||
assert(rb != NULL);
|
||||
rmt_rx_start(RMT_RX_CHANNEL, true);
|
||||
items = (rmt_item32_t*) xRingbufferReceive(rb, &rx_size, pdMS_TO_TICKS(10));
|
||||
printf( ">>> %i\n", rx_size);
|
||||
|
||||
//printf( ">>> %i\n", rx_size);
|
||||
rmt_rx_stop(RMT_RX_CHANNEL);
|
||||
|
||||
if (rx_size > (1 * sizeof(rmt_item32_t)))
|
||||
xTaskNotify(t_yellow, LED_ONCE, eSetValueWithOverwrite);
|
||||
else
|
||||
if (items == NULL)
|
||||
return 0;
|
||||
for (i = 0; i < (rx_size / sizeof(rmt_item32_t)); i++) {
|
||||
printf("%d:%dus %d:%dus\n", (items+i)->level0, (items+i)->duration0, (items+i)->level1, (items+i)->duration1);
|
||||
|
||||
/*
|
||||
* Mouse response size in bits is events / sizeof(rmt_item32_t) (4)
|
||||
* start bit + 16 data bits + stop bit = 72 bytes in RMT buffer (18 bits received)
|
||||
*/
|
||||
|
||||
switch (rx_size) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 72:
|
||||
xTaskNotify(t_yellow, LED_ONCE, eSetValueWithOverwrite);
|
||||
break;
|
||||
default:
|
||||
xTaskNotify(t_red, LED_ONCE, eSetValueWithOverwrite);
|
||||
}
|
||||
|
||||
/* check start and stop bits */
|
||||
if (! adb_rx_isone(*(items+0)) && (! adb_rx_isstop(*(items+(rx_size / sizeof(rmt_item32_t) - 1))))) {
|
||||
xTaskNotify(t_red, LED_ONCE, eSetValueWithOverwrite);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* rebuild our data with RMT buffer */
|
||||
for (i = 1; i < ((rx_size / sizeof(rmt_item32_t)) - 1); i++) {
|
||||
data <<= 1;
|
||||
|
||||
/* check that every data is either one or zero */
|
||||
if ((! adb_rx_isone(*(items+i))) && (! adb_rx_iszero(*(items+i)))) {
|
||||
xTaskNotify(t_red, LED_ONCE, eSetValueWithOverwrite);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (adb_rx_isone(*(items+i)))
|
||||
data |= 1;
|
||||
//printf("%d:%dus %d:%dus ", (items+i)->level0, (items+i)->duration0, (items+i)->level1, (items+i)->duration1);
|
||||
}
|
||||
printf("\n");
|
||||
vRingbufferReturnItem(rb, (void*) items);
|
||||
|
||||
return 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline void adb_rx_setup() {
|
||||
gpio_set_level(GPIO_DIR, 0);
|
||||
gpio_set_direction(GPIO_ADB, GPIO_MODE_INPUT);
|
||||
gpio_pullup_dis(GPIO_ADB);
|
||||
gpio_pulldown_dis(GPIO_ADB);
|
||||
}
|
||||
|
||||
static inline void adb_tx_as() {
|
||||
@ -132,8 +263,7 @@ static inline void adb_tx_as() {
|
||||
}
|
||||
|
||||
void adb_tx_cmd(unsigned char cmd) {
|
||||
gpio_set_direction(GPIO_ADB, GPIO_MODE_OUTPUT);
|
||||
|
||||
adb_tx_setup();
|
||||
adb_tx_as();
|
||||
|
||||
/* send actual byte (unrolled loop) */
|
||||
@ -148,8 +278,7 @@ void adb_tx_cmd(unsigned char cmd) {
|
||||
|
||||
/* stop bit */
|
||||
adb_tx_zero();
|
||||
gpio_set_direction(GPIO_ADB, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(GPIO_ADB, GPIO_PULLUP_ONLY);
|
||||
adb_rx_setup();
|
||||
}
|
||||
|
||||
static inline void adb_tx_one() {
|
||||
@ -173,6 +302,11 @@ void adb_tx_reset() {
|
||||
ets_delay_us(500);
|
||||
}
|
||||
|
||||
static inline void adb_tx_setup() {
|
||||
gpio_set_direction(GPIO_ADB, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(GPIO_DIR, 1);
|
||||
}
|
||||
|
||||
static inline void adb_tx_zero() {
|
||||
/* values from AN591 Datasheet minus the estimated call to ets_delay_us */
|
||||
gpio_set_level(GPIO_ADB, 0);
|
||||
|
10
main/adb.h
10
main/adb.h
@ -44,6 +44,12 @@ void adb_tx_reset(void);
|
||||
#define ADB_1_LOW 35
|
||||
#define ADB_1_HIGH 65
|
||||
|
||||
/* Classic Apple Mouse Protocol bitmasks */
|
||||
#define ADB_CMP_B1 (1<<15)
|
||||
#define ADB_CMP_B2 (1<<7)
|
||||
#define ADB_CMD_MX (127<<0)
|
||||
#define ADB_CMD_MY (127<<8)
|
||||
|
||||
/* ADB commands values from 00591b.pdf page 16-17 */
|
||||
#define ADB_MOUSE (3<<4)
|
||||
#define ADB_TALK 0xC
|
||||
@ -51,4 +57,8 @@ void adb_tx_reset(void);
|
||||
#define ADB_REG0 0x0
|
||||
#define ADB_REG3 0x3
|
||||
|
||||
/* Various stuff */
|
||||
#define ADB_B_UP 0
|
||||
#define ADB_B_DOWN 1
|
||||
|
||||
#endif
|
||||
|
@ -44,7 +44,9 @@ void gpio_init(void) {
|
||||
gpio_set_direction(GPIO_REDLED, GPIO_MODE_OUTPUT);
|
||||
|
||||
/* External chips */
|
||||
gpio_reset_pin(GPIO_DIR);
|
||||
gpio_reset_pin(GPIO_OE);
|
||||
gpio_set_direction(GPIO_DIR, GPIO_MODE_OUTPUT);
|
||||
gpio_set_direction(GPIO_OE, GPIO_MODE_OUTPUT);
|
||||
|
||||
/* Modes */
|
||||
@ -55,6 +57,7 @@ void gpio_init(void) {
|
||||
|
||||
/* ADB */
|
||||
gpio_set_direction(GPIO_ADB, GPIO_MODE_INPUT);
|
||||
gpio_set_level(GPIO_DIR, 0);
|
||||
|
||||
/* Quadrature mouse */
|
||||
gpio_reset_pin(GPIO_CLICK);
|
||||
@ -75,9 +78,9 @@ void gpio_init(void) {
|
||||
}
|
||||
|
||||
void gpio_output_disable(void) {
|
||||
gpio_set_level(GPIO_OE, 0);
|
||||
gpio_set_level(GPIO_OE, 1);
|
||||
}
|
||||
|
||||
void gpio_output_enable(void) {
|
||||
gpio_set_level(GPIO_OE, 1);
|
||||
gpio_set_level(GPIO_OE, 0);
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ void gpio_output_enable(void);
|
||||
#define GPIO_QY1 14
|
||||
#define GPIO_QY2 15
|
||||
|
||||
#define GPIO_DIR 19
|
||||
#define GPIO_OE 22
|
||||
#define GPIO_ADBSRC 32
|
||||
#define GPIO_BTOFF 33
|
||||
|
32
main/quad.c
32
main/quad.c
@ -52,9 +52,12 @@ void quad_init(void) {
|
||||
esp_timer_create_args_t args;
|
||||
|
||||
/* create quadrature tasks */
|
||||
xTaskCreate(quad_click, "CLICK", 1024, NULL, tskIDLE_PRIORITY + 1, &t_click);
|
||||
xTaskCreate(quad_move_x, "QX", 1024, NULL, tskIDLE_PRIORITY + 1, &t_qx);
|
||||
xTaskCreate(quad_move_y, "QY", 1024, NULL, tskIDLE_PRIORITY + 1, &t_qy);
|
||||
xTaskCreate(quad_click, "CLICK", 4 * 1024, NULL, tskIDLE_PRIORITY + 1, &t_click);
|
||||
xTaskCreate(quad_move_x, "QX", 4 * 1024, NULL, tskIDLE_PRIORITY + 1, &t_qx);
|
||||
xTaskCreate(quad_move_y, "QY", 4 * 1024, NULL, tskIDLE_PRIORITY + 1, &t_qy);
|
||||
|
||||
printf(">>> T_QX %x\n", (unsigned int)t_qx);
|
||||
printf(">>> T_QY %x\n", (unsigned int)t_qy);
|
||||
|
||||
/* click is active low */
|
||||
gpio_set_level(GPIO_CLICK, 1);
|
||||
@ -67,11 +70,11 @@ void quad_init(void) {
|
||||
|
||||
/* create timers for quadrature phases */
|
||||
args.callback = &quad_timer;
|
||||
args.arg = &t_qx;
|
||||
args.arg = t_qx;
|
||||
args.name = "quad_qx";
|
||||
ESP_ERROR_CHECK(esp_timer_create(&args, &quad_qx));
|
||||
args.callback = &quad_timer;
|
||||
args.arg = &t_qy;
|
||||
args.arg = t_qy;
|
||||
args.name = "quad_qy";
|
||||
ESP_ERROR_CHECK(esp_timer_create(&args, &quad_qy));
|
||||
|
||||
@ -85,6 +88,7 @@ void quad_click(void *pvParameters) {
|
||||
|
||||
while (true) {
|
||||
xTaskNotifyWait(0, 0, &click, portMAX_DELAY);
|
||||
printf("CLICK");
|
||||
switch (click)
|
||||
{
|
||||
case true:
|
||||
@ -114,19 +118,19 @@ void quad_move_x(void *pvParameters) {
|
||||
if (move > 0) {
|
||||
while (move--) {
|
||||
i++;
|
||||
printf("MOVE X %i %i %i\n", move, q1[i % 4], q2[i % 4]);
|
||||
gpio_set_level(GPIO_QX1, q1[i % 4]);
|
||||
gpio_set_level(GPIO_QX2, q2[i % 4]);
|
||||
ESP_ERROR_CHECK(esp_timer_start_once(quad_qx, QUAD_INTERVAL));
|
||||
vTaskSuspend(NULL);
|
||||
//ets_delay_us(QUAD_INTERVAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (move++) {
|
||||
i--;
|
||||
printf("MOVE X %i %i %i\n", move, q1[i % 4], q2[i % 4]);
|
||||
gpio_set_level(GPIO_QX1, q1[i % 4]);
|
||||
gpio_set_level(GPIO_QX2, q2[i % 4]);
|
||||
ESP_ERROR_CHECK(esp_timer_start_once(quad_qx, QUAD_INTERVAL));
|
||||
vTaskSuspend(NULL);
|
||||
//ets_delay_us(QUAD_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,19 +151,19 @@ void quad_move_y(void *pvParameters) {
|
||||
if (move > 0) {
|
||||
while (move--) {
|
||||
i++;
|
||||
printf("MOVE Y %i %i %i\n", move, q1[i % 4], q2[i % 4]);
|
||||
gpio_set_level(GPIO_QY1, q1[i % 4]);
|
||||
gpio_set_level(GPIO_QY2, q2[i % 4]);
|
||||
ESP_ERROR_CHECK(esp_timer_start_once(quad_qy, QUAD_INTERVAL));
|
||||
vTaskSuspend(NULL);
|
||||
//ets_delay_us(QUAD_INTERVAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (move++) {
|
||||
i--;
|
||||
printf("MOVE Y %i %i %i\n", move, q1[i % 4], q2[i % 4]);
|
||||
gpio_set_level(GPIO_QY1, q1[i % 4]);
|
||||
gpio_set_level(GPIO_QY2, q2[i % 4]);
|
||||
ESP_ERROR_CHECK(esp_timer_start_once(quad_qy, QUAD_INTERVAL));
|
||||
vTaskSuspend(NULL);
|
||||
//ets_delay_us(QUAD_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,6 +173,8 @@ void quad_move_y(void *pvParameters) {
|
||||
static void quad_timer(void* arg) {
|
||||
BaseType_t xYieldRequired = pdFALSE;
|
||||
|
||||
printf(">>> TIMER %x\n", (unsigned int)arg);
|
||||
|
||||
xYieldRequired = xTaskResumeFromISR(arg);
|
||||
|
||||
/* switch context of needed */
|
||||
|
@ -32,7 +32,7 @@ void quad_move_x(void *pvParameters);
|
||||
void quad_move_y(void *pvParameters);
|
||||
|
||||
/* defines */
|
||||
#define QUAD_INTERVAL 100
|
||||
#define QUAD_INTERVAL 20
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user