1- # Hardware initialization for Fri3d Camp 2024 Badge
1+ # Hardware initialization for Fri3d Camp 2026 Badge
2+
3+ # TODO:
4+ # - touch screen / touch pad
5+ # - IMU is different from fri3d_2024 (also address 0x6A instead of 0x6B)
6+ # - I2S audio (communicator) is the same
7+ # - headphone jack audio?
8+ # - headphone jack microphone?
9+ # - CH32X035GxUx over I2C:
10+ # - battery voltage measurement
11+ # - analog joystick
12+ # - digital buttons (X,Y,A,B, MENU)
13+ # - buzzer
14+ # - audio DAC emulation using buzzer might be slow or need specific buffered protocol
15+
216from machine import Pin , SPI , SDCard
317import st7789
418import lcd_bus
@@ -262,34 +276,16 @@ def keypad_read_cb(indev, data):
262276indev .set_display (disp ) # different from display
263277indev .enable (True ) # NOQA
264278
265- # Battery voltage ADC measuring
266- # NOTE: GPIO13 is on ADC2, which requires WiFi to be disabled during reading on ESP32-S3.
267- # battery_voltage.py handles this automatically: disables WiFi, reads ADC, reconnects WiFi.
279+ # Battery voltage ADC measuring: sits on PC0 of CH32X035GxUx
268280import mpos .battery_voltage
269- """
270- best fit on battery power:
271- 2482 is 4.180
272- 2470 is 4.170
273- 2457 is 4.147
274- # 2444 is 4.12
275- 2433 is 4.109
276- 2429 is 4.102
277- 2393 is 4.044
278- 2369 is 4.000
279- 2343 is 3.957
280- 2319 is 3.916
281- 2269 is 3.831
282- 2227 is 3.769
283- """
284281def adc_to_voltage (adc_value ):
285282 """
286283 Convert raw ADC value to battery voltage using calibrated linear function.
287284 Calibration data shows linear relationship: voltage = -0.0016237 * adc + 8.2035
288285 This is ~10x more accurate than simple scaling (error ~0.01V vs ~0.1V).
289286 """
290287 return (0.001651 * adc_value + 0.08709 )
291-
292- mpos .battery_voltage .init_adc (13 , adc_to_voltage )
288+ #mpos.battery_voltage.init_adc(13, adc_to_voltage) # TODO
293289
294290import mpos .sdcard
295291mpos .sdcard .init (spi_bus , cs_pin = 14 )
@@ -298,8 +294,8 @@ def adc_to_voltage(adc_value):
298294from machine import PWM , Pin
299295from mpos import AudioFlinger
300296
301- # Initialize buzzer (GPIO 46)
302- buzzer = PWM (Pin (46 ), freq = 550 , duty = 0 )
297+ # Initialize buzzer: sits on PC14/CC1 of the CH32X035GxUx
298+ # buzzer = PWM(Pin(46), freq=550, duty=0)
303299
304300# I2S pin configuration for audio output (DAC) and input (microphone)
305301# Note: I2S is created per-stream, not at boot (only one instance can exist)
@@ -316,7 +312,7 @@ def adc_to_voltage(adc_value):
316312}
317313
318314# Initialize AudioFlinger with I2S and buzzer
319- AudioFlinger (i2s_pins = i2s_pins , buzzer_instance = buzzer )
315+ # AudioFlinger(i2s_pins=i2s_pins, buzzer_instance=buzzer)
320316
321317# === LED HARDWARE ===
322318import mpos .lights as LightsManager
@@ -327,71 +323,9 @@ def adc_to_voltage(adc_value):
327323# === SENSOR HARDWARE ===
328324import mpos .sensor_manager as SensorManager
329325
330- # Create I2C bus for IMU (different pins from display)
326+ # Create I2C bus for IMU
331327from machine import I2C
332328imu_i2c = I2C (0 , sda = Pin (9 ), scl = Pin (18 ))
333- SensorManager .init (imu_i2c , address = 0x6B , mounted_position = SensorManager .FACING_EARTH )
329+ SensorManager .init (imu_i2c , address = 0x6A , mounted_position = SensorManager .FACING_EARTH )
334330
335- print ("Fri3d hardware: Audio, LEDs, and sensors initialized" )
336-
337- # === STARTUP "WOW" EFFECT ===
338- import time
339- import _thread
340-
341- def startup_wow_effect ():
342- """
343- Epic startup effect with rainbow LED chase and upbeat startup jingle.
344- Runs in background thread to avoid blocking boot.
345- """
346- try :
347- # Startup jingle: Happy upbeat sequence (ascending scale with flourish)
348- startup_jingle = "Startup:d=8,o=6,b=200:c,d,e,g,4c7,4e,4c7"
349- #startup_jingle = "ShortBeeps:d=32,o=5,b=320:c6,c7"
350-
351- # Start the jingle
352- AudioFlinger .play_rtttl (
353- startup_jingle ,
354- stream_type = AudioFlinger .STREAM_NOTIFICATION ,
355- volume = 60
356- )
357-
358- # Rainbow colors for the 5 LEDs
359- rainbow = [
360- (255 , 0 , 0 ), # Red
361- (255 , 128 , 0 ), # Orange
362- (255 , 255 , 0 ), # Yellow
363- (0 , 255 , 0 ), # Green
364- (0 , 0 , 255 ), # Blue
365- ]
366-
367- # Rainbow sweep effect (3 passes, getting faster)
368- for pass_num in range (3 ):
369- for i in range (5 ):
370- # Light up LEDs progressively
371- for j in range (i + 1 ):
372- LightsManager .set_led (j , * rainbow [j ])
373- LightsManager .write ()
374- time .sleep_ms (80 - pass_num * 20 ) # Speed up each pass
375-
376- # Flash all LEDs bright white
377- LightsManager .set_all (255 , 255 , 255 )
378- LightsManager .write ()
379- time .sleep_ms (150 )
380-
381- # Rainbow finale
382- for i in range (5 ):
383- LightsManager .set_led (i , * rainbow [i ])
384- LightsManager .write ()
385- time .sleep_ms (300 )
386-
387- # Fade out
388- LightsManager .clear ()
389- LightsManager .write ()
390-
391- except Exception as e :
392- print (f"Startup effect error: { e } " )
393-
394- _thread .stack_size (mpos .apps .good_stack_size ()) # default stack size won't work, crashes!
395- _thread .start_new_thread (startup_wow_effect , ())
396-
397- print ("fri3d_2024.py finished" )
331+ print ("fri3d_2026.py finished" )
0 commit comments