mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-04-11 16:37:45 -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
|
|
@ -1926,7 +1926,6 @@ target/arm/rk27xx/ihifi2/audio-ihifi800.c
|
|||
#if CONFIG_CPU == STM32H743
|
||||
target/arm/stm32/crt0-stm32h7.S
|
||||
target/arm/stm32/vectors-stm32h7.S
|
||||
target/arm/stm32/adc-stm32h7.c
|
||||
#ifndef BOOTLOADER
|
||||
target/arm/stm32/debug-stm32h7.c
|
||||
#endif
|
||||
|
|
@ -1942,6 +1941,7 @@ target/arm/stm32/usb-stm32h7.c
|
|||
#endif
|
||||
|
||||
#if defined(ECHO_R1)
|
||||
target/arm/stm32/echoplayer/adc-echoplayer.c
|
||||
target/arm/stm32/echoplayer/audiohw-echoplayer.c
|
||||
target/arm/stm32/echoplayer/backlight-echoplayer.c
|
||||
target/arm/stm32/echoplayer/button-echoplayer.c
|
||||
|
|
|
|||
|
|
@ -1509,3 +1509,251 @@ I2C1 @ 0x40005400 : I2C
|
|||
I2C2 @ 0x40005800 : I2C
|
||||
I2C3 @ 0x40005C00 : I2C
|
||||
I2C4 @ 0x58001C00 : I2C
|
||||
|
||||
block ADC {
|
||||
ISR @ 0x00 : reg {
|
||||
12 LDORDY
|
||||
10 JQOVF
|
||||
09 AWD3
|
||||
08 AWD2
|
||||
07 AWD1
|
||||
06 JEOS
|
||||
05 JEOC
|
||||
04 OVR
|
||||
03 EOS
|
||||
02 EOC
|
||||
01 EOSMP
|
||||
00 ADRDY
|
||||
}
|
||||
|
||||
IER @ 0x04 : reg {
|
||||
10 JQOVFIE
|
||||
09 AWD3IE
|
||||
08 AWD2IE
|
||||
07 AWD1IE
|
||||
06 JEOSIE
|
||||
05 JEOCIE
|
||||
04 OVRIE
|
||||
03 EOSIE
|
||||
02 EOCIE
|
||||
01 EOSMPIE
|
||||
00 ADRDYIE
|
||||
}
|
||||
|
||||
CR @ 0x08 : reg {
|
||||
-- 31 ADCAL
|
||||
-- 30 ADCALDIF
|
||||
-- 29 DEEPPWD
|
||||
-- 28 ADVREGEN
|
||||
-- 27 LINCALRDYW6
|
||||
-- 26 LINCALRDYW5
|
||||
-- 25 LINCALRDYW4
|
||||
-- 24 LINCALRDYW3
|
||||
-- 23 LINCALRDYW2
|
||||
-- 22 LINCALRDYW1
|
||||
-- 16 ADCALLIN
|
||||
-- 09 BOOST1 // present on revision V only
|
||||
-- 08 BOOST0
|
||||
-- 05 JADSTP
|
||||
-- 04 ADSTP
|
||||
-- 03 JADSTART
|
||||
-- 02 ADSTART
|
||||
-- 01 ADDIS
|
||||
-- 00 ADEN
|
||||
}
|
||||
|
||||
CFGR @ 0x0c : reg {
|
||||
-- 31 JQDIS
|
||||
30 26 AWD1CH
|
||||
-- 25 JAUTO
|
||||
-- 24 JAWD1EN
|
||||
-- 23 AWD1EN
|
||||
-- 22 AWD1SGL
|
||||
-- 21 JQM
|
||||
-- 20 JDISCEN
|
||||
19 17 DISCNUM
|
||||
-- 16 DISCEN
|
||||
-- 14 AUTDLY
|
||||
-- 13 CONT
|
||||
-- 12 OVRMOD
|
||||
11 10 EXTEN
|
||||
09 05 EXTSEL
|
||||
04 02 RES
|
||||
01 00 DMNGT
|
||||
}
|
||||
|
||||
CFGR2 @ 0x10 : reg {
|
||||
31 28 LSHIFT
|
||||
25 16 OSVR
|
||||
-- 14 RSHIFT4
|
||||
-- 13 RSHIFT3
|
||||
-- 12 RSHIFT2
|
||||
-- 11 RSHIFT1
|
||||
-- 10 ROVSM
|
||||
-- 09 TROVS
|
||||
08 05 OVSS
|
||||
-- 01 JOVSE
|
||||
-- 00 ROVSE
|
||||
}
|
||||
|
||||
enum SMPTIME {
|
||||
0 = 1_5CYCLE
|
||||
1 = 2_5CYCLE
|
||||
2 = 8_5CYCLE
|
||||
3 = 16_5CYCLE
|
||||
4 = 32_5CYCLE
|
||||
5 = 64_5CYCLE
|
||||
6 = 387_5CYCLE
|
||||
7 = 810_5CYCLE
|
||||
}
|
||||
|
||||
SMPR1 @ 0x14 : reg {
|
||||
29 27 SMP9 : SMPTIME
|
||||
26 24 SMP8 : SMPTIME
|
||||
23 21 SMP7 : SMPTIME
|
||||
20 18 SMP6 : SMPTIME
|
||||
17 15 SMP5 : SMPTIME
|
||||
14 12 SMP4 : SMPTIME
|
||||
11 09 SMP3 : SMPTIME
|
||||
08 06 SMP2 : SMPTIME
|
||||
05 03 SMP1 : SMPTIME
|
||||
02 00 SMP0 : SMPTIME
|
||||
}
|
||||
|
||||
SMPR2 @ 0x18 : reg {
|
||||
29 27 SMP19 : SMPTIME
|
||||
26 24 SMP18 : SMPTIME
|
||||
23 21 SMP17 : SMPTIME
|
||||
20 18 SMP16 : SMPTIME
|
||||
17 15 SMP15 : SMPTIME
|
||||
14 12 SMP14 : SMPTIME
|
||||
11 09 SMP13 : SMPTIME
|
||||
08 06 SMP12 : SMPTIME
|
||||
05 03 SMP11 : SMPTIME
|
||||
02 00 SMP10 : SMPTIME
|
||||
}
|
||||
|
||||
PCSEL @ 0x1c : reg
|
||||
LTR1 @ 0x20 : reg
|
||||
HTR1 @ 0x24 : reg
|
||||
|
||||
SQR1 @ 0x30 : reg {
|
||||
28 24 SQ4
|
||||
22 18 SQ3
|
||||
16 12 SQ2
|
||||
10 06 SQ1
|
||||
03 00 L
|
||||
}
|
||||
|
||||
SQR2 @ 0x34 : reg {
|
||||
28 24 SQ9
|
||||
22 18 SQ8
|
||||
16 12 SQ7
|
||||
10 06 SQ6
|
||||
04 00 SQ5
|
||||
}
|
||||
|
||||
SQR3 @ 0x38 : reg {
|
||||
28 24 SQ14
|
||||
22 18 SQ13
|
||||
16 12 SQ12
|
||||
10 06 SQ11
|
||||
04 00 SQ10
|
||||
}
|
||||
|
||||
SQR4 @ 0x38 : reg {
|
||||
10 06 SQ16
|
||||
04 00 SQ15
|
||||
}
|
||||
|
||||
DR @ 0x40 : reg
|
||||
|
||||
JSQR @ 0x4c : reg {
|
||||
31 27 JSQ4
|
||||
25 21 JSQ3
|
||||
19 15 JSQ2
|
||||
13 09 JSQ1
|
||||
08 07 JEXTEN
|
||||
06 02 JEXTSEL
|
||||
01 00 JL
|
||||
}
|
||||
|
||||
OFR @ 0x60 [4; 0x04] : reg {
|
||||
-- 31 SSATE
|
||||
30 26 OFFSET_CH
|
||||
25 00 OFFSET
|
||||
}
|
||||
|
||||
JDR @ 0x80 [4; 0x04] : reg
|
||||
|
||||
AWD2CR @ 0xa0 : reg {
|
||||
19 00 AWD2CH
|
||||
}
|
||||
|
||||
AWD3CR @ 0xa4 : reg {
|
||||
19 00 AWD3CH
|
||||
}
|
||||
|
||||
LTR2 @ 0xb0 : reg
|
||||
HTR2 @ 0xb4 : reg
|
||||
LTR3 @ 0xb8 : reg
|
||||
HTR3 @ 0xbc : reg
|
||||
|
||||
DIFSEL @ 0xc0 : reg
|
||||
|
||||
CALFACT @ 0xc4 : reg {
|
||||
26 16 D
|
||||
10 00 S
|
||||
}
|
||||
|
||||
CALFACT2 @ 0xc8 : reg {
|
||||
29 00 LINCALFACT
|
||||
}
|
||||
|
||||
CSR @ 0x300 : reg {
|
||||
26 JQOVF_SLV
|
||||
25 AWD3_SLV
|
||||
24 AWD2_SLV
|
||||
23 AWD1_SLV
|
||||
22 JEOS_SLV
|
||||
21 JEOC_SLV
|
||||
20 OVR_SLV
|
||||
19 EOS_SLV
|
||||
18 EOC_SLV
|
||||
17 EOSMP_SLV
|
||||
16 ADRDY_SLV
|
||||
10 JQOVF_MST
|
||||
09 AWD3_MST
|
||||
08 AWD2_MST
|
||||
07 AWD1_MST
|
||||
06 JEOS_MST
|
||||
05 JEOC_MST
|
||||
04 OVR_MST
|
||||
03 EOS_MST
|
||||
02 EOC_MST
|
||||
01 EOSMP_MST
|
||||
00 ADRDY_MST
|
||||
}
|
||||
|
||||
CCR @ 0x308 : reg {
|
||||
-- 24 VBATEN
|
||||
-- 23 TSEN
|
||||
-- 22 VREFEN
|
||||
21 18 PRESC
|
||||
17 16 CKMOD
|
||||
15 14 DAMDF
|
||||
10 08 DELAY
|
||||
04 00 DUAL
|
||||
}
|
||||
|
||||
CDR @ 0x30c : reg {
|
||||
31 16 RDATA_SLV
|
||||
15 00 RDATA_MST
|
||||
}
|
||||
|
||||
CDR2 @ 0x310 : reg
|
||||
}
|
||||
|
||||
ADC1 @ 0x40022000 : ADC
|
||||
ADC2 @ 0x40022100 : ADC
|
||||
ADC3 @ 0x58026000 : ADC
|
||||
|
|
|
|||
|
|
@ -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