Skip to content

Commit

Permalink
adc
Browse files Browse the repository at this point in the history
  • Loading branch information
ducalex committed Aug 17, 2024
1 parent 183d481 commit 1fa6459
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 93 deletions.
2 changes: 1 addition & 1 deletion components/retro-go/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(COMPONENT_SRCDIRS ". drivers/audio fonts libs/netplay libs/lodepng")
set(COMPONENT_SRCDIRS ". drivers/audio drivers/input fonts libs/netplay libs/lodepng")
set(COMPONENT_ADD_INCLUDEDIRS ". libs/netplay libs/lodepng")

message(STATUS "ESP-IDF version: ${IDF_VER}")
Expand Down
98 changes: 98 additions & 0 deletions components/retro-go/drivers/input/adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "rg_system.h"
#include "rg_input.h"

#include <driver/adc.h>
#include <string.h>

#define MAX_INPUTS 8

static uint8_t current_attenuation[2][8];

static struct {int16_t unit, channel;} inputs[MAX_INPUTS];
static size_t inputs_count;

static bool adc_set_atten(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten)
{
if (current_attenuation[unit][channel] == atten)
{
return true;
}
else if (unit == ADC_UNIT_1 && adc1_config_channel_atten(channel, atten) != ESP_OK)
{
current_attenuation[unit][channel] = atten;
return true;
}
else if (unit == ADC_UNIT_2 && adc2_config_channel_atten(channel, atten) == ESP_OK)
{
current_attenuation[unit][channel] = atten;
return true;
}
return false;
}

static bool adc_get_raw(adc_unit_t unit, adc_channel_t channel, int *value)
{
if (unit == ADC_UNIT_1)
{
*value = adc1_get_raw(channel);
return true;
}
else if (unit == ADC_UNIT_2)
{
if (adc2_get_raw(channel, ADC_WIDTH_MAX - 1, &value) != ESP_OK)
RG_LOGE("ADC2 reading failed, this can happen while wifi is active.");
return true;
}
return false;
}

static bool driver_init(void)
{
adc1_config_width(ADC_WIDTH_MAX - 1);
inputs_count = 0;
}

static bool driver_deinit(void)
{
// Nothing to do
}

static bool driver_add_input(int unit, int channel, int atten, int arg2, void *arg3, size_t *index)
{
RG_ASSERT(inputs_count < MAX_INPUTS, "Too many inputs specified!");
if (!adc_set_atten(unit, channel, atten))
{
RG_LOGE("adc_set_atten(%d, %d, %d) failed.", unit, channel, atten);
return false;
}
inputs[inputs_count].unit = unit;
inputs[inputs_count].channel = channel;
if (index) *index = inputs_count;
inputs_count++;
return true;
}

static bool driver_read_inputs(size_t index, size_t count, int *values_out)
{
RG_ASSERT(index < inputs_count, "index out of range");
for (size_t i = index, max = RG_MIN(index + count, inputs_count); i < max; ++i)
adc_get_raw(inputs[i].unit, inputs[i].channel, &values_out[i - index]);
return true;
}

static bool driver_read(int unit, int channel, int atten, int arg2, void *arg3, int *value_out)
{
// FIXME: Must apply read current attenuation, apply new one, then restore at the end
if (adc_set_atten(unit, channel, atten))
return adc_get_raw(unit, channel, value_out);
return false;
}

const rg_input_driver_t RG_DRIVER_INPUT_ADC = {
.name = "ADC",
.init = driver_init,
.deinit = driver_deinit,
.add_input = driver_add_input,
.read_inputs = driver_read_inputs,
.read = driver_read,
};
14 changes: 9 additions & 5 deletions components/retro-go/drivers/input/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#define MAX_INPUTS 16

static gpio_num_t inputs[MAX_INPUTS];
static uint8_t inputs[MAX_INPUTS];
static size_t inputs_count;

static bool driver_init(void)
Expand All @@ -22,16 +22,18 @@ static bool driver_deinit(void)
static bool driver_add_input(int port, int pin_num, int pull_mode, int arg2, void *arg3, size_t *index)
{
RG_ASSERT(inputs_count < MAX_INPUTS, "Too many inputs specified!");
RG_ASSERT_ARG(port == 0 && pin_num >= 0 && pin_num < 255);

esp_err_t ret = gpio_set_direction(pin_num, GPIO_MODE_INPUT);
if (ret == ESP_OK)
{
gpio_set_pull_mode(pin_num, pull_mode);
inputs[inputs_count++] = pin_num;
if (index)
*index = inputs_count - 1;
inputs[inputs_count] = pin_num;
if (index) *index = inputs_count;
inputs_count++;
return true;
}
RG_LOGE("gpio_set_direction(%d) failed: %d", pin_num, ret);
RG_LOGE("gpio_set_direction(%d) failed: %d", pin_num, (int)ret);
return false;
}

Expand All @@ -45,6 +47,8 @@ static bool driver_read_inputs(size_t index, size_t count, int *values_out)

static bool driver_read(int port, int pin_num, int pull_mode, int arg2, void *arg3, int *value_out)
{
RG_ASSERT_ARG(port == 0 && pin_num >= 0 && pin_num < 255);
// TODO: Must read current direction and pull mode, then set input/pull and read, then restore direction/pull
return false;
}

Expand Down
63 changes: 9 additions & 54 deletions components/retro-go/rg_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
static esp_adc_cal_characteristics_t adc_chars;
#endif

#ifdef RG_GAMEPAD_ADC_MAP
static rg_keymap_adc_t keymap_adc[] = RG_GAMEPAD_ADC_MAP;
#endif
#ifdef RG_GAMEPAD_I2C_MAP
static rg_keymap_i2c_t keymap_i2c[] = RG_GAMEPAD_I2C_MAP;
#endif
Expand All @@ -36,11 +33,15 @@ static bool input_task_running = false;
static uint32_t gamepad_state = -1; // _Atomic
static rg_battery_t battery_state = {0};

extern const rg_input_driver_t RG_DRIVER_INPUT_GPIO;
static const rg_input_driver_t *input_drivers[4];
static size_t input_drivers_count = 0;

extern const rg_input_driver_t RG_DRIVER_INPUT_ADC;
extern const rg_input_driver_t RG_DRIVER_INPUT_GPIO;
#define GPIO &RG_DRIVER_INPUT_GPIO, 0
#define ADC1 &RG_DRIVER_INPUT_ADC, ADC_UNIT_1
#define ADC2 &RG_DRIVER_INPUT_ADC, ADC_UNIT_2

static const rg_keymap_desc_t keymap_config[] = RG_GAMEPAD_MAP;
static rg_keymap_t keymap[RG_COUNT(keymap_config)];
static size_t keymap_count;
Expand All @@ -60,25 +61,6 @@ static size_t register_driver(const rg_input_driver_t *driver)

#define UPDATE_GLOBAL_MAP(keymap)

#ifdef ESP_PLATFORM
static inline int adc_get_raw(adc_unit_t unit, adc_channel_t channel)
{
if (unit == ADC_UNIT_1)
{
return adc1_get_raw(channel);
}
else if (unit == ADC_UNIT_2)
{
int adc_raw_value = -1;
if (adc2_get_raw(channel, ADC_WIDTH_MAX - 1, &adc_raw_value) != ESP_OK)
RG_LOGE("ADC2 reading failed, this can happen while wifi is active.");
return adc_raw_value;
}
RG_LOGE("Invalid ADC unit %d", (int)unit);
return -1;
}
#endif

bool rg_input_read_battery_raw(rg_battery_t *out)
{
uint32_t raw_value = 0;
Expand All @@ -88,8 +70,8 @@ bool rg_input_read_battery_raw(rg_battery_t *out)
#if RG_BATTERY_DRIVER == 1 /* ADC */
for (int i = 0; i < 4; ++i)
{
int value = adc_get_raw(RG_BATTERY_ADC_UNIT, RG_BATTERY_ADC_CHANNEL);
if (value < 0)
int value;
if (!RG_DRIVER_INPUT_ADC.read(RG_BATTERY_ADC_UNIT, RG_BATTERY_ADC_CHANNEL, ADC_ATTEN_DB_11, 0, 0, &value))
return false;
raw_value += esp_adc_cal_raw_to_voltage(value, &adc_chars);
}
Expand Down Expand Up @@ -135,16 +117,6 @@ bool rg_input_read_gamepad_raw(uint32_t *out)
state |= mapping->key;
}

#if defined(RG_GAMEPAD_ADC_MAP)
for (size_t i = 0; i < RG_COUNT(keymap_adc); ++i)
{
const rg_keymap_adc_t *mapping = &keymap_adc[i];
int value = adc_get_raw(mapping->unit, mapping->channel);
if (value >= mapping->min && value <= mapping->max)
state |= mapping->key;
}
#endif

#if defined(RG_GAMEPAD_I2C_MAP)
uint32_t buttons = 0;
uint8_t data[5];
Expand Down Expand Up @@ -286,22 +258,6 @@ void rg_input_init(void)
}
}

#if defined(RG_GAMEPAD_ADC_MAP)
RG_LOGI("Initializing ADC gamepad driver...");
adc1_config_width(ADC_WIDTH_MAX - 1);
for (size_t i = 0; i < RG_COUNT(keymap_adc); ++i)
{
const rg_keymap_adc_t *mapping = &keymap_adc[i];
if (mapping->unit == ADC_UNIT_1)
adc1_config_channel_atten(mapping->channel, mapping->atten);
else if (mapping->unit == ADC_UNIT_2)
adc2_config_channel_atten(mapping->channel, mapping->atten);
else
RG_LOGE("Invalid ADC unit %d!", (int)mapping->unit);
}
UPDATE_GLOBAL_MAP(keymap_adc);
#endif

#if defined(RG_GAMEPAD_I2C_MAP)
RG_LOGI("Initializing I2C gamepad driver...");
rg_i2c_init();
Expand Down Expand Up @@ -331,13 +287,12 @@ void rg_input_init(void)
RG_LOGI("Initializing ADC battery driver...");
if (RG_BATTERY_ADC_UNIT == ADC_UNIT_1)
{
adc1_config_width(ADC_WIDTH_MAX - 1); // there is no adc2_config_width
adc1_config_channel_atten(RG_BATTERY_ADC_CHANNEL, ADC_ATTEN_DB_11);
register_driver(&RG_DRIVER_INPUT_ADC);
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_MAX - 1, 1100, &adc_chars);
}
else if (RG_BATTERY_ADC_UNIT == ADC_UNIT_2)
{
adc2_config_channel_atten(RG_BATTERY_ADC_CHANNEL, ADC_ATTEN_DB_11);
register_driver(&RG_DRIVER_INPUT_ADC);
esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_11, ADC_WIDTH_MAX - 1, 1100, &adc_chars);
}
else
Expand Down
21 changes: 1 addition & 20 deletions components/retro-go/rg_input.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef struct
void (*deinit)(void);
bool (*add_input)(int port, int channel, int arg1, int arg2, void *arg3, size_t *index);
bool (*read_inputs)(int index, int count, int *values_out);
bool (*read)(int port, int pin_num, int pull_mode, int arg2, void *arg3, int *value_out);
bool (*read)(int port, int channel, int arg1, int arg2, void *arg3, int *value_out);
} rg_input_driver_t;

typedef struct
Expand All @@ -55,25 +55,6 @@ typedef struct
void *arg3;
} rg_keymap_desc_t;

// #define RG_GAMEPAD_ADC_MAP {{}, ...} to use ADC driver
typedef struct
{
rg_key_t key;
int unit; // adc_unit_t
int channel;// adc_channel_t
int atten; // adc_atten_t
int min, max;
} rg_keymap_adc_t;

// #define RG_GAMEPAD_GPIO_MAP {{}, ...} to use GPIO driver
typedef struct
{
rg_key_t key;
int num; // gpio_num_t
int pull; // gpio_pull_mode_t
int level; // 0-1
} rg_keymap_gpio_t;

// #define RG_GAMEPAD_I2C_MAP {{}, ...} to use I2C driver
typedef struct
{
Expand Down
23 changes: 10 additions & 13 deletions components/retro-go/targets/odroid-go/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,17 @@
ILI9341_CMD(0xE1, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F);

// Input
// Refer to rg_input.h to see all available RG_KEY_* and RG_GAMEPAD_*_MAP types
#define RG_GAMEPAD_ADC_MAP {\
{RG_KEY_UP, ADC_UNIT_1, ADC_CHANNEL_7, ADC_ATTEN_DB_11, 3072, 4096},\
{RG_KEY_DOWN, ADC_UNIT_1, ADC_CHANNEL_7, ADC_ATTEN_DB_11, 1024, 3071},\
{RG_KEY_LEFT, ADC_UNIT_1, ADC_CHANNEL_6, ADC_ATTEN_DB_11, 3072, 4096},\
{RG_KEY_RIGHT, ADC_UNIT_1, ADC_CHANNEL_6, ADC_ATTEN_DB_11, 1024, 3071},\
}
#define RG_GAMEPAD_MAP {\
{RG_KEY_SELECT, 0, 0, GPIO, GPIO_NUM_27, GPIO_PULLUP_ONLY},\
{RG_KEY_START, 0, 0, GPIO, GPIO_NUM_39, GPIO_FLOATING },\
{RG_KEY_MENU, 0, 0, GPIO, GPIO_NUM_13, GPIO_PULLUP_ONLY},\
{RG_KEY_OPTION, 0, 0, GPIO, GPIO_NUM_0, GPIO_FLOATING },\
{RG_KEY_A, 0, 0, GPIO, GPIO_NUM_32, GPIO_PULLUP_ONLY},\
{RG_KEY_B, 0, 0, GPIO, GPIO_NUM_33, GPIO_PULLUP_ONLY},\
{RG_KEY_UP, 3072, 4096, ADC1, ADC_CHANNEL_7, ADC_ATTEN_DB_11},\
{RG_KEY_DOWN, 1024, 3071, ADC1, ADC_CHANNEL_7, ADC_ATTEN_DB_11},\
{RG_KEY_LEFT, 3072, 4096, ADC1, ADC_CHANNEL_6, ADC_ATTEN_DB_11},\
{RG_KEY_RIGHT, 1024, 3071, ADC1, ADC_CHANNEL_6, ADC_ATTEN_DB_11},\
{RG_KEY_SELECT, 0, 0, GPIO, GPIO_NUM_27, GPIO_PULLUP_ONLY },\
{RG_KEY_START, 0, 0, GPIO, GPIO_NUM_39, GPIO_FLOATING },\
{RG_KEY_MENU, 0, 0, GPIO, GPIO_NUM_13, GPIO_PULLUP_ONLY },\
{RG_KEY_OPTION, 0, 0, GPIO, GPIO_NUM_0, GPIO_FLOATING },\
{RG_KEY_A, 0, 0, GPIO, GPIO_NUM_32, GPIO_PULLUP_ONLY },\
{RG_KEY_B, 0, 0, GPIO, GPIO_NUM_33, GPIO_PULLUP_ONLY },\
}

// Battery
Expand Down

0 comments on commit 1fa6459

Please sign in to comment.