nmhw21: prepare UI v2.0 implementation

This commit is contained in:
Rene Straub 2018-11-02 07:13:02 +01:00
parent c0550c87fb
commit a962411cbf
2 changed files with 188 additions and 76 deletions

View File

@ -14,11 +14,52 @@
#include "ui.h" #include "ui.h"
/* TODO: Define as masks */
/* HW V1.0: PCA9539BS (16 Bit) */
#define UI_V1_TOP_LED_GREEN 6
#define UI_V1_TOP_LED_RED 7
#define UI_V1_BOTTOM_LED_GREEN 9
#define UI_V1_BOTTOM_LED_RED 8
static int ui_i2c_bus = 0; /* HW V2.0: PCA9538ABS (8 Bit) */
static int ui_bus_claimed = false; #define UI_V2_ID_0 0
#define UI_V2_ID_1 1
#define UI_V2_TOP_LED_GREEN 2
#define UI_V2_TOP_LED_RED 3
#define UI_V2_BOTTOM_LED_GREEN 6
#define UI_V2_BOTTOM_LED_RED 5
#define PCA9538_OUT_REG 0x01
#define PCA9538_CONF_REG 0x03
#define PCA9539_OUT_REG 0x02
#define PCA9539_CONF_REG 0x06
static int ioext_i2c_bus = 0;
/* -1: unitialized, 0: UI not available, 1: UI V1.x, 2: UI V2.x */
static int hw_version = -1;
static int bus_claimed = 0;
static uint8_t out_reg[2];
static void set_output(uint bit, bool state)
{
if (state) {
out_reg[bit/8U] &= ~(1U << (bit % 8U));
}
else {
out_reg[bit/8U] |= (1U << (bit % 8U));
}
}
static int switch_i2c_bus(int* old_bus) static int switch_i2c_bus(int* old_bus)
{ {
int ret = 0; int ret = 0;
@ -27,92 +68,152 @@ static int switch_i2c_bus(int* old_bus)
return -1; return -1;
*old_bus = i2c_get_bus_num(); *old_bus = i2c_get_bus_num();
if (*old_bus != ui_i2c_bus) { if (*old_bus != ioext_i2c_bus) {
ret = i2c_set_bus_num(ui_i2c_bus); ret = i2c_set_bus_num(ioext_i2c_bus);
} }
ui_bus_claimed = true; bus_claimed++;
return ret; return ret;
} }
static int revert_i2c_bus(int bus) static void revert_i2c_bus(int bus)
{ {
int ret = 0; if (ioext_i2c_bus != bus) {
if (ui_i2c_bus != bus) { (void)i2c_set_bus_num(bus);
ret = i2c_set_bus_num(bus);
} }
ui_bus_claimed = false; bus_claimed--;
return ret;
} }
static void detect_version(void)
void ui_i2c_init(int i2c_bus)
{
ui_i2c_bus = i2c_bus;
}
int ui_claim_i2c_bus(int* old_bus)
{
return switch_i2c_bus(old_bus);
}
int ui_release_i2c_bus(int bus)
{
return revert_i2c_bus(bus);
}
static int ui_i2c_get_reg(uint32_t reg, u8* val, int version)
{ {
int ret; int ret;
u8 temp; uint8_t temp = 0;
/* Argument check */ hw_version = 0;
if ((reg >= 8)) {
return -1; /* Try to detect PCA9539 on V1.x HW */
ret = i2c_read(CONFIG_UI_V1_I2C_ADDR, 0x00, 1, &temp, 1);
if (ret == 0) {
hw_version = 1;
} }
/* State check. Has bus been claimed */ if (hw_version == 0) {
if (ui_bus_claimed == false) { /* Try to detect PCA9538 on V2.x HW */
return -2; ret = i2c_read(CONFIG_UI_V2_I2C_ADDR, 0x00, 1, &temp, 1);
if (ret == 0) {
hw_version = 2;
} }
*val = 0;
if (version == 2) {
ret = i2c_read(CONFIG_UIV2_I2C_ADDR, reg & 0xFF, 1, &temp, 1);
} }
else{
ret = i2c_read(CONFIG_UI_I2C_ADDR, reg & 0xFF, 1, &temp, 1);
}
if (ret == 0)
*val = temp;
return ret;
} }
/* version 2: V2.0 UI , 1: V1.0 UI */ static void init_io(void)
int detect_ui(void)
{ {
int bus; switch (hw_version) {
int claim; case 1: {
uint8_t val; uint8_t dir[2] = { 0x00, 0x00 }; /* All IOs = Outputs */
static int ui_detected = -1; /* -1: unitialized, 0: UI not available, 1: UI V1 detected ,2: UI V2 detected */ (void)i2c_write(CONFIG_UI_V1_I2C_ADDR, PCA9539_CONF_REG, 1, dir, 2);
if (ui_detected < 0) {
claim = ui_claim_i2c_bus(&bus); out_reg[0] = 0xFF;
if (claim == 0) { out_reg[1] = 0xFF;
if ( 0 == ui_i2c_get_reg(0x00, &val,1)) break;
ui_detected = 1;
else {
if ( 0 == ui_i2c_get_reg(0x00, &val,2))
ui_detected = 2;
else
ui_detected = 0;
} }
ui_release_i2c_bus(bus);
case 2: {
uint8_t dir[1] = { 0x03 }; /* Keep IO 0 & 1 as inputs */
(void)i2c_write(CONFIG_UI_V2_I2C_ADDR, PCA9538_CONF_REG, 1, dir, 1);
out_reg[0] = 0xFF;
break;
} }
default:
break;
} }
return ui_detected; }
static void v1_set_top_leds(int red, int green)
{
set_output(UI_V1_TOP_LED_RED, red);
set_output(UI_V1_TOP_LED_GREEN, green);
(void)i2c_write(CONFIG_UI_V1_I2C_ADDR, PCA9539_OUT_REG, 1, out_reg, 2);
}
static void v1_set_bottom_leds(int red, int green)
{
set_output(UI_V1_BOTTOM_LED_RED, red);
set_output(UI_V1_BOTTOM_LED_GREEN, green);
(void)i2c_write(CONFIG_UI_V1_I2C_ADDR, PCA9539_OUT_REG, 1, out_reg, 2);
}
static void v2_set_top_leds(int red, int green)
{
set_output(UI_V2_TOP_LED_RED, red);
set_output(UI_V2_TOP_LED_GREEN, green);
(void)i2c_write(CONFIG_UI_V2_I2C_ADDR, PCA9538_OUT_REG, 1, out_reg, 1);
}
static void v2_set_bottom_leds(int red, int green)
{
set_output(UI_V2_BOTTOM_LED_RED, red);
set_output(UI_V2_BOTTOM_LED_GREEN, green);
(void)i2c_write(CONFIG_UI_V2_I2C_ADDR, PCA9538_OUT_REG, 1, out_reg, 1);
} }
void ui_init(int i2c_bus)
{
int bus = -1;
int claimed;
ioext_i2c_bus = i2c_bus;
claimed = switch_i2c_bus(&bus);
if (claimed == 0) {
detect_version();
init_io();
}
revert_i2c_bus(bus);
}
int ui_version(void)
{
return hw_version;
}
void ui_set_top_led(int red, int green)
{
int bus = -1;
int claimed;
claimed = switch_i2c_bus(&bus);
if (claimed == 0) {
switch (hw_version) {
case 1: v1_set_top_leds(red, green); break;
case 2: v2_set_top_leds(red, green); break;
default: break;
}
revert_i2c_bus(bus);
}
}
void ui_set_bottom_led(int red, int green)
{
int bus = -1;
int claimed;
claimed = switch_i2c_bus(&bus);
if (claimed == 0) {
switch (hw_version) {
case 1: v1_set_bottom_leds(red, green); break;
case 2: v2_set_bottom_leds(red, green); break;
default: break;
}
revert_i2c_bus(bus);
}
}

View File

@ -13,16 +13,27 @@
#define CONFIG_UI_I2C_BUS 1 #define CONFIG_UI_I2C_BUS 1
#define CONFIG_UI_I2C_ADDR 0x74 /* Pages 0 and 1, Pages 2 and 3 -> 0x59 */
#define CONFIG_UIV2_I2C_ADDR 0x70 /* Pages 0 and 1, Pages 2 and 3 -> 0x59 */ #define CONFIG_UI_V1_I2C_ADDR 0x74
#define CONFIG_UI_V2_I2C_ADDR 0x70
extern void ui_i2c_init(int i2c_bus);
extern int ui_claim_i2c_bus(int* old_bus); /**
extern int ui_release_i2c_bus(int bus); * Initializes user interface module.
*
* @param i2c_bus Number of I2C bus UI is attached to.
*/
extern void ui_init(int i2c_bus);
extern int detect_ui(void); /**
* Returns hardware version of UI.
*
* @return 0: No or unknown UI
* >0: Version (e.g. 1 or 2)
*/
extern int ui_version(void);
void ui_set_top_led(int red, int green);
void ui_set_bottom_led(int red, int green);
#endif /* UI_H */ #endif /* UI_H */