2121
2222// Code version numbers
2323#define VERSION_MAJOR 0
24- #define VERSION_MINOR 4
24+ #define VERSION_MINOR 5
2525
2626// Global pointer for I2C register selection (addresses 0–8)
2727volatile uint8_t pointer = 0 ;
@@ -34,6 +34,8 @@ uint8_t pwm_duty_cycles[4] = {0};
3434// Cached ADC values for channels 0–3 (corresponding to I2C addresses 4–7)
3535// These values are updated continuously in the background.
3636volatile uint16_t adc_cache [4 ] = {0 };
37+ volatile uint32_t filtered_adc [4 ] = {0 , 0 , 0 , 0 };
38+ #define ALPHA 0.25f
3739
3840// -----------------------------------------------------------------------------
3941// Function: set_up_pwm_pin
@@ -52,18 +54,16 @@ static inline void set_up_pwm_pin(uint pin) {
5254}
5355
5456
55- // Increase oversampling factor to 1024 samples for an extra bit of resolution.
56- uint16_t read_adc_oversampled (uint8_t adc_channel ) {
57+ uint32_t read_adc_oversampled (uint8_t adc_channel ) {
5758 adc_select_input (adc_channel );
58- const int num_samples = 1024 ; // 4^5 samples to gain 5 extra bits
59+ const int num_samples = 1024 ;
5960 uint32_t sum = 0 ;
6061 for (int i = 0 ; i < num_samples ; i ++ ) {
6162 sum += adc_read ();
62- // Continue to add a random delay between 1 and 5 µs to help with dithering.
63- sleep_us (1 + (rand () % 5 ));
63+ sleep_us (1 + (rand () % 3 ));
6464 }
65- // Shift right by 5 bits to account for the increased number of samples.
66- return (uint16_t )( sum >> 5 );
65+ // Shift down by 5 bits but keep it in 32-bit
66+ return (sum >> 5 );
6767}
6868
6969// -----------------------------------------------------------------------------
@@ -164,14 +164,29 @@ int main() {
164164 irq_set_exclusive_handler (I2C1_IRQ , i2c1_irq_handler );
165165 irq_set_enabled (I2C1_IRQ , true);
166166
167- // Background loop: continuously update the cached ADC values.
167+ // Variables for scheduling updates
168+ uint32_t loop_counter = 0 ;
168169 while (true) {
169- for (uint8_t channel = 0 ; channel < 4 ; channel ++ ) {
170- adc_cache [channel ] = read_adc_oversampled (channel );
170+
171+ for (uint8_t channel = 2 ; channel < 4 ; channel ++ ) {
172+ uint32_t new_sample = read_adc_oversampled (channel );
173+ // Update the filtered value with a heavy low-pass filter:
174+ filtered_adc [channel ] = (uint32_t )((1.0f - ALPHA ) * filtered_adc [channel ] + ALPHA * new_sample );
175+ // Use the filtered value as the cached result for I2C reads.
176+ adc_cache [channel ] = (uint16_t )filtered_adc [channel ];
171177 }
178+
179+ // Low-priority channels (0 and 1) are updated only once every N loops.
180+ if (loop_counter % 100 == 0 ) {
181+
182+ adc_cache [0 ] = read_adc_oversampled (0 );
183+ adc_cache [1 ] = read_adc_oversampled (1 );
184+
185+ }
186+
187+ loop_counter ++ ;
172188 // A short delay to yield; adjust as needed.
173189 sleep_ms (1 );
174190 }
175-
176191 return 0 ;
177192}
0 commit comments