[PATCH] hw/adc/stm32f2xx_adc: fix left-aligned conversion results

Manuele Conti posted 1 patch 1 day, 21 hours ago
hw/adc/stm32f2xx_adc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
[PATCH] hw/adc/stm32f2xx_adc: fix left-aligned conversion results
Posted by Manuele Conti 1 day, 21 hours ago
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