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 <[email protected]> --- 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
