circuitpython/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

191 lines
6.4 KiB
C
Raw Normal View History

/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Damien P. George
* Copyright (c) 2022 David Lechner <david@pybricks.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mphal.h"
#include "hub_display.h"
#include STM32_HAL_H
#define I2C_ADDR 0x28
// Registers
#define DEVICE_CONFIG0 0x00
#define DEVICE_CONFIG1 0x01
#define LED_CONFIG0 0x02
#define BANK_BRIGHTNESS 0x03
#define BANK_A_COLOR 0x04
#define BANK_B_COLOR 0x05
#define BANK_C_COLOR 0x06
#define LED0_BRIGHTNESS 0x07
#define LED1_BRIGHTNESS 0x08
#define LED2_BRIGHTNESS 0x09
#define LED3_BRIGHTNESS 0x0A
#define OUT0_COLOR 0x0B
#define OUT1_COLOR 0x0C
#define OUT2_COLOR 0x0D
#define OUT3_COLOR 0x0E
#define OUT4_COLOR 0x0F
#define OUT5_COLOR 0x10
#define OUT6_COLOR 0x11
#define OUT7_COLOR 0x12
#define OUT8_COLOR 0x13
#define OUT9_COLOR 0x14
#define OUT10_COLOR 0x15
#define OUT11_COLOR 0x16
#define RESET 0x17
// Flags
#define DEVICE_CONFIG0_CHIP_EN (1 << 6)
#define DEVICE_CONFIG1_LOG_SCALE_EN (1 << 5)
#define DEVICE_CONFIG1_POWER_SAVE_EN (1 << 4)
#define DEVICE_CONFIG1_AUTO_INCR_EN (1 << 3)
#define DEVICE_CONFIG1_PWM_DITHERING_EN (1 << 2)
#define DEVICE_CONFIG1_MAX_CURRENT_OPTION (1 << 1)
#define DEVICE_CONFIG1_LED_GLOBAL_OFF (1 << 0)
#define LED_CONFIG0_LED3_BANK_EN (1 << 3)
#define LED_CONFIG0_LED2_BANK_EN (1 << 2)
#define LED_CONFIG0_LED1_BANK_EN (1 << 1)
#define LED_CONFIG0_LED0_BANK_EN (1 << 0)
#define LP50XX_NUM_CH 6
// channel mapping:
// CH 0 = battery LED - red
// CH 1 = battery LED - green
// CH 2 = battery LED - blue
// CH 3 = status LED - red
// CH 4 = status LED - green
// CH 5 = status LED - blue
#define FMPI2C_CONVERT_TIMINGS(PRESC, SCLDEL, SDADEL, SCLH, SCLL) \
(((PRESC) << FMPI2C_TIMINGR_PRESC_Pos) | \
((SCLDEL) << FMPI2C_TIMINGR_SCLDEL_Pos) | \
((SDADEL) << FMPI2C_TIMINGR_SDADEL_Pos) | \
((SCLH) << FMPI2C_TIMINGR_SCLH_Pos) | \
((SCLL) << FMPI2C_TIMINGR_SCLL_Pos))
static FMPI2C_HandleTypeDef hub_display_i2c;
static bool hub_display_init;
static struct {
uint8_t reg;
uint8_t values[LP50XX_NUM_CH];
} __attribute__((packed)) hub_display_data = {
.reg = OUT0_COLOR,
};
void HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef *hfmpi2c) {
__HAL_RCC_FMPI2C1_CLK_ENABLE();
mp_hal_pin_config(pyb_pin_LED_SCL, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 4);
mp_hal_pin_config(pyb_pin_LED_SDA, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 4);
}
void HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef *hfmpi2c) {
__HAL_RCC_FMPI2C1_CLK_DISABLE();
__HAL_RCC_FMPI2C1_FORCE_RESET();
__HAL_RCC_FMPI2C1_RELEASE_RESET();
mp_hal_pin_config(pyb_pin_LED_SCL, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
mp_hal_pin_config(pyb_pin_LED_SDA, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
}
static void hub_display_i2c_init(void) {
hub_display_i2c.Instance = FMPI2C1;
hub_display_i2c.Init.Timing = FMPI2C_CONVERT_TIMINGS(0, 4, 0, 19, 28);
hub_display_i2c.Init.OwnAddress1 = 0;
hub_display_i2c.Init.AddressingMode = FMPI2C_ADDRESSINGMODE_7BIT;
hub_display_i2c.Init.DualAddressMode = FMPI2C_DUALADDRESS_DISABLE;
hub_display_i2c.Init.OwnAddress2 = 0;
hub_display_i2c.Init.OwnAddress2Masks = FMPI2C_OA2_NOMASK;
hub_display_i2c.Init.GeneralCallMode = FMPI2C_GENERALCALL_DISABLE;
hub_display_i2c.Init.NoStretchMode = FMPI2C_NOSTRETCH_DISABLE;
HAL_FMPI2C_Init(&hub_display_i2c);
}
void hub_display_set(uint8_t led, uint16_t value) {
if (led >= LP50XX_NUM_CH) {
return;
}
hub_display_data.values[led] = value >> 8;
}
void hub_display_update(void) {
if (!hub_display_init) {
return;
}
HAL_FMPI2C_Master_Transmit(&hub_display_i2c, I2C_ADDR, (uint8_t *)&hub_display_data,
sizeof(hub_display_data), HAL_MAX_DELAY);
}
void hub_display_on(void) {
if (hub_display_init) {
return;
}
hub_display_i2c_init();
mp_hal_pin_output(pyb_pin_LED_EN);
mp_hal_pin_high(pyb_pin_LED_EN);
static const struct {
uint8_t reg;
uint8_t values[11];
} __attribute__((packed)) init_data = {
.reg = DEVICE_CONFIG0,
.values = {
[DEVICE_CONFIG0] = DEVICE_CONFIG0_CHIP_EN,
[DEVICE_CONFIG1] = DEVICE_CONFIG1_POWER_SAVE_EN | DEVICE_CONFIG1_PWM_DITHERING_EN | DEVICE_CONFIG1_AUTO_INCR_EN,
[LED_CONFIG0] = 0,
[BANK_BRIGHTNESS] = 0,
[BANK_A_COLOR] = 0,
[BANK_B_COLOR] = 0,
[BANK_C_COLOR] = 0,
[LED0_BRIGHTNESS] = 51, // battery LED
[LED1_BRIGHTNESS] = 38, // status LED
[LED2_BRIGHTNESS] = 0,
[LED3_BRIGHTNESS] = 0,
}
};
HAL_FMPI2C_Master_Transmit(&hub_display_i2c, I2C_ADDR, (uint8_t *)&init_data,
sizeof(init_data), HAL_MAX_DELAY);
hub_display_init = true;
}
void hub_display_off(void) {
if (!hub_display_init) {
return;
}
HAL_FMPI2C_DeInit(&hub_display_i2c);
mp_hal_pin_config(pyb_pin_LED_EN, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
hub_display_init = false;
}