Skip to content
Snippets Groups Projects
Commit c8cdf948 authored by moon2's avatar moon2 :speech_balloon: Committed by q3k
Browse files

badge link: some backend

parent 2dc66484
No related branches found
No related tags found
No related merge requests found
......@@ -6,13 +6,68 @@
#define BUTTON_PRESSED_RIGHT 1
#define BUTTON_NOT_PRESSED 0
int8_t get_button_state(bool leftbutton);
void update_button_state();
#define BADGE_LINK_LINE_IN_TIP 0b0001
#define BADGE_LINK_LINE_IN_RING 0b0010
#define BADGE_LINK_LINE_OUT_TIP 0b0100
#define BADGE_LINK_LINE_OUT_RING 0b1000
#define BADGE_LINK_LINE_IN ((BADGE_LINK_LINE_IN_TIP) | (BADGE_LINK_LINE_IN_RING))
#define BADGE_LINK_LINE_OUT ((BADGE_LINK_LINE_OUT_TIP) | (BADGE_LINK_LINE_OUT_RING))
#define BADGE_LINK_ALL ((BADGE_LINK_LINE_IN) | (BADGE_LINK_LINE_OUT))
#define BADGE_LINK_LINE_IN_TIP_PIN 4
#define BADGE_LINK_LINE_IN_RING_PIN 5
#define BADGE_LINK_LINE_OUT_TIP_PIN 6
#define BADGE_LINK_LINE_OUT_RING_PIN 7
/* Initializes GPIO modes, prefills structs, etc. Call before using library.
*/
void init_buttons();
/* Gets data from I2C portexpanders and GPIOs. Requires I2C lock.
*/
void update_button_state();
/* UI sugar: People might prefer using one button for in-application stuff and the other
* for entering main menu/volume control, depending on their handedness and how they hold
* the badge. This function allows them configure this and is meant to be only be used by
* the OS user config handler.
*
* Set to 1 to use the left shoulder button as the menu button, 0 for the right
*/
void spio_menu_button_set_left(bool left);
/* Gets user menu button user preference as set with spio_menu_button_set_left.
*/
int8_t spio_menu_button_get_left();
/* Read the state of the menu/application button at the last call of update_button_state.
* Compare with BUTTON_(NOT)PRESSED* constants for -h.
*/
int8_t spio_menu_button_get();
int8_t spio_application_button_get();
/* Read the state of the left/right button at the last call of update_button_state.
* Compare with BUTTON_(NOT)PRESSED* constants for -h.
* This ignores user preference and should be used only with good reason.
*/
int8_t spio_left_button_get();
int8_t spio_right_button_get();
int8_t spio_menu_button_get_left();
void spio_menu_button_set_left(bool left);
/* Gets active badge links ports. Mask with BADGE_LINK_LINE_{IN/OUT}_{TIP/RING}. The corresponding
* GPIO indices are listed in BADGE_LINK_LINE_{OUT/IN}_{TIP/RING}_PIN.
*/
uint8_t spio_badge_link_get_active(uint8_t pin_mask);
/* Disables badge link ports. Mask with BADGE_LINK_LINE_{IN/OUT}_{TIP/RING}. The corresponding
* GPIO indices are listed in BADGE_LINK_LINE_{OUT/IN}_{TIP/RING}_PIN.
* Returns the output of spio_badge_link_get_active after execution.
*/
uint8_t spio_badge_link_disable(uint8_t pin_mask);
/* Enables badge link ports. Mask with BADGE_LINK_LINE_{IN/OUT}_{TIP/RING}. The corresponding
* GPIO indices are listed in BADGE_LINK_LINE_{OUT/IN}_{TIP/RING}_PIN.
* Returns the output of spio_badge_link_get_active after execution.
*
* Do NOT connect headphones to a badge link port. You might hear a ringing for a while. Warn user.
*/
uint8_t spio_badge_link_enable(uint8_t pin_mask);
......@@ -4,10 +4,123 @@
#include "stdint.h"
#include "badge23/spio.h"
#include "badge23/lock.h"
#include "badge23/audio.h"
#include "driver/i2c.h"
#define I2C_MASTER_NUM 0
#define TIMEOUT_MS 1000
#if defined(CONFIG_BADGE23_HW_GEN_P4) || defined(CONFIG_BADGE23_HW_GEN_P3)
#define BADGE_LINK_LINE_OUT_TIP_ENABLE_PIN 6
#define BADGE_LINK_LINE_OUT_RING_ENABLE_PIN 7
#define BADGE_LINK_LINE_IN_TIP_ENABLE_PIN 5
#define BADGE_LINK_LINE_IN_RING_ENABLE_PIN 4
#define LEFT_BUTTON_RIGHT (0+8)
#define RIGHT_BUTTON_LEFT (6+8)
#define RIGHT_BUTTON_MID (5+8)
#define RIGHT_BUTTON_RIGHT (7+8)
#elif defined(CONFIG_BADGE23_HW_GEN_P6)
#define BADGE_LINK_LINE_OUT_TIP_ENABLE_PIN 5
#define BADGE_LINK_LINE_OUT_RING_ENABLE_PIN 6
#define BADGE_LINK_LINE_IN_TIP_ENABLE_PIN 3
#define BADGE_LINK_LINE_IN_RING_ENABLE_PIN 4
#define LEFT_BUTTON_RIGHT (0+8)
#define RIGHT_BUTTON_LEFT (4+8)
#define RIGHT_BUTTON_MID (7+8)
#define RIGHT_BUTTON_RIGHT (5+8)
#endif
static int8_t leftbutton = 0;
static int8_t rightbutton = 0;
static bool menu_button_left = 0;
static uint8_t badge_link_enabled = 0;
/* The MAX7321 doesn't have any input/output pin configuration methods. Instead,
* it has a ~40k pullup resistor to VCC and a programmable shunt transistor to VEE.
* Writing a byte to the IC closes each shunt with a LO at its index.
* Reading a byte returns the state of each pin.
*
* This means that changing a single output bit cannot be changed without some
* information about the other pins. Also a output pin set to HI can read as LO
* if there's an outside shunt.
*/
typedef struct{
uint8_t address;
uint8_t is_output_pin; // mask for pins we wish to use as outputs
uint8_t read_state; //
uint8_t output_state; // goal output state
} max7321_t;
max7321_t port_expanders[2];
void _max7321_update(max7321_t *max){
uint8_t rx = 0;
uint8_t tx = (~(max->is_output_pin)) | max->output_state;
xSemaphoreTake(mutex_i2c, portMAX_DELAY);
esp_err_t tx_error = i2c_master_write_to_device(I2C_MASTER_NUM, max->address, &tx, sizeof(tx), TIMEOUT_MS / portTICK_PERIOD_MS);
esp_err_t rx_error = i2c_master_read_from_device(I2C_MASTER_NUM, max->address, &rx, sizeof(rx), TIMEOUT_MS / portTICK_PERIOD_MS);
xSemaphoreGive(mutex_i2c);
max->read_state = rx;
}
void max7321s_update(){
_max7321_update(&port_expanders[0]);
_max7321_update(&port_expanders[1]);
}
bool max7321s_get_pin(uint8_t pin){
if(pin>15) return 0;
max7321_t * pe = &port_expanders[0];
if(pin>7){
pe = &port_expanders[1];
pin -= 8;
}
return ((pe->read_state) >> pin) & 1;
}
bool max7321s_set_pin(uint8_t pin, bool on){
if(pin>15) return 0;
max7321_t * pe = &port_expanders[0];
if(pin>7){
pe = &port_expanders[1];
pin -= 8;
}
if(((pe->is_output_pin) >> pin) & 1){
if(on){
pe->output_state |= 1<<pin;
} else {
pe->output_state &= ~(1<<pin);
}
return 1;
} else {
return 0;
}
}
void max7321s_set_pinmode_output(uint8_t pin, bool output){
if(pin>15) return 0;
max7321_t * pe = &port_expanders[0];
if(pin>7){
pe = &port_expanders[1];
pin -= 8;
}
if(output){
pe->is_output_pin |= (1<<pin);
} else {
pe->is_output_pin &= ~(1<<pin);
}
}
#if defined(CONFIG_BADGE23_HW_GEN_P1)
#define RIGHT_BUTTON_LEFT 37
......@@ -61,21 +174,16 @@ void update_button_state(){
}
}
#elif defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4)
#include "driver/i2c.h"
#define I2C_MASTER_NUM 0
#define TIMEOUT_MS 1000
#elif defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4) || defined(CONFIG_BADGE23_HW_GEN_P6)
//on ESP32
#define LEFT_BUTTON_LEFT 3
#define LEFT_BUTTON_MID 0
//on PORTEXPANDER
#define LEFT_BUTTON_RIGHT 0
#define RIGHT_BUTTON_LEFT 6
#define RIGHT_BUTTON_MID 5
#define RIGHT_BUTTON_RIGHT 7
max7321_t port_expanders[] = { {0b01101110, 0, 255, 255},
{0b01101101, 0, 255, 255} };
static void _init_buttons(){
//configure all buttons as pullup
......@@ -90,42 +198,45 @@ static void _init_buttons(){
cfg.pin_bit_mask = 1;
cfg.pull_up_en = GPIO_PULLUP_DISABLE;
ESP_ERROR_CHECK(gpio_config(&cfg));
printf("nya\n");
max7321s_set_pinmode_output(RIGHT_BUTTON_RIGHT, 0);
max7321s_set_pinmode_output(RIGHT_BUTTON_MID, 0);
max7321s_set_pinmode_output(RIGHT_BUTTON_LEFT, 0);
max7321s_set_pinmode_output(LEFT_BUTTON_RIGHT, 0);
}
void update_button_state(){
uint8_t port;
xSemaphoreTake(mutex_i2c, portMAX_DELAY);
esp_err_t ret = i2c_master_read_from_device(I2C_MASTER_NUM, 0b1101101, &port, sizeof(port), TIMEOUT_MS / portTICK_PERIOD_MS);
xSemaphoreGive(mutex_i2c);
int8_t process_button_state(bool r, bool m, bool l){
if(!l){
return BUTTON_PRESSED_LEFT;
} else if(!m){
return BUTTON_PRESSED_DOWN;
} else if(!r){
return BUTTON_PRESSED_RIGHT;
} else {
return BUTTON_NOT_PRESSED;
}
}
uint8_t rr = port & (1ULL << RIGHT_BUTTON_RIGHT);
uint8_t rm = port & (1ULL << RIGHT_BUTTON_MID);
uint8_t rl = port & (1ULL << RIGHT_BUTTON_LEFT);
uint8_t lr = port & (1ULL << LEFT_BUTTON_RIGHT);
void update_button_state(){
max7321s_update();
uint8_t rr = max7321s_get_pin(RIGHT_BUTTON_RIGHT);
uint8_t rm = max7321s_get_pin(RIGHT_BUTTON_MID);
uint8_t rl = max7321s_get_pin(RIGHT_BUTTON_LEFT);
uint8_t lr = max7321s_get_pin(LEFT_BUTTON_RIGHT);
uint8_t ll = gpio_get_level(LEFT_BUTTON_LEFT);
uint8_t lm = gpio_get_level(LEFT_BUTTON_MID);
if(!rl){
rightbutton = BUTTON_PRESSED_LEFT;
} else if(!rm){
rightbutton = BUTTON_PRESSED_DOWN;
} else if(!rr){
rightbutton = BUTTON_PRESSED_RIGHT;
} else {
rightbutton = BUTTON_NOT_PRESSED;
int8_t new_rightbutton = process_button_state(rr, rm, rl);
int8_t new_leftbutton = process_button_state(lr, lm, ll);
if(new_rightbutton != rightbutton){
//TODO: CALLBACK button_state_has_changed_to(new_rightbutton)
//note: consider menubutton/application button config option
}
if(!ll){
leftbutton = BUTTON_PRESSED_LEFT;
} else if(!lm){
leftbutton = BUTTON_PRESSED_DOWN;
} else if(!lr){
leftbutton = BUTTON_PRESSED_RIGHT;
} else {
leftbutton = BUTTON_NOT_PRESSED;
if(new_leftbutton != leftbutton){
//TODO: CALLBACK button_state_has_changed_to(new_leftbutton)
}
rightbutton = new_rightbutton;
leftbutton = new_leftbutton;
}
#else
......@@ -145,7 +256,6 @@ int8_t get_button_state(bool left){
return rightbutton;
}
static bool menu_button_left = 0;
void spio_menu_button_set_left(bool left){
menu_button_left = 1;
......@@ -170,3 +280,57 @@ int8_t spio_right_button_get(){
int8_t spio_menu_button_get_left(){
return menu_button_left;
}
uint8_t spio_badge_link_get_active(uint8_t pin_mask){
return badge_link_enabled & pin_mask;
}
#if defined(CONFIG_BADGE23_HW_GEN_P1)
static uint8_t spio_badge_link_set(uint8_t pin_mask, uint8_t state){
return 0; // no badge link here (yet)
}
#elif defined(CONFIG_BADGE23_HW_GEN_P3) || defined(CONFIG_BADGE23_HW_GEN_P4) || defined(CONFIG_BADGE23_HW_GEN_P6)
#define USER_WARNINGS_ENABLED
static int8_t spio_badge_link_set(uint8_t pin_mask, bool state){
if(state) {
if((pin_mask & BADGE_LINK_LINE_OUT_RING) || (pin_mask & BADGE_LINK_LINE_OUT_TIP)){
if(!audio_headphones_are_connected()) {
pin_mask &= ~BADGE_LINK_LINE_OUT_RING;
pin_mask &= ~BADGE_LINK_LINE_OUT_TIP;
#ifdef USER_WARNINGS_ENABLED
printf("cannot enable line out badge link without cable plugged in for safety reasons\n");
} else {
printf("badge link enabled on line out. please make sure not to have headphones or sound sources connected before transmitting data.\n");
#endif
}
}
}
if(pin_mask & BADGE_LINK_LINE_IN_RING) max7321s_set_pinmode_output(BADGE_LINK_LINE_IN_RING_ENABLE_PIN, 1);
if(pin_mask & BADGE_LINK_LINE_IN_TIP) max7321s_set_pinmode_output(BADGE_LINK_LINE_IN_TIP_ENABLE_PIN, 1);
if(pin_mask & BADGE_LINK_LINE_OUT_RING) max7321s_set_pinmode_output(BADGE_LINK_LINE_OUT_RING_ENABLE_PIN, 1);
if(pin_mask & BADGE_LINK_LINE_OUT_TIP) max7321s_set_pinmode_output(BADGE_LINK_LINE_OUT_TIP_ENABLE_PIN, 1);
if(pin_mask & BADGE_LINK_LINE_IN_RING) max7321s_set_pin(BADGE_LINK_LINE_IN_RING_ENABLE_PIN, !state);
if(pin_mask & BADGE_LINK_LINE_IN_TIP) max7321s_set_pin(BADGE_LINK_LINE_IN_TIP_ENABLE_PIN, !state);
if(pin_mask & BADGE_LINK_LINE_OUT_RING) max7321s_set_pin(BADGE_LINK_LINE_OUT_RING_ENABLE_PIN, !state);
if(pin_mask & BADGE_LINK_LINE_OUT_TIP) max7321s_set_pin(BADGE_LINK_LINE_OUT_TIP_ENABLE_PIN, !state);
max7321s_update();
badge_link_enabled = (badge_link_enabled & (~pin_mask)) | (pin_mask & (state ? 255: 0));
return spio_badge_link_get_active(pin_mask);
}
#endif
uint8_t spio_badge_link_disable(uint8_t pin_mask){
return spio_badge_link_set(pin_mask, 0);
}
uint8_t spio_badge_link_enable(uint8_t pin_mask){
return spio_badge_link_set(pin_mask, 1);
}
......@@ -7,6 +7,7 @@ add_library(usermod_badge23 INTERFACE)
target_sources(usermod_badge23 INTERFACE
${CMAKE_CURRENT_LIST_DIR}/mp_hardware.c
${CMAKE_CURRENT_LIST_DIR}/mp_audio.c
${CMAKE_CURRENT_LIST_DIR}/mp_badge_link.c
${CMAKE_CURRENT_LIST_DIR}/mp_synth.c
${CMAKE_CURRENT_LIST_DIR}/mp_kernel.c
)
......
// probably doesn't need all of these idk
#include <stdio.h>
#include <string.h>
#include "py/runtime.h"
#include "py/mphal.h"
#include "mphalport.h"
#include "modmachine.h"
#include "extmod/virtpin.h"
#include "machine_rtc.h"
#include "py/builtin.h"
#include "py/runtime.h"
#include "badge23/audio.h"
#include "badge23/leds.h"
#include "badge23/captouch.h"
#include "badge23/display.h"
#include "badge23/spio.h"
#include "badge23/espan.h"
#include "badge23_hwconfig.h"
mp_obj_t mp_ctx_from_ctx(Ctx *ctx);
STATIC mp_obj_t mp_get_active(mp_obj_t pin_mask) {
return mp_obj_new_int(spio_badge_link_get_active(mp_obj_get_int(pin_mask)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_get_active_obj, mp_get_active);
STATIC mp_obj_t mp_enable(mp_obj_t pin_mask) {
return mp_obj_new_int(spio_badge_link_enable(mp_obj_get_int(pin_mask)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_enable_obj, mp_enable);
STATIC mp_obj_t mp_disable(mp_obj_t pin_mask) {
return mp_obj_new_int(spio_badge_link_disable(mp_obj_get_int(pin_mask)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_disable_obj, mp_disable);
STATIC const mp_rom_map_elem_t mp_module_badge_link_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_badge_link) },
{ MP_ROM_QSTR(MP_QSTR_get_active), MP_ROM_PTR(&mp_get_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&mp_enable_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&mp_disable_obj) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_IN_TIP), MP_ROM_INT(BADGE_LINK_LINE_IN_TIP) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_IN_RING), MP_ROM_INT(BADGE_LINK_LINE_IN_RING) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_OUT_TIP), MP_ROM_INT(BADGE_LINK_LINE_OUT_TIP) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_OUT_RING), MP_ROM_INT(BADGE_LINK_LINE_OUT_RING) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_ALL), MP_ROM_INT(BADGE_LINK_ALL) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_IN_TIP_PIN), MP_ROM_INT(BADGE_LINK_LINE_IN_TIP_PIN) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_IN_RING_PIN), MP_ROM_INT(BADGE_LINK_LINE_IN_RING_PIN) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_OUT_TIP_PIN), MP_ROM_INT(BADGE_LINK_LINE_OUT_TIP_PIN) },
{ MP_ROM_QSTR(MP_QSTR_BADGE_LINK_LINE_OUT_RING_PIN), MP_ROM_INT(BADGE_LINK_LINE_OUT_RING_PIN) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_badge_link_globals, mp_module_badge_link_globals_table);
const mp_obj_module_t mp_module_badge_link = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_badge_link_globals,
};
MP_REGISTER_MODULE(MP_QSTR_badge_link, mp_module_badge_link);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment