Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

echoplayer: implement ADC to read battery voltage

Change-Id: I8043e7d2f02c10cb8c9d9ec59b7d216945431481

+402 -27
+1 -1
firmware/SOURCES
··· 1926 1926 #if CONFIG_CPU == STM32H743 1927 1927 target/arm/stm32/crt0-stm32h7.S 1928 1928 target/arm/stm32/vectors-stm32h7.S 1929 - target/arm/stm32/adc-stm32h7.c 1930 1929 #ifndef BOOTLOADER 1931 1930 target/arm/stm32/debug-stm32h7.c 1932 1931 #endif ··· 1942 1941 #endif 1943 1942 1944 1943 #if defined(ECHO_R1) 1944 + target/arm/stm32/echoplayer/adc-echoplayer.c 1945 1945 target/arm/stm32/echoplayer/audiohw-echoplayer.c 1946 1946 target/arm/stm32/echoplayer/backlight-echoplayer.c 1947 1947 target/arm/stm32/echoplayer/button-echoplayer.c
+248
firmware/reggen/stm32h743.regs
··· 1509 1509 I2C2 @ 0x40005800 : I2C 1510 1510 I2C3 @ 0x40005C00 : I2C 1511 1511 I2C4 @ 0x58001C00 : I2C 1512 + 1513 + block ADC { 1514 + ISR @ 0x00 : reg { 1515 + 12 LDORDY 1516 + 10 JQOVF 1517 + 09 AWD3 1518 + 08 AWD2 1519 + 07 AWD1 1520 + 06 JEOS 1521 + 05 JEOC 1522 + 04 OVR 1523 + 03 EOS 1524 + 02 EOC 1525 + 01 EOSMP 1526 + 00 ADRDY 1527 + } 1528 + 1529 + IER @ 0x04 : reg { 1530 + 10 JQOVFIE 1531 + 09 AWD3IE 1532 + 08 AWD2IE 1533 + 07 AWD1IE 1534 + 06 JEOSIE 1535 + 05 JEOCIE 1536 + 04 OVRIE 1537 + 03 EOSIE 1538 + 02 EOCIE 1539 + 01 EOSMPIE 1540 + 00 ADRDYIE 1541 + } 1542 + 1543 + CR @ 0x08 : reg { 1544 + -- 31 ADCAL 1545 + -- 30 ADCALDIF 1546 + -- 29 DEEPPWD 1547 + -- 28 ADVREGEN 1548 + -- 27 LINCALRDYW6 1549 + -- 26 LINCALRDYW5 1550 + -- 25 LINCALRDYW4 1551 + -- 24 LINCALRDYW3 1552 + -- 23 LINCALRDYW2 1553 + -- 22 LINCALRDYW1 1554 + -- 16 ADCALLIN 1555 + -- 09 BOOST1 // present on revision V only 1556 + -- 08 BOOST0 1557 + -- 05 JADSTP 1558 + -- 04 ADSTP 1559 + -- 03 JADSTART 1560 + -- 02 ADSTART 1561 + -- 01 ADDIS 1562 + -- 00 ADEN 1563 + } 1564 + 1565 + CFGR @ 0x0c : reg { 1566 + -- 31 JQDIS 1567 + 30 26 AWD1CH 1568 + -- 25 JAUTO 1569 + -- 24 JAWD1EN 1570 + -- 23 AWD1EN 1571 + -- 22 AWD1SGL 1572 + -- 21 JQM 1573 + -- 20 JDISCEN 1574 + 19 17 DISCNUM 1575 + -- 16 DISCEN 1576 + -- 14 AUTDLY 1577 + -- 13 CONT 1578 + -- 12 OVRMOD 1579 + 11 10 EXTEN 1580 + 09 05 EXTSEL 1581 + 04 02 RES 1582 + 01 00 DMNGT 1583 + } 1584 + 1585 + CFGR2 @ 0x10 : reg { 1586 + 31 28 LSHIFT 1587 + 25 16 OSVR 1588 + -- 14 RSHIFT4 1589 + -- 13 RSHIFT3 1590 + -- 12 RSHIFT2 1591 + -- 11 RSHIFT1 1592 + -- 10 ROVSM 1593 + -- 09 TROVS 1594 + 08 05 OVSS 1595 + -- 01 JOVSE 1596 + -- 00 ROVSE 1597 + } 1598 + 1599 + enum SMPTIME { 1600 + 0 = 1_5CYCLE 1601 + 1 = 2_5CYCLE 1602 + 2 = 8_5CYCLE 1603 + 3 = 16_5CYCLE 1604 + 4 = 32_5CYCLE 1605 + 5 = 64_5CYCLE 1606 + 6 = 387_5CYCLE 1607 + 7 = 810_5CYCLE 1608 + } 1609 + 1610 + SMPR1 @ 0x14 : reg { 1611 + 29 27 SMP9 : SMPTIME 1612 + 26 24 SMP8 : SMPTIME 1613 + 23 21 SMP7 : SMPTIME 1614 + 20 18 SMP6 : SMPTIME 1615 + 17 15 SMP5 : SMPTIME 1616 + 14 12 SMP4 : SMPTIME 1617 + 11 09 SMP3 : SMPTIME 1618 + 08 06 SMP2 : SMPTIME 1619 + 05 03 SMP1 : SMPTIME 1620 + 02 00 SMP0 : SMPTIME 1621 + } 1622 + 1623 + SMPR2 @ 0x18 : reg { 1624 + 29 27 SMP19 : SMPTIME 1625 + 26 24 SMP18 : SMPTIME 1626 + 23 21 SMP17 : SMPTIME 1627 + 20 18 SMP16 : SMPTIME 1628 + 17 15 SMP15 : SMPTIME 1629 + 14 12 SMP14 : SMPTIME 1630 + 11 09 SMP13 : SMPTIME 1631 + 08 06 SMP12 : SMPTIME 1632 + 05 03 SMP11 : SMPTIME 1633 + 02 00 SMP10 : SMPTIME 1634 + } 1635 + 1636 + PCSEL @ 0x1c : reg 1637 + LTR1 @ 0x20 : reg 1638 + HTR1 @ 0x24 : reg 1639 + 1640 + SQR1 @ 0x30 : reg { 1641 + 28 24 SQ4 1642 + 22 18 SQ3 1643 + 16 12 SQ2 1644 + 10 06 SQ1 1645 + 03 00 L 1646 + } 1647 + 1648 + SQR2 @ 0x34 : reg { 1649 + 28 24 SQ9 1650 + 22 18 SQ8 1651 + 16 12 SQ7 1652 + 10 06 SQ6 1653 + 04 00 SQ5 1654 + } 1655 + 1656 + SQR3 @ 0x38 : reg { 1657 + 28 24 SQ14 1658 + 22 18 SQ13 1659 + 16 12 SQ12 1660 + 10 06 SQ11 1661 + 04 00 SQ10 1662 + } 1663 + 1664 + SQR4 @ 0x38 : reg { 1665 + 10 06 SQ16 1666 + 04 00 SQ15 1667 + } 1668 + 1669 + DR @ 0x40 : reg 1670 + 1671 + JSQR @ 0x4c : reg { 1672 + 31 27 JSQ4 1673 + 25 21 JSQ3 1674 + 19 15 JSQ2 1675 + 13 09 JSQ1 1676 + 08 07 JEXTEN 1677 + 06 02 JEXTSEL 1678 + 01 00 JL 1679 + } 1680 + 1681 + OFR @ 0x60 [4; 0x04] : reg { 1682 + -- 31 SSATE 1683 + 30 26 OFFSET_CH 1684 + 25 00 OFFSET 1685 + } 1686 + 1687 + JDR @ 0x80 [4; 0x04] : reg 1688 + 1689 + AWD2CR @ 0xa0 : reg { 1690 + 19 00 AWD2CH 1691 + } 1692 + 1693 + AWD3CR @ 0xa4 : reg { 1694 + 19 00 AWD3CH 1695 + } 1696 + 1697 + LTR2 @ 0xb0 : reg 1698 + HTR2 @ 0xb4 : reg 1699 + LTR3 @ 0xb8 : reg 1700 + HTR3 @ 0xbc : reg 1701 + 1702 + DIFSEL @ 0xc0 : reg 1703 + 1704 + CALFACT @ 0xc4 : reg { 1705 + 26 16 D 1706 + 10 00 S 1707 + } 1708 + 1709 + CALFACT2 @ 0xc8 : reg { 1710 + 29 00 LINCALFACT 1711 + } 1712 + 1713 + CSR @ 0x300 : reg { 1714 + 26 JQOVF_SLV 1715 + 25 AWD3_SLV 1716 + 24 AWD2_SLV 1717 + 23 AWD1_SLV 1718 + 22 JEOS_SLV 1719 + 21 JEOC_SLV 1720 + 20 OVR_SLV 1721 + 19 EOS_SLV 1722 + 18 EOC_SLV 1723 + 17 EOSMP_SLV 1724 + 16 ADRDY_SLV 1725 + 10 JQOVF_MST 1726 + 09 AWD3_MST 1727 + 08 AWD2_MST 1728 + 07 AWD1_MST 1729 + 06 JEOS_MST 1730 + 05 JEOC_MST 1731 + 04 OVR_MST 1732 + 03 EOS_MST 1733 + 02 EOC_MST 1734 + 01 EOSMP_MST 1735 + 00 ADRDY_MST 1736 + } 1737 + 1738 + CCR @ 0x308 : reg { 1739 + -- 24 VBATEN 1740 + -- 23 TSEN 1741 + -- 22 VREFEN 1742 + 21 18 PRESC 1743 + 17 16 CKMOD 1744 + 15 14 DAMDF 1745 + 10 08 DELAY 1746 + 04 00 DUAL 1747 + } 1748 + 1749 + CDR @ 0x30c : reg { 1750 + 31 16 RDATA_SLV 1751 + 15 00 RDATA_MST 1752 + } 1753 + 1754 + CDR2 @ 0x310 : reg 1755 + } 1756 + 1757 + ADC1 @ 0x40022000 : ADC 1758 + ADC2 @ 0x40022100 : ADC 1759 + ADC3 @ 0x58026000 : ADC
-25
firmware/target/arm/stm32/adc-stm32h7.c
··· 1 - /*************************************************************************** 2 - * __________ __ ___. 3 - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 - * \/ \/ \/ \/ \/ 8 - * $Id$ 9 - * 10 - * Copyright (C) 2025 by Aidan MacDonald 11 - * 12 - * This program is free software; you can redistribute it and/or 13 - * modify it under the terms of the GNU General Public License 14 - * as published by the Free Software Foundation; either version 2 15 - * of the License, or (at your option) any later version. 16 - * 17 - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 - * KIND, either express or implied. 19 - * 20 - ****************************************************************************/ 21 - #include "adc.h" 22 - 23 - void adc_init(void) 24 - { 25 - }
+140
firmware/target/arm/stm32/echoplayer/adc-echoplayer.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id$ 9 + * 10 + * Copyright (C) 2026 by Aidan MacDonald 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 2 15 + * of the License, or (at your option) any later version. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include "adc.h" 22 + #include "mutex.h" 23 + #include "kernel.h" 24 + #include "fixedpoint.h" 25 + #include "regs/stm32h743/adc.h" 26 + #include "regs/stm32h743/rcc.h" 27 + 28 + #define VREF_MV 3300 29 + 30 + static volatile void *const adc3 = (void *)ITA_ADC3; 31 + static struct mutex adc_mutex; 32 + 33 + static void set_smptime(volatile void *adcbase, int channel, uint32_t smpval) 34 + { 35 + uint32_t reg_off = ITO_ADC_SMPR1; 36 + if (channel > 10) 37 + { 38 + reg_off = ITO_ADC_SMPR2; 39 + channel -= 10; 40 + } 41 + 42 + volatile uint32_t *reg = adcbase + reg_off; 43 + uint32_t reg_val = *reg; 44 + 45 + reg_val &= ~(0x7 << (channel * 3)); 46 + reg_val |= smpval << (channel * 3); 47 + 48 + *reg = reg_val; 49 + } 50 + 51 + void adc_init(void) 52 + { 53 + mutex_init(&adc_mutex); 54 + reg_writef(RCC_AHB4ENR, ADC3EN(1)); 55 + 56 + /* Power up ADC */ 57 + reg_writelf(adc3, ADC_CR, DEEPPWD(0)); 58 + reg_writelf(adc3, ADC_CR, ADVREGEN(1)); 59 + while (!reg_readlf(adc3, ADC_ISR, LDORDY)); 60 + 61 + /* Run calibration */ 62 + reg_writelf(adc3, ADC_CR, ADCALDIF(0), ADCALLIN(1), ADCAL(1)); 63 + while (reg_readlf(adc3, ADC_CR, ADCAL)); 64 + 65 + /* Enable the ADC */ 66 + reg_assignlf(adc3, ADC_ISR, ADRDY(1)); 67 + reg_writelf(adc3, ADC_CR, ADEN(1)); 68 + while (!reg_readlf(adc3, ADC_ISR, ADRDY)); 69 + 70 + /* Set sampling times for each channel (387.5 cycles @ 6 MHz = 64.5us) */ 71 + set_smptime(adc3, ADC_CHANNEL_VBUS, BV_ADC_SMPR1_SMP0_387_5CYCLE); 72 + set_smptime(adc3, ADC_CHANNEL_BATTERY, BV_ADC_SMPR1_SMP0_387_5CYCLE); 73 + } 74 + 75 + /* 76 + * Converts raw ADC reading to millivolts, assuming the 77 + * ADC samples the output of a voltage divider as in the 78 + * following circuit: 79 + * 80 + * [VIN]---[R1] 81 + * | 82 + * +----[ADC] 83 + * | 84 + * [R2] 85 + * | 86 + * [GND] 87 + * 88 + * The value returned is the voltage at the VIN node. 89 + */ 90 + static uint32_t scale_adc_val(uint32_t raw_val, 91 + uint32_t vref_mV, 92 + uint32_t r1_ohms, 93 + uint32_t r2_ohms) 94 + { 95 + /* 96 + * Finds the best fracbits value which doesn't overflow. 97 + * GCC will optimize this loop to a constant. 98 + */ 99 + uint32_t fracbits = 16; 100 + uint32_t conv_fac; 101 + for (; fracbits > 0; --fracbits) 102 + { 103 + conv_fac = fp_div(r1_ohms + r2_ohms, r2_ohms, fracbits); 104 + if (conv_fac <= UINT16_MAX) 105 + break; 106 + } 107 + 108 + uint32_t conv_val = fp_mul(raw_val, conv_fac, fracbits); 109 + return fp_mul(vref_mV, conv_val, 16); 110 + } 111 + 112 + unsigned short adc_read(int channel) 113 + { 114 + mutex_lock(&adc_mutex); 115 + 116 + /* Configure ADC to read the channel */ 117 + reg_writelf(adc3, ADC_SQR1, L(1 - 1), SQ1(channel)); 118 + reg_varl(adc3, ADC_PCSEL) = (1 << channel); 119 + 120 + /* Start conversion & wait until complete */ 121 + reg_writelf(adc3, ADC_CR, ADSTART(1)); 122 + while (reg_readlf(adc3, ADC_CR, ADSTART)); 123 + 124 + uint32_t raw_val = reg_readl(adc3, ADC_DR); 125 + 126 + mutex_unlock(&adc_mutex); 127 + 128 + /* Convert to millivolts */ 129 + switch (channel) 130 + { 131 + case ADC_CHANNEL_VBUS: 132 + return scale_adc_val(raw_val, VREF_MV, 174, 100); 133 + 134 + case ADC_CHANNEL_BATTERY: 135 + return scale_adc_val(raw_val, VREF_MV, 174, 390); 136 + 137 + default: 138 + return 0; 139 + } 140 + }
+4
firmware/target/arm/stm32/echoplayer/adc-target.h
··· 21 21 #ifndef __ECHOPLAYER_ADC_TARGET_H__ 22 22 #define __ECHOPLAYER_ADC_TARGET_H__ 23 23 24 + /* ADC3 channels */ 25 + #define ADC_CHANNEL_VBUS 11 26 + #define ADC_CHANNEL_BATTERY 16 /* real battery voltage */ 27 + 24 28 #endif /* __ECHOPLAYER_ADC_TARGET_H__ */
+1
firmware/target/arm/stm32/echoplayer/clock-echoplayer.c
··· 165 165 reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q)); 166 166 reg_writef(RCC_D2CCIP1R, SAI1SEL_V(PLL2P), SPI45SEL_V(HSE)); 167 167 reg_writef(RCC_D2CCIP2R, I2C123SEL_V(HSI)); 168 + reg_writef(RCC_D3CCIPR, ADCSEL_V(PLL3R)); 168 169 169 170 /* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */ 170 171 reg_writef(RCC_AHB3LPENR, AXISRAMEN(1));
+3
firmware/target/arm/stm32/echoplayer/gpio-target.h
··· 55 55 56 56 #define GPIO_USB_VBUS GPIO_PA(9) 57 57 58 + #define GPIO_ADC_VBAT GPIO_PH(5) 59 + #define GPIO_ADC_VBUS GPIO_PC(1) 60 + 58 61 #endif /* __ECHOPLAYER_GPIO_TARGET_H__ */
+2 -1
firmware/target/arm/stm32/echoplayer/power-echoplayer.c
··· 20 20 ****************************************************************************/ 21 21 #include "power.h" 22 22 #include "mutex.h" 23 + #include "adc.h" 23 24 #include "gpio-stm32h7.h" 24 25 #include "system-echoplayer.h" 25 26 #include "regs/cortex-m/cm_scb.h" ··· 130 131 131 132 int _battery_voltage(void) 132 133 { 133 - return 4000; 134 + return adc_read(ADC_CHANNEL_BATTERY); 134 135 }
+3
firmware/target/arm/stm32/echoplayer/system-echoplayer.c
··· 49 49 #define F_LCD_AF9 GPIOF_FUNCTION(9, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED) 50 50 #define F_LPTIM4_OUT GPIOF_FUNCTION(3, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_LOW, GPIO_PULL_DISABLED) 51 51 #define F_LPTIM1_OUT GPIOF_FUNCTION(1, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED) 52 + #define F_ANALOG GPIOF_ANALOG() 52 53 53 54 #if STM32H743_USBOTG_INSTANCE == STM32H743_USBOTG_INSTANCE_USB1 54 55 # define F_OTG_FS GPIOF_ANALOG() ··· 90 91 STM_DEFGPIO(GPIO_LCD_RESET, F_OUT_LS(0)), /* active low */ 91 92 STM_DEFGPIO(GPIO_BACKLIGHT, F_LPTIM1_OUT), 92 93 STM_DEFGPIO(GPIO_USB_VBUS, F_INPUT), /* active high */ 94 + STM_DEFGPIO(GPIO_ADC_VBAT, F_ANALOG), 95 + STM_DEFGPIO(GPIO_ADC_VBUS, F_ANALOG), 93 96 }; 94 97 95 98 /* TODO - replace hex constants - there are probably mistakes here */