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"
/* 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;
static int ui_bus_claimed = false;
/* HW V2.0: PCA9538ABS (8 Bit) */
#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)
{
int ret = 0;
@ -27,92 +68,152 @@ static int switch_i2c_bus(int* old_bus)
return -1;
*old_bus = i2c_get_bus_num();
if (*old_bus != ui_i2c_bus) {
ret = i2c_set_bus_num(ui_i2c_bus);
if (*old_bus != ioext_i2c_bus) {
ret = i2c_set_bus_num(ioext_i2c_bus);
}
ui_bus_claimed = true;
bus_claimed++;
return ret;
}
static int revert_i2c_bus(int bus)
static void revert_i2c_bus(int bus)
{
int ret = 0;
if (ui_i2c_bus != bus) {
ret = i2c_set_bus_num(bus);
if (ioext_i2c_bus != bus) {
(void)i2c_set_bus_num(bus);
}
ui_bus_claimed = false;
return ret;
bus_claimed--;
}
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)
static void detect_version(void)
{
int ret;
u8 temp;
uint8_t temp = 0;
/* Argument check */
if ((reg >= 8)) {
return -1;
hw_version = 0;
/* 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 (ui_bus_claimed == false) {
return -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 */
int detect_ui(void)
{
int bus;
int claim;
uint8_t val;
static int ui_detected = -1; /* -1: unitialized, 0: UI not available, 1: UI V1 detected ,2: UI V2 detected */
if (ui_detected < 0) {
claim = ui_claim_i2c_bus(&bus);
if (claim == 0) {
if ( 0 == ui_i2c_get_reg(0x00, &val,1))
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);
if (hw_version == 0) {
/* Try to detect PCA9538 on V2.x HW */
ret = i2c_read(CONFIG_UI_V2_I2C_ADDR, 0x00, 1, &temp, 1);
if (ret == 0) {
hw_version = 2;
}
}
return ui_detected;
}
static void init_io(void)
{
switch (hw_version) {
case 1: {
uint8_t dir[2] = { 0x00, 0x00 }; /* All IOs = Outputs */
(void)i2c_write(CONFIG_UI_V1_I2C_ADDR, PCA9539_CONF_REG, 1, dir, 2);
out_reg[0] = 0xFF;
out_reg[1] = 0xFF;
break;
}
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;
}
}
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_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 */