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.

imx233/fuze+: rework lradc/adc code, add external temperature sensing(battery)

Rework code to be more useful:
- move battery channel init to lradc
- always init lradc from system (previously from adc)
- don't reserve channels for vddio, nmos or pmos
- implement external temperature sensing using current source
- use this for battery sensing on the Fuze+ (calibration needed)

Change-Id: I5f9a24b9243db7d1e6bdb16b84bc891e61d0c318

+135 -51
+33 -44
firmware/target/arm/imx233/adc-imx233.c
··· 25 25 #include "system.h" 26 26 #include "adc-imx233.h" 27 27 28 - /* dedicate two channels to temperature sensing 29 - * dedicate channel 7 to battery 30 - * and channel 6 to vddio */ 31 - static int pmos_chan, nmos_chan; 32 - static int battery_chan, vddio_chan; 33 - static int battery_delay_chan; 34 - 35 28 void adc_init(void) 36 29 { 37 - imx233_lradc_init(); 38 - /* reserve channels 6 for vddio and 7 for battery (special for conversion) */ 39 - battery_chan = 7; 40 - vddio_chan = 6; 41 - imx233_lradc_reserve_channel(battery_chan); 42 - imx233_lradc_reserve_channel(vddio_chan); 43 - /* reserve any channels for PMOS and NMOS */ 44 - pmos_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); 45 - if(pmos_chan < 0) panicf("No LRADC channel for PMOS !"); 46 - nmos_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); 47 - if(nmos_chan < 0) panicf("No LRADC channel for NMOS !"); 48 - 49 - /* setup them for the simplest use: no accumulation, no division*/ 50 - imx233_lradc_setup_channel(battery_chan, false, false, 0, HW_LRADC_CHANNEL_BATTERY); 51 - imx233_lradc_setup_channel(vddio_chan, false, false, 0, HW_LRADC_CHANNEL_VDDIO); 52 - imx233_lradc_setup_channel(nmos_chan, false, false, 0, HW_LRADC_CHANNEL_NMOS_THIN); 53 - imx233_lradc_setup_channel(pmos_chan, false, false, 0, HW_LRADC_CHANNEL_PMOS_THIN); 54 - /* setup delay channel for battery for automatic reading and scaling */ 55 - battery_delay_chan = 0; 56 - imx233_lradc_reserve_delay(battery_delay_chan); 57 - /* setup delay to trigger battery channel and retrigger itself. 58 - * The counter runs at 2KHz so a delay of 200 will trigger 10 59 - * conversions per seconds */ 60 - imx233_lradc_setup_delay(battery_delay_chan, 1 << battery_chan, 61 - 1 << battery_delay_chan, 0, 200); 62 - imx233_lradc_kick_delay(battery_delay_chan); 63 - /* enable automatic conversion, use Li-Ion type battery */ 64 - imx233_lradc_setup_battery_conversion(true, HW_LRADC_CONVERSION__SCALE_FACTOR__LI_ION); 65 30 } 66 31 67 - int adc_read_physical_ex(int virt) 32 + static short adc_read_physical_ex(int virt) 68 33 { 69 34 imx233_lradc_clear_channel(virt); 70 35 imx233_lradc_kick_channel(virt); ··· 72 37 return imx233_lradc_read_channel(virt); 73 38 } 74 39 75 - int adc_read_physical(int src) 40 + static short adc_read_physical(int src, bool div2) 76 41 { 77 42 int virt = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); 78 43 // divide by two for wider ranger 79 - imx233_lradc_setup_channel(virt, true, false, 0, src); 44 + imx233_lradc_setup_channel(virt, div2, false, 0, src); 80 45 int val = adc_read_physical_ex(virt); 81 46 imx233_lradc_release_channel(virt); 82 47 return val; 83 48 } 84 49 85 - unsigned short adc_read_virtual(int c) 50 + static short adc_read_virtual(int c) 86 51 { 87 52 switch(c) 88 53 { 89 54 case IMX233_ADC_BATTERY: 90 - return adc_read_physical_ex(battery_chan); 55 + return imx233_lradc_read_battery_voltage(); 91 56 case IMX233_ADC_VDDIO: 92 - return adc_read_physical_ex(vddio_chan); 57 + /* VddIO pin has a builtin 2:1 divide */ 58 + return adc_read_physical(HW_LRADC_CHANNEL_VDDIO, false); 59 + case IMX233_ADC_VDD5V: 60 + /* Vdd5V pin has a builtin 4:1 divide */ 61 + return adc_read_physical(HW_LRADC_CHANNEL_5V, false) * 2; 93 62 case IMX233_ADC_DIE_TEMP: 94 - // do kelvin to celsius conversion 95 - return imx233_lradc_sense_die_temperature(nmos_chan, pmos_chan) - 273; 63 + { 64 + // don't block on second channel otherwise we might deadlock ! 65 + int nmos_chan = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); 66 + int pmos_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK); 67 + int val = 0; 68 + if(pmos_chan >= 0) 69 + { 70 + val = imx233_lradc_sense_die_temperature(nmos_chan, pmos_chan) - 273; 71 + imx233_lradc_release_channel(pmos_chan); 72 + } 73 + imx233_lradc_release_channel(nmos_chan); 74 + return val; 75 + } 76 + #ifdef IMX233_ADC_BATT_TEMP_SENSOR 77 + case IMX233_ADC_BATT_TEMP: 78 + { 79 + int virt = imx233_lradc_acquire_channel(TIMEOUT_BLOCK); 80 + int val = imx233_lradc_sense_ext_temperature(virt, IMX233_ADC_BATT_TEMP_SENSOR); 81 + imx233_lradc_release_channel(virt); 82 + return val; 83 + } 84 + #endif 96 85 default: 97 86 return 0; 98 87 } ··· 104 93 if(c < 0) 105 94 return adc_read_virtual(c); 106 95 else 107 - return adc_read_physical(c); 96 + return adc_read_physical(c, true); 108 97 }
+4
firmware/target/arm/imx233/adc-imx233.h
··· 29 29 #define IMX233_ADC_BATTERY -1 /* Battery voltage (mV) */ 30 30 #define IMX233_ADC_DIE_TEMP -2 /* Die temperature (°C) */ 31 31 #define IMX233_ADC_VDDIO -3 /* VddIO voltage (mV) */ 32 + #define IMX233_ADC_VDD5V -4 /* Vdd5V voltage (mV) */ 33 + #ifdef IMX233_ADC_BATT_TEMP_SENSOR 34 + #define IMX233_ADC_BATT_TEMP -5 /* Battery temperature (°C) */ 35 + #endif 32 36 33 37 /* Channel mapping */ 34 38 extern int imx233_adc_mapping[];
+75
firmware/target/arm/imx233/lradc-imx233.c
··· 27 27 static struct channel_arbiter_t channel_arbiter; 28 28 /* delay channels */ 29 29 static struct channel_arbiter_t delay_arbiter; 30 + /* battery is very special, dedicate a channel and a delay to it */ 31 + static int battery_chan; 32 + static int battery_delay_chan; 30 33 31 34 void imx233_lradc_setup_channel(int channel, bool div2, bool acc, int nr_samples, int src) 32 35 { ··· 111 114 112 115 int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan) 113 116 { 117 + imx233_lradc_setup_channel(nmos_chan, false, false, 0, HW_LRADC_CHANNEL_NMOS_THIN); 118 + imx233_lradc_setup_channel(pmos_chan, false, false, 0, HW_LRADC_CHANNEL_PMOS_THIN); 114 119 // mux sensors 115 120 __REG_CLR(HW_LRADC_CTRL2) = HW_LRADC_CTRL2__TEMPSENSE_PWD; 116 121 imx233_lradc_clear_channel(nmos_chan); ··· 129 134 return (diff * 1012) / 4000; 130 135 } 131 136 137 + /* set to 0 to disable current source */ 138 + static void imx233_lradc_set_temp_isrc(int sensor, int value) 139 + { 140 + if(sensor < 0 || sensor > 1) 141 + panicf("imx233_lradc_set_temp_isrc: invalid sensor"); 142 + unsigned mask = HW_LRADC_CTRL2__TEMP_ISRCx_BM(sensor); 143 + unsigned bp = HW_LRADC_CTRL2__TEMP_ISRCx_BP(sensor); 144 + unsigned en = HW_LRADC_CTRL2__TEMP_SENSOR_IENABLEx(sensor); 145 + 146 + __REG_CLR(HW_LRADC_CTRL2) = mask; 147 + __REG_SET(HW_LRADC_CTRL2) = value << bp; 148 + if(value != 0) 149 + { 150 + __REG_SET(HW_LRADC_CTRL2) = en; 151 + udelay(100); 152 + } 153 + else 154 + __REG_CLR(HW_LRADC_CTRL2) = en; 155 + } 156 + 157 + int imx233_lradc_sense_ext_temperature(int chan, int sensor) 158 + { 159 + #define EXT_TEMP_ACC_COUNT 5 160 + /* setup channel */ 161 + imx233_lradc_setup_channel(chan, false, false, 0, sensor); 162 + /* set current source to 300µA */ 163 + imx233_lradc_set_temp_isrc(sensor, HW_LRADC_CTRL2__TEMP_ISRC__300uA); 164 + /* read value and accumulate */ 165 + int a = 0; 166 + for(int i = 0; i < EXT_TEMP_ACC_COUNT; i++) 167 + { 168 + imx233_lradc_clear_channel(chan); 169 + imx233_lradc_kick_channel(chan); 170 + imx233_lradc_wait_channel(chan); 171 + a += imx233_lradc_read_channel(chan); 172 + } 173 + /* setup channel for small accumulation */ 174 + /* set current source to 20µA */ 175 + imx233_lradc_set_temp_isrc(sensor, HW_LRADC_CTRL2__TEMP_ISRC__20uA); 176 + /* read value */ 177 + int b = 0; 178 + for(int i = 0; i < EXT_TEMP_ACC_COUNT; i++) 179 + { 180 + imx233_lradc_clear_channel(chan); 181 + imx233_lradc_kick_channel(chan); 182 + imx233_lradc_wait_channel(chan); 183 + b += imx233_lradc_read_channel(chan); 184 + } 185 + /* disable sensor current */ 186 + imx233_lradc_set_temp_isrc(sensor, HW_LRADC_CTRL2__TEMP_ISRC__0uA); 187 + 188 + return (b - a) / EXT_TEMP_ACC_COUNT; 189 + } 190 + 132 191 void imx233_lradc_setup_battery_conversion(bool automatic, unsigned long scale_factor) 133 192 { 134 193 __REG_CLR(HW_LRADC_CONVERSION) = HW_LRADC_CONVERSION__SCALE_FACTOR_BM; ··· 159 218 // set frequency 160 219 __REG_CLR(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME_BM; 161 220 __REG_SET(HW_LRADC_CTRL3) = HW_LRADC_CTRL3__CYCLE_TIME__6MHz; 221 + // setup battery 222 + battery_chan = 7; 223 + imx233_lradc_reserve_channel(battery_chan); 224 + /* setup them for the simplest use: no accumulation, no division*/ 225 + imx233_lradc_setup_channel(battery_chan, false, false, 0, HW_LRADC_CHANNEL_BATTERY); 226 + /* setup delay channel for battery for automatic reading and scaling */ 227 + battery_delay_chan = 0; 228 + imx233_lradc_reserve_delay(battery_delay_chan); 229 + /* setup delay to trigger battery channel and retrigger itself. 230 + * The counter runs at 2KHz so a delay of 200 will trigger 10 231 + * conversions per seconds */ 232 + imx233_lradc_setup_delay(battery_delay_chan, 1 << battery_chan, 233 + 1 << battery_delay_chan, 0, 200); 234 + imx233_lradc_kick_delay(battery_delay_chan); 235 + /* enable automatic conversion, use Li-Ion type battery */ 236 + imx233_lradc_setup_battery_conversion(true, HW_LRADC_CONVERSION__SCALE_FACTOR__LI_ION); 162 237 }
+11 -2
firmware/target/arm/imx233/lradc-imx233.h
··· 43 43 #define HW_LRADC_CTRL2__TEMP_ISRC1_BM 0xf0 44 44 #define HW_LRADC_CTRL2__TEMP_ISRC0_BP 0 45 45 #define HW_LRADC_CTRL2__TEMP_ISRC0_BM 0xf 46 + #define HW_LRADC_CTRL2__TEMP_ISRCx_BP(x) (4 * (x)) 47 + #define HW_LRADC_CTRL2__TEMP_ISRCx_BM(x) (0xf << (4 * (x))) 48 + #define HW_LRADC_CTRL2__TEMP_ISRC__0uA 0 49 + #define HW_LRADC_CTRL2__TEMP_ISRC__20uA 1 50 + #define HW_LRADC_CTRL2__TEMP_ISRC__300uA 15 46 51 #define HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE0 (1 << 8) 47 52 #define HW_LRADC_CTRL2__TEMP_SENSOR_IENABLE1 (1 << 9) 53 + #define HW_LRADC_CTRL2__TEMP_SENSOR_IENABLEx(x) (1 << (8 + (x))) 48 54 #define HW_LRADC_CTRL2__TEMPSENSE_PWD (1 << 15) 49 55 #define HW_LRADC_CTRL2__DIVIDE_BY_TWO(x) (1 << ((x) + 24)) 50 56 ··· 59 65 #define HW_LRADC_STATUS (*(volatile uint32_t *)(HW_LRADC_BASE + 0x40)) 60 66 61 67 #define HW_LRADC_CHx(x) (*(volatile uint32_t *)(HW_LRADC_BASE + 0x50 + (x) * 0x10)) 62 - #define HW_LRADC_CHx__NUM_SAMPLES_BM (0xf << 24) 68 + #define HW_LRADC_CHx__NUM_SAMPLES_BM (0x1f << 24) 63 69 #define HW_LRADC_CHx__NUM_SAMPLES_BP 24 64 70 #define HW_LRADC_CHx__ACCUMULATE 29 65 71 #define HW_LRADC_CHx__VALUE_BM 0x3ffff ··· 127 133 void imx233_lradc_release_delay(int dchan); 128 134 129 135 /* enable sensing and return temperature in kelvin, 130 - * channels must already be configured as nmos and pmos */ 136 + * channels needs not to be configured */ 131 137 int imx233_lradc_sense_die_temperature(int nmos_chan, int pmos_chan); 138 + /* return *raw* external temperature, might need some transformation 139 + * channel needs not to be configured */ 140 + int imx233_lradc_sense_ext_temperature(int chan, int sensor); 132 141 133 142 void imx233_lradc_setup_battery_conversion(bool automatic, unsigned long scale_factor); 134 143 // read scaled voltage, only available after proper setup
+5 -3
firmware/target/arm/imx233/sansa-fuzeplus/adc-fuzeplus.c
··· 26 26 [ADC_BATTERY] = IMX233_ADC_BATTERY, 27 27 [ADC_DIE_TEMP] = IMX233_ADC_DIE_TEMP, 28 28 [ADC_VDDIO] = IMX233_ADC_VDDIO, 29 - [ADC_5V] = HW_LRADC_CHANNEL_5V, 29 + [ADC_5V] = IMX233_ADC_VDD5V, 30 + [ADC_BATT_TEMP] = IMX233_ADC_BATT_TEMP, 30 31 [ADC_CH2] = HW_LRADC_CHANNEL(2), 31 32 }; 32 33 ··· 34 35 { 35 36 "Battery(raw)", 36 37 "Die temperature(°C)", 37 - "VddIO", 38 - "Vdd5V", 38 + "VddIO(mV)", 39 + "Vdd5V(mV)", 40 + "Battery temperature(raw)", 39 41 "Channel 2", 40 42 };
+5 -2
firmware/target/arm/imx233/sansa-fuzeplus/adc-target.h
··· 21 21 #ifndef _ADC_TARGET_H_ 22 22 #define _ADC_TARGET_H_ 23 23 24 - #define NUM_ADC_CHANNELS 5 24 + #define NUM_ADC_CHANNELS 6 25 25 26 26 #define ADC_BATTERY 0 27 27 #define ADC_DIE_TEMP 1 28 28 #define ADC_VDDIO 2 29 29 #define ADC_5V 3 30 - #define ADC_CH2 4 30 + #define ADC_BATT_TEMP 4 31 + #define ADC_CH2 5 32 + 33 + #define IMX233_ADC_BATT_TEMP_SENSOR 0 31 34 32 35 #endif
+2
firmware/target/arm/imx233/system-imx233.c
··· 31 31 #include "ssp-imx233.h" 32 32 #include "i2c-imx233.h" 33 33 #include "dcp-imx233.h" 34 + #include "lradc-imx233.h" 34 35 #include "lcd.h" 35 36 #include "backlight-target.h" 36 37 #include "button.h" ··· 214 215 imx233_dma_init(); 215 216 imx233_ssp_init(); 216 217 imx233_dcp_init(); 218 + imx233_lradc_init(); 217 219 imx233_i2c_init(); 218 220 #if defined(SANSA_FUZEPLUS) && !defined(BOOTLOADER) 219 221 fmradio_i2c_init();