Left-aligned regular conversion results must occupy bits [15:4],
[15:6], or [15:8] for 12-, 10-, or 8-bit resolution respectively.
At 6-bit resolution the result is aligned within a byte, in bits [7:2].
The current single-bit shift and 0xFFF0 mask both misalign the result
and discard significant sample bits. Select the shift according to RES
and keep the existing right-aligned sample generation unchanged.
Signed-off-by: Manuele Conti <conti.manuele@gmail.com>
---
hw/adc/stm32f2xx_adc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/hw/adc/stm32f2xx_adc.c b/hw/adc/stm32f2xx_adc.c
index 50a04a0..e2dfc83 100644
--- a/hw/adc/stm32f2xx_adc.c
+++ b/hw/adc/stm32f2xx_adc.c
@@ -69,10 +69,12 @@ static void stm32f2xx_adc_reset(DeviceState *dev)
static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
{
+ unsigned resolution = (s->adc_cr1 & ADC_CR1_RES) >> 24;
+
/* Attempts to fake some ADC values */
s->adc_dr = s->adc_dr + 7;
- switch ((s->adc_cr1 & ADC_CR1_RES) >> 24) {
+ switch (resolution) {
case 0:
/* 12-bit */
s->adc_dr &= 0xFFF;
@@ -91,7 +93,10 @@ static uint32_t stm32f2xx_adc_generate_value(STM32F2XXADCState *s)
}
if (s->adc_cr2 & ADC_CR2_ALIGN) {
- return (s->adc_dr << 1) & 0xFFF0;
+ /* 6-bit results are left-aligned within a byte. */
+ unsigned shift = resolution == 3 ? 2 : 4 + 2 * resolution;
+
+ return s->adc_dr << shift;
} else {
return s->adc_dr;
}
--
2.41.0