LNSC-2420-Firmware/src/led_chplex.c
Thomas Kolb df3211333e Properly shut down peripherals before entering deep sleep
This is most important for the LEDs and the RS485 interface. If any LED
is on when deep sleep is entered, it will stay on the whole sleep time,
drawing about 10 mA on the 3,3V rail.

The RS485 transceiver must be switched to RX mode, as it consumes about
30 mA from the 5V rail in TX mode.
2021-06-12 16:02:21 +02:00

122 lines
2.6 KiB
C

#include <libopencm3/stm32/gpio.h>
#include "pinout.h"
#include "led_chplex.h"
#define NUM_LEDs 6
static uint8_t led_index;
static uint8_t led_mask;
void led_chplex_init(void)
{
// set up required GPIOs
gpio_clear(LED_PORT, LED_ALL_PINS);
gpio_mode_setup(LED_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, LED_ALL_PINS);
// initialize charlieplex stepping
led_index = 0;
// all LEDs off by default
led_mask = 0;
}
void led_chplex_periodic(void)
{
// set all GPIOs to input to ensure the LEDs are properly switched off
gpio_mode_setup(LED_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, LED_ALL_PINS);
// apply the proper signals depending on LED index
if(led_mask & (1 << led_index)) {
switch(led_index)
{
case LED_CHPLEX_IDX_SOLAR_ON:
gpio_set(LED_PORT, LED_A_PIN);
gpio_clear(LED_PORT, LED_B_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_A_PIN | LED_B_PIN);
break;
case LED_CHPLEX_IDX_LOAD_ON:
gpio_set(LED_PORT, LED_B_PIN);
gpio_clear(LED_PORT, LED_C_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_B_PIN | LED_C_PIN);
break;
case LED_CHPLEX_IDX_ERR_TEMP:
gpio_set(LED_PORT, LED_B_PIN);
gpio_clear(LED_PORT, LED_A_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_A_PIN | LED_B_PIN);
break;
case LED_CHPLEX_IDX_ERR_LOAD:
gpio_set(LED_PORT, LED_C_PIN);
gpio_clear(LED_PORT, LED_B_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_B_PIN | LED_C_PIN);
break;
case LED_CHPLEX_IDX_CHARGE_PULSE:
gpio_set(LED_PORT, LED_A_PIN);
gpio_clear(LED_PORT, LED_C_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_A_PIN | LED_C_PIN);
break;
case LED_CHPLEX_IDX_DISCHARGE_PULSE:
gpio_set(LED_PORT, LED_C_PIN);
gpio_clear(LED_PORT, LED_A_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_A_PIN | LED_C_PIN);
break;
default:
// unknown index => do nothing and reset index
led_index = 0;
break;
}
}
led_index++;
if(led_index >= NUM_LEDs) {
led_index = 0;
}
}
void led_chplex_on(uint8_t idx)
{
led_mask |= (1 << idx);
}
void led_chplex_off(uint8_t idx)
{
led_mask &= ~(1 << idx);
}
void led_chplex_toggle(uint8_t idx)
{
led_mask ^= (1 << idx);
}
void led_chplex_mask(uint8_t mask)
{
led_mask = mask;
}
void led_chplex_deepsleep_prepare(void)
{
// set all GPIOs to input to ensure the LEDs are properly switched off
gpio_mode_setup(LED_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, LED_ALL_PINS);
}
void led_chplex_deepsleep_resume(void)
{
// nothing to do here
}