import time import machine from machine import Pin, SPI, I2C, I2S import ili9341 from ft6336u import FT6336U from audio_util import ES8311 def main(): print("--- Starting RAM-based Touch Mic Demo ---") # 1. Initialize display spi = SPI(1, baudrate=40000000, polarity=0, phase=0, sck=Pin(12), mosi=Pin(11), miso=Pin(13)) display = ili9341.ILI9341(spi, cs=Pin(10), dc=Pin(46), bl=Pin(45), rst=None) display.clear(0) display.text("RAM Touch Mic", 10, 10, 1) display.show() # 2. Initialize touch i2c = I2C(0, sda=Pin(16), scl=Pin(15)) touch = FT6336U(i2c, rst_pin=18, int_pin=17, width=320, height=240, swap_xy=True, invert_x=False, invert_y=True) # 3. Configure audio codec ES8311 # Generate MCLK PWM on GPIO 4 at 6.144 MHz mclk_pin = Pin(4, Pin.OUT) mclk_pwm = machine.PWM(mclk_pin) mclk_pwm.freq(6144000) mclk_pwm.duty_u16(32768) codec = ES8311(i2c) if not codec.init(sample_rate=16000): print("ES8311 init failed!") return # Set speaker volume to 95% codec.set_volume(95) # Configure microphone registers on ES8311 try: codec._write(0x14, 0x1A) # Enable analog mic input & set PGA gain codec._write(0x16, 0x01) # Boost MIC digital gain to +6dB to prevent saturation codec._write(0x17, 0xC8) # Set ADC digital volume print("Microphone registers initialized with gain boost.") except Exception as e: print("Failed to write microphone registers:", e) amp_pin = Pin(1, Pin.OUT, value=1) # start with amp disabled (1 = disabled) # We allocate a buffer for I2S read buffer = bytearray(2048) while True: display.clear(0) display.text("RAM Touch Mic", 10, 10, 1) display.line(10, 22, 310, 22, 1) display.text("Press & hold screen", 50, 80, 1) display.text("to record voice...", 50, 100, 1) display.show() # Wait for touch while not touch.is_touched(): time.sleep_ms(30) print("Touch detected! Starting recording to RAM...") display.clear(0) display.text("Recording...", 10, 10, 1) display.line(10, 22, 310, 22, 1) display.text("SPEAK NOW!", 80, 80, 1) display.fill_rect(130, 110, 30, 30, 1) display.show() # 4. Open I2S RX for recording i2s_rx = I2S(1, sck=Pin(5), ws=Pin(7), sd=Pin(6), mode=I2S.RX, ibuf=8000, rate=16000, bits=16, format=I2S.STEREO) audio_chunks = [] total_data_bytes = 0 try: # Record loop - append chunks directly in RAM while touch.is_touched(): bytes_read = i2s_rx.readinto(buffer) if bytes_read > 0: audio_chunks.append(bytes(buffer[:bytes_read])) total_data_bytes += bytes_read print(f"Touch released! Recorded {total_data_bytes} bytes in RAM.") except Exception as e: print("Error recording:", e) finally: i2s_rx.deinit() # 5. Playback recorded audio display.clear(0) display.text("Playing back...", 10, 10, 1) display.line(10, 22, 310, 22, 1) display.text("Listening to RAM...", 50, 80, 1) display.show() print("Starting playback from RAM...") amp_pin.value(0) # Enable amp i2s_tx = I2S(1, sck=Pin(5), ws=Pin(7), sd=Pin(8), mode=I2S.TX, ibuf=4096, rate=16000, bits=16, format=I2S.STEREO) try: for chunk in audio_chunks: i2s_tx.write(chunk) except Exception as e: print("Error during playback:", e) finally: time.sleep_ms(100) # wait to clear buffer amp_pin.value(1) # Disable amp i2s_tx.deinit() print("Playback finished.") display.clear(0) display.text("Finished!", 10, 10, 1) display.line(10, 22, 310, 22, 1) display.text("Touch screen to", 50, 80, 1) display.text("record again.", 50, 100, 1) display.show() # Debounce touch release while touch.is_touched(): time.sleep_ms(30) time.sleep_ms(400) if __name__ == "__main__": main()