mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-05-12 19:53:18 -04:00
echoplayer: implement ADC to read battery voltage
Change-Id: I8043e7d2f02c10cb8c9d9ec59b7d216945431481
This commit is contained in:
parent
684b3d8c49
commit
acd3a5f0ce
9 changed files with 402 additions and 27 deletions
|
|
@ -1,25 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2025 by Aidan MacDonald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "adc.h"
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
}
|
||||
140
firmware/target/arm/stm32/echoplayer/adc-echoplayer.c
Normal file
140
firmware/target/arm/stm32/echoplayer/adc-echoplayer.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2026 by Aidan MacDonald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "adc.h"
|
||||
#include "mutex.h"
|
||||
#include "kernel.h"
|
||||
#include "fixedpoint.h"
|
||||
#include "regs/stm32h743/adc.h"
|
||||
#include "regs/stm32h743/rcc.h"
|
||||
|
||||
#define VREF_MV 3300
|
||||
|
||||
static volatile void *const adc3 = (void *)ITA_ADC3;
|
||||
static struct mutex adc_mutex;
|
||||
|
||||
static void set_smptime(volatile void *adcbase, int channel, uint32_t smpval)
|
||||
{
|
||||
uint32_t reg_off = ITO_ADC_SMPR1;
|
||||
if (channel > 10)
|
||||
{
|
||||
reg_off = ITO_ADC_SMPR2;
|
||||
channel -= 10;
|
||||
}
|
||||
|
||||
volatile uint32_t *reg = adcbase + reg_off;
|
||||
uint32_t reg_val = *reg;
|
||||
|
||||
reg_val &= ~(0x7 << (channel * 3));
|
||||
reg_val |= smpval << (channel * 3);
|
||||
|
||||
*reg = reg_val;
|
||||
}
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
mutex_init(&adc_mutex);
|
||||
reg_writef(RCC_AHB4ENR, ADC3EN(1));
|
||||
|
||||
/* Power up ADC */
|
||||
reg_writelf(adc3, ADC_CR, DEEPPWD(0));
|
||||
reg_writelf(adc3, ADC_CR, ADVREGEN(1));
|
||||
while (!reg_readlf(adc3, ADC_ISR, LDORDY));
|
||||
|
||||
/* Run calibration */
|
||||
reg_writelf(adc3, ADC_CR, ADCALDIF(0), ADCALLIN(1), ADCAL(1));
|
||||
while (reg_readlf(adc3, ADC_CR, ADCAL));
|
||||
|
||||
/* Enable the ADC */
|
||||
reg_assignlf(adc3, ADC_ISR, ADRDY(1));
|
||||
reg_writelf(adc3, ADC_CR, ADEN(1));
|
||||
while (!reg_readlf(adc3, ADC_ISR, ADRDY));
|
||||
|
||||
/* Set sampling times for each channel (387.5 cycles @ 6 MHz = 64.5us) */
|
||||
set_smptime(adc3, ADC_CHANNEL_VBUS, BV_ADC_SMPR1_SMP0_387_5CYCLE);
|
||||
set_smptime(adc3, ADC_CHANNEL_BATTERY, BV_ADC_SMPR1_SMP0_387_5CYCLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts raw ADC reading to millivolts, assuming the
|
||||
* ADC samples the output of a voltage divider as in the
|
||||
* following circuit:
|
||||
*
|
||||
* [VIN]---[R1]
|
||||
* |
|
||||
* +----[ADC]
|
||||
* |
|
||||
* [R2]
|
||||
* |
|
||||
* [GND]
|
||||
*
|
||||
* The value returned is the voltage at the VIN node.
|
||||
*/
|
||||
static uint32_t scale_adc_val(uint32_t raw_val,
|
||||
uint32_t vref_mV,
|
||||
uint32_t r1_ohms,
|
||||
uint32_t r2_ohms)
|
||||
{
|
||||
/*
|
||||
* Finds the best fracbits value which doesn't overflow.
|
||||
* GCC will optimize this loop to a constant.
|
||||
*/
|
||||
uint32_t fracbits = 16;
|
||||
uint32_t conv_fac;
|
||||
for (; fracbits > 0; --fracbits)
|
||||
{
|
||||
conv_fac = fp_div(r1_ohms + r2_ohms, r2_ohms, fracbits);
|
||||
if (conv_fac <= UINT16_MAX)
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t conv_val = fp_mul(raw_val, conv_fac, fracbits);
|
||||
return fp_mul(vref_mV, conv_val, 16);
|
||||
}
|
||||
|
||||
unsigned short adc_read(int channel)
|
||||
{
|
||||
mutex_lock(&adc_mutex);
|
||||
|
||||
/* Configure ADC to read the channel */
|
||||
reg_writelf(adc3, ADC_SQR1, L(1 - 1), SQ1(channel));
|
||||
reg_varl(adc3, ADC_PCSEL) = (1 << channel);
|
||||
|
||||
/* Start conversion & wait until complete */
|
||||
reg_writelf(adc3, ADC_CR, ADSTART(1));
|
||||
while (reg_readlf(adc3, ADC_CR, ADSTART));
|
||||
|
||||
uint32_t raw_val = reg_readl(adc3, ADC_DR);
|
||||
|
||||
mutex_unlock(&adc_mutex);
|
||||
|
||||
/* Convert to millivolts */
|
||||
switch (channel)
|
||||
{
|
||||
case ADC_CHANNEL_VBUS:
|
||||
return scale_adc_val(raw_val, VREF_MV, 174, 100);
|
||||
|
||||
case ADC_CHANNEL_BATTERY:
|
||||
return scale_adc_val(raw_val, VREF_MV, 174, 390);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,4 +21,8 @@
|
|||
#ifndef __ECHOPLAYER_ADC_TARGET_H__
|
||||
#define __ECHOPLAYER_ADC_TARGET_H__
|
||||
|
||||
/* ADC3 channels */
|
||||
#define ADC_CHANNEL_VBUS 11
|
||||
#define ADC_CHANNEL_BATTERY 16 /* real battery voltage */
|
||||
|
||||
#endif /* __ECHOPLAYER_ADC_TARGET_H__ */
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ INIT_ATTR static void init_periph_clock(void)
|
|||
reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q));
|
||||
reg_writef(RCC_D2CCIP1R, SAI1SEL_V(PLL2P), SPI45SEL_V(HSE));
|
||||
reg_writef(RCC_D2CCIP2R, I2C123SEL_V(HSI));
|
||||
reg_writef(RCC_D3CCIPR, ADCSEL_V(PLL3R));
|
||||
|
||||
/* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */
|
||||
reg_writef(RCC_AHB3LPENR, AXISRAMEN(1));
|
||||
|
|
|
|||
|
|
@ -55,4 +55,7 @@
|
|||
|
||||
#define GPIO_USB_VBUS GPIO_PA(9)
|
||||
|
||||
#define GPIO_ADC_VBAT GPIO_PH(5)
|
||||
#define GPIO_ADC_VBUS GPIO_PC(1)
|
||||
|
||||
#endif /* __ECHOPLAYER_GPIO_TARGET_H__ */
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
****************************************************************************/
|
||||
#include "power.h"
|
||||
#include "mutex.h"
|
||||
#include "adc.h"
|
||||
#include "gpio-stm32h7.h"
|
||||
#include "system-echoplayer.h"
|
||||
#include "regs/cortex-m/cm_scb.h"
|
||||
|
|
@ -130,5 +131,5 @@ bool charging_state(void)
|
|||
|
||||
int _battery_voltage(void)
|
||||
{
|
||||
return 4000;
|
||||
return adc_read(ADC_CHANNEL_BATTERY);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#define F_LCD_AF9 GPIOF_FUNCTION(9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED)
|
||||
#define F_LPTIM4_OUT GPIOF_FUNCTION(3, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED)
|
||||
#define F_LPTIM1_OUT GPIOF_FUNCTION(1, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
#define F_ANALOG GPIOF_ANALOG()
|
||||
|
||||
#if STM32H743_USBOTG_INSTANCE == STM32H743_USBOTG_INSTANCE_USB1
|
||||
# define F_OTG_FS GPIOF_ANALOG()
|
||||
|
|
@ -90,6 +91,8 @@ static const struct gpio_setting gpios[] = {
|
|||
STM_DEFGPIO(GPIO_LCD_RESET, F_OUT_LS(0)), /* active low */
|
||||
STM_DEFGPIO(GPIO_BACKLIGHT, F_LPTIM1_OUT),
|
||||
STM_DEFGPIO(GPIO_USB_VBUS, F_INPUT), /* active high */
|
||||
STM_DEFGPIO(GPIO_ADC_VBAT, F_ANALOG),
|
||||
STM_DEFGPIO(GPIO_ADC_VBUS, F_ANALOG),
|
||||
};
|
||||
|
||||
/* TODO - replace hex constants - there are probably mistakes here */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue