Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
JuanVi
Published

A.I. Assistant Pendant

The A.I. Pendant helps the visually impaired navigate their surroundings by taking photos and providing real-time descriptions through A.I.

ExpertFull instructions provided200
A.I. Assistant Pendant

Things used in this project

Hardware components

Seeed Studio XIAO ESP32S3 Sense
Seeed Studio XIAO ESP32S3 Sense
×1
PCBWay Custom PCB
PCBWay Custom PCB
×1
Speaker 3W 4R 40mm
×1
Li-Po Battery 3.7V 400mA
×1
SMD 0805 100K Resistor
×1
SMD 0805 10K Resistor
×1
SMD 0805 100nF Capacitor
×1
SMD Button 6x6x15mm
×1
SPDT Sliding Switch MSS22D18 2.5mm
×1
MAX98357AETE_T (1)
×1
Ferrite Bead 0805: BLM21AG121SN1D (1)
×2
SMD 0805 220pF Capacitor (1)
×2
SMD 0805 10uF Capacitor (1)
×1
SMD 0805 100nF Capacitor (1)
×1
JST 2.0mm Pitch THT 2 Pos, Right Angle
×1
JST 2.0mm Pitch Female 2 Pos (1 for Speaker, 1 for Battery)
×2
Pin Header 2.54mm 7 Pos
×2
Pin Socket 2.54mm 7 Pos
×2

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Solder Flux, Soldering
Solder Flux, Soldering
Solder Paste, Rework
Solder Paste, Rework
Hot Air Station, Industrial
Hot Air Station, Industrial
Hot Plate, Programmable
Hot Plate, Programmable
Wire Stripper / Crimper, 10AWG - 20AWG Strip
Wire Stripper / Crimper, 10AWG - 20AWG Strip

Story

Read more

Custom parts and enclosures

SolidEdge Files

ESP32 FRONT

ESP32 BACK

BUTTON CAP 2

BUTTON CAP 1

BUTTON EXTENDER (x2)

Schematics

Schematic PDF

Front PCB

Back_PCB

PCB_MOUNT_F

PCB_MOUNT_B

Schematic Kicad

PCB Kicad

Code

BUILD2GETHER_ESP32.ino

C/C++
main
#include "network_param.h"
#include "AudioMic.h"
#include "CloudSpeechClient.h"
#include "Audio.h"
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#include <ChatGPT.hpp>
#include "Base64ImageData.h"

#include "esp_camera.h"
#include "SPIFFS.h"
#include <WiFi.h>
#include "base64.h"
#include "CameraConfig.h"

// AUDIO I2S PIN OUTPUT
#define I2S_LRC D3
#define I2S_DOUT D1
#define I2S_BCLK D2
#define I2S_MCLK 0

Audio audio(false, 3, 1); // USE I2S 1 (I2S0 FOR MICROPHONE AS I2S_MODE_PDM IS ONLY IN PIN I2S0)


WiFiClientSecure client_audio;
ChatGPT<WiFiClientSecure> chatGPT_Client(&client_audio, "v1", chatgpt_token, 60000);


// Variables for buttons
int button_pressed_camera = 0;
int button_pressed_microphone = 0;

const int button_camera = D8;
const int button_microphone = D9;

// Variable for audio transcript
String audio_transcript;

// Variables for camera
const char *photoPath = "/photo.jpg"; // File path for the photo
const char *base64ImageDataChar = nullptr;

void button_camera_trigger() {
  if (button_pressed_camera == 0) {
    button_pressed_camera = 1;
  }
}

void button_microphone_trigger() {
  if (button_pressed_microphone == 0) {
    button_pressed_microphone = 1;
  }
}

void capturePhoto() {
  camera_fb_t *photo = esp_camera_fb_get();
  if (!photo) {
    Serial.println("Error capturing photo");
    return;
  }

  // Save the photo in SPIFFS
  File photoFile = SPIFFS.open(photoPath, FILE_WRITE);
  if (!photoFile) {
    Serial.println("Error opening file for writing");
    return;
  }

  photoFile.write(photo->buf, photo->len);
  photoFile.close();

  Serial.println("Photo saved at: " + String(photoPath));

  esp_camera_fb_return(photo);
  //verifyImage(photoPath);
}

void verifyImage(const char *filePath) {
  File file = SPIFFS.open(filePath, FILE_READ);
  if (!file) {
    Serial.println("Error opening file for reading");
    return;
  }

  size_t fileSize = file.size();
  uint8_t *buffer = new uint8_t[fileSize];
  file.read(buffer, fileSize);
  file.close();

  String base64Data = base64::encode(buffer, fileSize);

  delete[] buffer;

  Serial.println("Image saved in Base64:\n");
  Serial.println(base64Data);

  // Optimized creation of base64DataWithPrefix
  String base64DataWithPrefix = "data:image/jpeg;base64," + base64Data;

  base64ImageDataChar = base64DataWithPrefix.c_str();

  /* String result;
    Serial.println("\n\n[ChatGPT] - Asking a Vision Question");
    if (chatGPT_Client.vision_question("gpt-4o", "user", "text", "Whats in this image?", "image_url", base64ImageDataChar, "auto", 500, true, result)) {
      Serial.print("[ChatGPT] Response: ");
      Serial.println(result);
    } else {
      Serial.print("[ChatGPT] Error: ");
      Serial.println(result);
    }
    Serial.println("END");*/
}

void ChatGPT_Vision(const String& question) {
  /*
  model: Model to use for generating the response (e.g., "gpt-4o").
  role: Role of the message sender (e.g., "user" or "assistant").
  type: Type of content (e.g., "text").
  text: Text content of the message.
  image_type: Type of the image (e.g., "image_url").
  image_url: URL of the image or Base64 Image Data
  detail: Detail level of the image (e.g., "high", "low", "auto").
  max_tokens: Maximum number of tokens to generate in the response.
  content_only: Flag indicating whether to extract only the content of the response. (e.g., true - answer only, false - full response)
  result: Reference to a String variable to store the result of the API call.
  */

  String result;
  Serial.println("\n\n[ChatGPT] - Asking a Vision Question");
  if (chatGPT_Client.vision_question("gpt-4o", "user", "text", question.c_str(), "image_url", base64ImageDataChar, "auto", 500, true, result)) {
    Serial.print("[ChatGPT] Response: ");
    Serial.println(result);
    audio.openai_speech(chatgpt_token, "tts-1", result, "shimmer", "mp3", "1");
  } else {
    Serial.print("[ChatGPT] Error: ");
    Serial.println(result);
  }
}

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);
  //while(!Serial);
  Serial.println("START");
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(1500);
  // BUTTONS
  pinMode(button_camera, INPUT);
  attachInterrupt(digitalPinToInterrupt(button_camera), button_camera_trigger, FALLING);

  pinMode(button_microphone, INPUT);
  attachInterrupt(digitalPinToInterrupt(button_microphone), button_microphone_trigger, FALLING);
  // Audio
  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT, -1);
  audio.setVolume(7);

  client_audio.setInsecure();

  // CAMERA
  camera_config_t config = getCameraConfig();

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Error initializing the camera: 0x%x", err);
    audio.connecttospeech("ERROR CAMERA", "en");
    return;
  }

  // Mount the SPIFFS file system
  if (!SPIFFS.begin(true)) {
    Serial.println("Error mounting SPIFFS");
    audio.connecttospeech("ERROR SPIFFS", "en");
    return;
  }

  Serial.println("Camera ready");
  //audio.connecttospeech("CAMERA READY", "en");

  // CHATGPT CLIENT
}

void loop() {
  // Main code here, to run repeatedly:
  if (button_pressed_camera == 1) {
    capturePhoto();
    button_pressed_camera = 0;
  } else if (button_pressed_microphone == 1) {
    verifyImage(photoPath);
    //Serial.println(base64ImageDataChar);

    Serial.println("\r\nRecord start!\r\n");
    AudioMic* audio_Mic = new AudioMic(SENSE);

    audio_Mic->Record();
    Serial.println("Recording Completed. Now Processing...");
    //audio.connecttospeech("RECORD FINISH", "en");

    CloudSpeechClient* cloudSpeechClient = new CloudSpeechClient(USE_APIKEY);
    cloudSpeechClient->Transcribe(audio_Mic);

    Serial.print("Transcript: ");
    Serial.println(transcript);
    //audio.connecttospeech("TRANSCRIPT", "en");

    audio_transcript = String(transcript);

    delete cloudSpeechClient;
    delete audio_Mic;

    Serial.print("Transcript AUDIO: ");
    Serial.println(audio_transcript);

    //audio.connecttospeech(transcript, "es");
    button_pressed_microphone = 0;
    ChatGPT_Vision(audio_transcript);
  }
  audio.loop();
}

void audio_info(const char *info) {
  Serial.print("audio_info: "); Serial.println(info);
  if (strcmp(info, "End of Stream.") == 0) {
    Serial.println("FINISH");
    esp_restart();
  }
}

network_param.h

C Header File
#ifndef _NETWORK_PARAM_H
#define _NETWORK_PARAM_H

inline const char *ssid = "ssid";
inline const char *password = "password";

inline const char*  server = "speech.googleapis.com";
inline const char* chatgpt_token = "your-api-key";//CHATGPT API KEY


// To get the certificate for your region run:
// openssl s_client -showcerts -connect speech.googleapis.com:443
// Copy the certificate (all lines between and including ---BEGIN CERTIFICATE---
// and --END CERTIFICATE--) to root.cert and put here on the root_cert variable.
inline const char* root_ca= 

"-----BEGIN CERTIFICATE-----\n"
"MIIFCzCCAvOgAwIBAgIQf/AFoHxM3tEArZ1mpRB7mDANBgkqhkiG9w0BAQsFADBH\n"
"MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM\n"
"QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw\n"
"MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl\n"
"cnZpY2VzMQwwCgYDVQQDEwNXUjIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n"
"AoIBAQCp/5x/RR5wqFOfytnlDd5GV1d9vI+aWqxG8YSau5HbyfsvAfuSCQAWXqAc\n"
"+MGr+XgvSszYhaLYWTwO0xj7sfUkDSbutltkdnwUxy96zqhMt/TZCPzfhyM1IKji\n"
"aeKMTj+xWfpgoh6zySBTGYLKNlNtYE3pAJH8do1cCA8Kwtzxc2vFE24KT3rC8gIc\n"
"LrRjg9ox9i11MLL7q8Ju26nADrn5Z9TDJVd06wW06Y613ijNzHoU5HEDy01hLmFX\n"
"xRmpC5iEGuh5KdmyjS//V2pm4M6rlagplmNwEmceOuHbsCFx13ye/aoXbv4r+zgX\n"
"FNFmp6+atXDMyGOBOozAKql2N87jAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG\n"
"MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/\n"
"AgEAMB0GA1UdDgQWBBTeGx7teRXUPjckwyG77DQ5bUKyMDAfBgNVHSMEGDAWgBTk\n"
"rysmcRorSCeFL1JmLO/wiRNxPjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG\n"
"GGh0dHA6Ly9pLnBraS5nb29nL3IxLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw\n"
"Oi8vYy5wa2kuZ29vZy9yL3IxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq\n"
"hkiG9w0BAQsFAAOCAgEARXWL5R87RBOWGqtY8TXJbz3S0DNKhjO6V1FP7sQ02hYS\n"
"TL8Tnw3UVOlIecAwPJQl8hr0ujKUtjNyC4XuCRElNJThb0Lbgpt7fyqaqf9/qdLe\n"
"SiDLs/sDA7j4BwXaWZIvGEaYzq9yviQmsR4ATb0IrZNBRAq7x9UBhb+TV+PfdBJT\n"
"DhEl05vc3ssnbrPCuTNiOcLgNeFbpwkuGcuRKnZc8d/KI4RApW//mkHgte8y0YWu\n"
"ryUJ8GLFbsLIbjL9uNrizkqRSvOFVU6xddZIMy9vhNkSXJ/UcZhjJY1pXAprffJB\n"
"vei7j+Qi151lRehMCofa6WBmiA4fx+FOVsV2/7R6V2nyAiIJJkEd2nSi5SnzxJrl\n"
"Xdaqev3htytmOPvoKWa676ATL/hzfvDaQBEcXd2Ppvy+275W+DKcH0FBbX62xevG\n"
"iza3F4ydzxl6NJ8hk8R+dDXSqv1MbRT1ybB5W0k8878XSOjvmiYTDIfyc9acxVJr\n"
"Y/cykHipa+te1pOhv7wYPYtZ9orGBV5SGOJm4NrB3K1aJar0RfzxC3ikr7Dyc6Qw\n"
"qDTBU39CluVIQeuQRgwG3MuSxl7zRERDRilGoKb8uY45JzmxWuKxrfwT/478JuHU\n"
"/oTxUFqOl2stKnn7QGTq8z29W+GgBLCXSBxC9epaHM0myFH/FJlniXJfHeytWt0=\n"
"-----END CERTIFICATE-----\n";

// Getting Access Token : 
// At first, you should get service account key (JSON file).
// Type below command in Google Cloud Shell to get AccessToken: 
// $ gcloud auth activate-service-account --key-file=KEY_FILE   (KEY_FILE is your service account key file)
// $ gcloud auth print-access-token
// The Access Token is expired in an hour.
// Google recommends to use Access Token.
//const String AccessToken = "";

// It is also possible to use "API Key" instead of "Access Token". It doesn't have time limit.
inline const String ApiKey = "Googles Speech To Texy Api Key";

// see https://cloud.google.com/docs/authentication?hl=ja#getting_credentials_for_server-centric_flow
// see https://qiita.com/basi/items/3623a576b754f738138e (Japanese)

#endif  // _NETWORK_PARAM_H

AudioMic.cpp

C/C++
#include "AudioMic.h"

AudioMic::AudioMic(MicType micType) {
  wavData = new char*[wavDataSize/dividedWavDataSize];
  for (int i = 0; i < wavDataSize/dividedWavDataSize; ++i) wavData[i] = new char[dividedWavDataSize];
  i2s = new I2S(micType);
}

AudioMic::~AudioMic() {
  for (int i = 0; i < wavDataSize/dividedWavDataSize; ++i) delete[] wavData[i];
  delete[] wavData;
  delete i2s;
}

void AudioMic::CreateWavHeader(byte* header, int waveDataSize){
  header[0] = 'R';
  header[1] = 'I';
  header[2] = 'F';
  header[3] = 'F';
  unsigned int fileSizeMinus8 = waveDataSize + 44 - 8;
  header[4] = (byte)(fileSizeMinus8 & 0xFF);
  header[5] = (byte)((fileSizeMinus8 >> 8) & 0xFF);
  header[6] = (byte)((fileSizeMinus8 >> 16) & 0xFF);
  header[7] = (byte)((fileSizeMinus8 >> 24) & 0xFF);
  header[8] = 'W';
  header[9] = 'A';
  header[10] = 'V';
  header[11] = 'E';
  header[12] = 'f';
  header[13] = 'm';
  header[14] = 't';
  header[15] = ' ';
  header[16] = 0x10;  // linear PCM
  header[17] = 0x00;
  header[18] = 0x00;
  header[19] = 0x00;
  header[20] = 0x01;  // linear PCM
  header[21] = 0x00;
  header[22] = 0x01;  // monoral
  header[23] = 0x00;
  header[24] = 0x80;  // sampling rate 16000
  header[25] = 0x3E;
  header[26] = 0x00;
  header[27] = 0x00;
  header[28] = 0x00;  // Byte/sec = 16000x2x1 = 32000
  header[29] = 0x7D;
  header[30] = 0x00;
  header[31] = 0x00;
  header[32] = 0x02;  // 16bit monoral
  header[33] = 0x00;
  header[34] = 0x10;  // 16bit
  header[35] = 0x00;
  header[36] = 'd';
  header[37] = 'a';
  header[38] = 't';
  header[39] = 'a';
  header[40] = (byte)(waveDataSize & 0xFF);
  header[41] = (byte)((waveDataSize >> 8) & 0xFF);
  header[42] = (byte)((waveDataSize >> 16) & 0xFF);
  header[43] = (byte)((waveDataSize >> 24) & 0xFF);
}

void AudioMic::Record() {
  CreateWavHeader(paddedHeader, wavDataSize);
  int bitBitPerSample = i2s->GetBitPerSample();
  if (bitBitPerSample == 16) {
    for (int j = 0; j < wavDataSize/dividedWavDataSize; ++j) {
      i2s->Read(i2sBuffer, i2sBufferSize/2);
      for (int i = 0; i < i2sBufferSize/8; ++i) {
        wavData[j][2*i] = i2sBuffer[4*i + 2];
        wavData[j][2*i + 1] = i2sBuffer[4*i + 3];
      }
    }
  }
  else if (bitBitPerSample == 32) {
    for (int j = 0; j < wavDataSize/dividedWavDataSize; ++j) {
      i2s->Read(i2sBuffer, i2sBufferSize);
      for (int i = 0; i < i2sBufferSize/8; ++i) {
        wavData[j][2*i] = i2sBuffer[8*i + 2];
        wavData[j][2*i + 1] = i2sBuffer[8*i + 3];
      }
    }
  }
}

AudioMic.h

C Header File
#ifndef _AUDIOMIC_H
#define _AUDIOMIC_H

#include <Arduino.h>
#include "I2S.h"

// 16bit, monoral, 16000Hz,  linear PCM
class AudioMic {
  I2S* i2s;
  static const int headerSize = 44;
  static const int i2sBufferSize = 12000;
  char i2sBuffer[i2sBufferSize];
  void CreateWavHeader(byte* header, int waveDataSize);

public:
  static const int wavDataSize = 90000;                   // It must be multiple of dividedWavDataSize. Recording time is about 1.9 second.
  static const int dividedWavDataSize = i2sBufferSize/4;
  char** wavData;                                         // It's divided. Because large continuous memory area can't be allocated in esp32.
  byte paddedHeader[headerSize + 4] = {0};                // The size must be multiple of 3 for Base64 encoding. Additional byte size must be even because wave data is 16bit.

  AudioMic(MicType micType);
  ~AudioMic();
  void Record();
};

#endif // _AUDIO_H

Base64ImageData.h

C Header File
Example of base64 encoded Image of an Orange Cat
#ifndef BASE64_IMAGE_DATA_H
#define BASE64_IMAGE_DATA_H

// The image is an orange cat :).
const char* base64ImageData = "data:image/jpeg;base64,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lgkc4Vio9qrTWkytg7ZN394c01qTcqvHGgIeEqV6ADrUT7pFCBSiDrnqaaBu5Q1IRx2xG7k8DbXNRjA+Y85pjiWVAc5FSbCOtK5VjtzNgYzgewpFnRiVy5A67hgV47PTRF56R5wGOP7qgCq8lxk7sszHjH+H/wBasb9DRIs2sD5BcbWxkj+6K3bIBQfuoh/iP+cmuilF3MakjYs328Mx2Z43Hk1cBR24OPYV6VKzVjhqdy8oi2bV6fzqhcxYJweK2aMUzPmX5l3fdHQVTmJyRjisxlYr6dqaV+bFNEMryxKeSOSartGMdvpVoVzI1iJGtyCOR7VzX2Ubs0pbmsNh4g2dDQWIBzUFnWrPGg5ReOmMVHLettxHGx+pwK8qT00PQS1KrPJIp3Msag5OOadC8VuvmBWZ+ilxz9ay8zS+li5HcFwuPmkY9SeF9/rVyGXy2VyxbGeTxit6ZjM2bW+UpvAH+z6D3q3bzZPmB+vGTXZTfvI5ZLRmpFMvUHI9fWpXZWXuc12M5CpJCOSRn2qi9vu+Y8bug9qloLleRVjXYo+Y8VUlJEi4555oSE2VpjkEZIxzVd2O0ZwatIRkagxOVzwfaszyxnNRNamsHoRSLgdOtV5IW28c1Ni7n//ZAP/tFPBQaG90b3Nob3AgMy4wADhCSU0EJQAAAAAAEAAAAAAAAAAAAAAAAAAAAAA4QklNA+0AAAAAABAASAAAAAEAAgBIAAAAAQACOEJJTQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAB4OEJJTQQZAAAAAAAEAAAAHjhCSU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAI4QklNA/UAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAAAAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA/gAAAAAAHAAAP////////////////////////////8D6AAAAAD/////////////////////////////A+gAAAAA/////////////////////////////wPoAAAAAP////////////////////////////8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAAAAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA1MAAAAGAAAAAAAAAAAAAAb4AAAJYAAAAA8ARwBhAHQAbwAgACgAMgApACAAUgBFAEYATwBOACAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAACWAAAAb4AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAABudWxsAAAAAgAAAAZib3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAAAAAAAAAAQnRvbWxvbmcAAAb4AAAAAFJnaHRsb25nAAAJYAAAAAZzbGljZXNWbExzAAAAAU9iamMAAAABAAAAAAAFc2xpY2UAAAASAAAAB3NsaWNlSURsb25nAAAAAAAAAAdncm91cElEbG9uZwAAAAAAAAAGb3JpZ2luZW51bQAAAAxFU2xpY2VPcmlnaW4AAAANYXV0b0dlbmVyYXRlZAAAAABUeXBlZW51bQAAAApFU2xpY2VUeXBlAAAAAEltZyAAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAAAABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAAG+AAAAABSZ2h0bG9uZwAACWAAAAADdXJsVEVYVAAAAAEAAAAAAABudWxsVEVYVAAAAAEAAAAAAABNc2dlVEVYVAAAAAEAAAAAAAZhbHRUYWdURVhUAAAAAQAAAAAADmNlbGxUZXh0SXNIVE1MYm9vbAEAAAAIY2VsbFRleHRURVhUAAAAAQAAAAAACWhvcnpBbGlnbmVudW0AAAAPRVNsaWNlSG9yekFsaWduAAAAB2RlZmF1bHQAAAAJdmVydEFsaWduZW51bQAAAA9FU2xpY2VWZXJ0QWxpZ24AAAAHZGVmYXVsdAAAAAtiZ0NvbG9yVHlwZWVudW0AAAARRVNsaWNlQkdDb2xvclR5cGUAAAAATm9uZQAAAAl0b3BPdXRzZXRsb25nAAAAAAAAAApsZWZ0T3V0c2V0bG9uZwAAAAAAAAAMYm90dG9tT3V0c2V0bG9uZwAAAAAAAAALcmlnaHRPdXRzZXRsb25nAAAAAAA4QklNBCgAAAAAAAwAAAABP/AAAAAAAAA4QklNBBQAAAAAAAQAAAADOEJJTQQMAAAAAA8vAAAAAQAAAKAAAAB3AAAB4AAA3yAAAA8TABgAAf/Y/+AAEEpGSUYAAQIBAEgASAAA/+0ADEFkb2JlX0NNAAH/7gAOQWRvYmUAZIAAAAAB/9sAhAAMCAgICQgMCQkMEQsKCxEVDwwMDxUYExMVExMYEQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQ0LCw0ODRAODhAUDg4OFBQODg4OFBEMDAwMDBERDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAB3AKADASIAAhEBAxEB/90ABAAK/8QBPwAAAQUBAQEBAQEAAAAAAAAAAwABAgQFBgcICQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUGBwgJCgsQAAEEAQMCBAIFBwYIBQMMMwEAAhEDBCESMQVBUWETInGBMgYUkaGxQiMkFVLBYjM0coLRQwclklPw4fFjczUWorKDJkSTVGRFwqN0NhfSVeJl8rOEw9N14/NGJ5SkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2N0dXZ3eHl6e3x9fn9xEAAgIBAgQEAwQFBgcHBgU1AQACEQMhMRIEQVFhcSITBTKBkRShsUIjwVLR8DMkYuFygpJDUxVjczTxJQYWorKDByY1wtJEk1SjF2RFVTZ0ZeLys4TD03Xj80aUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9ic3R1dnd4eXp7fH/9oADAMBAAIRAxEAPwAQqKf0vJTbYPmpl7QJhQyHZniUDqghGtoKK95efaChFtk+4GE2l1rEDkIVwe7QEgIxta3kKFmQ2NAglDXXH0tUXaI4QHWmdFH7Q7hLVS9oaCk3adIUmUXXNL2Mc9oMEjiSmFZa4ggtI5BEFLVWii1gTtc3hJ1Tih+lZKSk8NSIaggP4IUw1xSUrSU52gKTaUTHwzk3Cpp2jmx8fRaPpPQUjrxX2VPvENYyds6biPpMr/e2N+kq7tfNbuQ2sVjY3ZWBsraZgAfRY399351ipHHqZYR2MED4paJIIOrngO4AUq6HOOoV/wBOsKPt7JKf/9B2Vy7d2SvNZEA6qm2+0NiUweZkqEybHC3Ki2sSVGy1rjroqpf5piGuHOqHErhXtc3sqjzqivY5p8UJzT4Jq5Hu1RqmNseG9yQPvMIWzXhFoDnX1NaQHF7YJ4ncEVOvVTWXemQNjBFfgCRLkW/ED2w4e0DQiTHwcjjEZba62qwUPeSXV2Ay0zx/52rf2K4MHua6P3RP3bdn/VKCHHIyJ76EM8uCIA8KILgGr0ztcNeQfEeKg8sCv5uKda3Szd/NvPDX9tzpd7LPzlh2PtY91bwWvaS1zT2I5apIm/MbsUo0fA7J3ObOgTF0KqbXtEoT77i7yT6WW3xZJgak6ALarxm4lLaCN113vuI7AfQqH/fll9OwLTsttBa+xwFLSO5Mf9JbTbWNte/cAG+wO/kt9rVAZiUzCOw+Y+PZmEOGImdzsEGQx+4FjPcAR6jxo0f1nLGycgG0+mSWtAAJ5gfnf2lpdR6hQ6ARvDuA8mNfo+z+V/LWO8vsPZrZna0Bo/6KliAQaPVjNggkdFC9x5Kl60cKIoICcVFKlW//0a4DEJ/OiRtaNEtzDrKgLYBYbhw5LjUKTnVnspB9O3VJNsfcVAteeApG1k+1Fbc2ISpVtYseRwpU1Wixjh+a4H7irILZRDtbBmACEgFEl0KMt4cWNrFgb9E6xtOrNdzdqN9qrIk0taePaTz/AFWvcqBpbUyjePe4yzngn2f9FOabLbGvfWADp25nVzSVWwylw6tvLCN6Ms3IYdRp8HDUf9UnGDg5bWZGVuY/88sOrh+bu5TNwgHOkGR3eCf9f7CPXU8nYNTEbR/tUU8k4yJHVIjGUQOzZZ0PobmAtqLtJ1c8k/H3JN6Z0nHsFtVLGPE7d4nX+24olguqqD6RLmaxqSY/NKe0PtpGRQd4eNxB8/H+Skc0jp4WtGKI18WNuNYbxkl0uqBIZOgJEbtFmuxW22AkkHu2PyI7cuKDkNn2aO2nSD8fzVaaG2NJaNpI8IPu8kzGalp11XZL4fLRyrumueDtYGB3LvHyZ/Ub+cs2+oUWOZIc5p1IHC3srIuqDmulxGsjv/JC5vItussd6g2mdW+CuwINkNWV6As/VAEnUqJvjhDEd0xA7JyH/9KkGNOig+kDVN72nlM6xx0KgbFq4+Ci5oITzomDUEgoiC0yEWt7H6HRM8CIQw1wKIQWwXBp0PCZ15LdSgEOKG+YRQ7lFluT09thk+gTW13BIEOb9L93cj4F+R7iQCx2m0zr8Ruc3/wJWPqrVPSC57QQ655b3MQ1quu6ewv3sZHceCp5YmM5EfpNvHMSgIy6NYBzxFft14B018PzW/2FaqpbU3e/nzR2Y3pVgCZ7z/r7k2XlY2OwuvtZW0abnOA/Ko+Hck6+K7i2AG/ZBmuLMQ3Hgy0hR22M9PJol2PbUGW1RwAP0bmfylWb1fomTW/DZl1E2DaKy9vJ/OZKv4FeRRiVVWw/ZDQ8fE7SlHGZT/wfxCpTEY11vY9YlTujsbVY5nFtYbGngYVHa/EGNaXEgBtF7D33ENa7+s1y6htbvTAA0hc51bLrw/UvsYXitwbVUNN1pB2j+Sxn849Wp4I8Nj00N/8AumtHOeLX1Wdv+antpofurcJA+iey5/quGyp3qEgHQRzI8ZCw39R6x1KrHzcjIsY/IyWY7cSsBlbQ4lvp116u9v09+5bnU8f0vY6w2Naf0QMSP833O/tJsCBKgNLITIaA3q5jntnROHM5Kj6DlJtBjUqallv/06BG4SomonVEa2ApEQq7ZprbSE43EosAyols6gJWmmO1ygWObqigPB4KcjXVK1U1iSlTW661tbeXkN8Ucsa5av1bwjdni0NHp06lxB5P0QEbWl36BidMwWUsG1o7EGXHxQm5wG6159g0HYSn6xVc8NDJHis+rEsLgbSXnnWIHyaq8+KUiANmWHCIgkt5nUH5dgqYDUzvZAJ+DQqXXPq8Mu2jOwWC7JxSfVx3OANjHDaTXv8A0frs/wAHvWiKpp9pAI5PmqD6ck3NdY97dZkT+Lq/amGMo7jiv9L5V8ZA3R4a6bvJ3UYVFedWca2/JyY9HEdj2NfXZGz9I97A3+XuXTfUhnXMK1vTOp0W/YrW78S24Q8FgG+d3u9Jzv5rf/Nrr+lG70mvssc4cDzCvXU+o32yZ0gd/mrOHDQuz0Ou9R/RYcmaOseG+m/X95rH02uLQRoVynXulHq2TVQy92IW5AuNjPpCGWVw3d7fz/zl0ZDWlvqGOxadNZVDqoqqsGS14/RH9KAZgD85THWwdjuxAVRG7jn6s0dMLepWX3dRzGNLaH3bQyufpOropDGse7+2sR9lz73m0FpHIP5xP5y7PJy2MxS6QWu1aOREfS0XEZN7rHvt3aPPsaOAB/5JQzwxEokaAfojZfDKTEg6nup5EKBceOyGLjOqKCCPPw/vTlP/1KgdCmK3WaAIuNg22w4ghnitP7KamRWA2PHUrPy5xHSOroY8JPzaNGnAIAcRr/roQjNxGt9r2ADnafH+S5WA2uxo9R4JHI1BQrXVVyGuJPYQSqss0jqT+LZjjiNAPwXd6DR9AB37v/kVWs9G3R1UxwO/4fRUnEvbuLTWPzTY/bPwa73/APQU8aoPs5aCDqZ3D/viYMuQyFFd7cADYQNwaXnaxrvnyF03SsSjGobXU3aSJcTySfEqDMOquj1Gw4qzRa1kEMLnkaH+4K5ilOwJytqZRGriKVn0l4AA1j4rOGNbTJJAB7RJWvYHPbr+VU7WvmGjTuSdP4q0Yi7awkaprNLwNLAJ7JgXjiwgnkN7/FO+hsn6IdySBJ/H2/5yC4bR/OOI7CdPkyuP/RiVBBLt9NuskMI2u5AH539Vmi2G3Wt0LDt+ELksXqD6Tuaxu0ch+pM/1SGNVizrNHLtrSBMOaBHbXVSxIDHIG3Q+sOLkZVLXYu1zmmXVO0Lgf3LB9F7VxFlj8y1uAC6u1wIvDXFzWNBLXl30fzf5v8AlrWy/rFLCygl24fmNgf2n/8AkVi1fbG3XZTgwm4g2EyDDR4/+TTJ8MpWPqzYpyjCQI/u3+862dbRXj+iRLGs9NocdIA2tG1vvesDKBa1jC2I5kCEd9xs99gIrZqGfvH+Us5+Y627T2D83/X81KUrY4xpITDdNPPv96gx4SNrToRr9yg4un2ifyprI//V0Kq31tHpgEfGFJzXn3GBHM90M3DxJHlH96dj5J/RuDR+c47p+A+isQgOyCWDnWn2MI10G3/cUF2Ne0h9lu0H81v0nf1UU3bQSGlw8S6B/mt2oLrQXe2XWO0Inn7o9v8AXUVDzZASw9E2PhrWt8XOJcT5fvOV7Cww2wcvcNXaQ0KNFLmEeqRu/PI48q2x/wBSxaOO7bAc7Y06NaILif5DPotUuLFrZWZMtCg6dbBZQGNkgck6A/gpUVBvt0gfd/5kg4zg06/RJ0E7iT5lH3se6CdT+T+qtDHEGj1aOSR1HRm+TwN0dxwqtjPUMmYHyn7loh1e3a0QBwP71WvrHP4KYhgty7KjEj2snQdyf+pahGkxudp5K9aAHBztYmPJVrS4k+Hb+9NTbQfQbDqY8x2/q/yv5SG/FsaQGPkH806gK9tnjWOfBRcIMcQkFpLm2bmyH17nCQI+j9yC5tjw0OaWMb+aNVqWNHPclAc0DvB8+CnAI4nI6ga2UkGSXaCZCxawGiDqZXR9Ra00kRKxxjtn4oS0Xw1CNkO1U9kDX5KXpBswVGS0E8oWvp//1rrbbQD7C7w0P+xBttyDIbWGnuX6ryNJY0rrW3XG76sd7mk2udtGu2tsT8FKmzY39Xr/AEhkANO4gfnOc4bvcvJ0lF37r9a8H16t1h2taIsd9J5BkD87Y0/+dverNJ2uBYCXQZmS6P7PvXjCSnx9PJim+8Y91xbu2OBcNJadGx2aP+oRaHEmWyHGNI90eLl4EkrML4oteVUX6LreeQDHgQZnzU3O01Gp8V84pK2Wq/Q7gzkEHyVVzGHV7hLtSJ4HZeBJJuitX3l5G0NZ37jgKtZu3tjsdV4ekkKQbfaro2kP+j+CE7fA5+a8aSTgh9VzJ1iY7qnDJ815skmz3ZMd8L6M8CNI+SC9gjRwXn6Sav1f/9kAOEJJTQQhAAAAAABTAAAAAQEAAAAPAEEAZABvAGIAZQAgAFAAaABvAHQAbwBzAGgAbwBwAAAAEgBBAGQAbwBiAGUAIABQAGgAbwB0AG8AcwBoAG8AcAAgAEMAUwAAAAEAOEJJTQQGAAAAAAAHAAgAAAABAQD/4RgFaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCc/Pg0KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIHRvb2xraXQgMy4wLTI4LCBmcmFtZXdvcmsgMS42Ij4NCgk8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiIHhtbG5zOmlYPSJodHRwOi8vbnMuYWRvYmUuY29tL2lYLzEuMC8iPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0idXVpZDoyYjNiYjk3MS01Nzg4LTExZTMtOWEwNS04ODU5MDRjZjU2YjAiIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4NCgkJCTxleGlmOkNvbG9yU3BhY2U+NDI5NDk2NzI5NTwvZXhpZjpDb2xvclNwYWNlPg0KCQkJPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjI0MDA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPg0KCQkJPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjE3ODQ8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9InV1aWQ6MmIzYmI5NzEtNTc4OC0xMWUzLTlhMDUtODg1OTA0Y2Y1NmIwIiB4bWxuczpwZGY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGRmLzEuMy8iPg0KCQk8L3JkZjpEZXNjcmlwdGlvbj4NCgkJPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9InV1aWQ6MmIzYmI5NzEtNTc4OC0xMWUzLTlhMDUtODg1OTA0Y2Y1NmIwIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iPg0KCQkJPHBob3Rvc2hvcDpIaXN0b3J5PjwvcGhvdG9zaG9wOkhpc3Rvcnk+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0idXVpZDoyYjNiYjk3MS01Nzg4LTExZTMtOWEwNS04ODU5MDRjZjU2YjAiIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIj4NCgkJCTx0aWZmOlhSZXNvbHV0aW9uPjcyLzE8L3RpZmY6WFJlc29sdXRpb24+DQoJCQk8dGlmZjpZUmVzb2x1dGlvbj43Mi8xPC90aWZmOllSZXNvbHV0aW9uPg0KCQkJPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4NCgkJPC9yZGY6RGVzY3JpcHRpb24+DQoJCTxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSJ1dWlkOjJiM2JiOTcxLTU3ODgtMTFlMy05YTA1LTg4NTkwNGNmNTZiMCIgeG1sbnM6eGFwPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4NCgkJCTx4YXA6Q3JlYXRlRGF0ZT4yMDEzLTExLTI3VDE1OjIwOjEwLTAzOjAwPC94YXA6Q3JlYXRlRGF0ZT4NCgkJCTx4YXA6TW9kaWZ5RGF0ZT4yMDEzLTExLTI3VDE1OjIwOjQ1LTAzOjAwPC94YXA6TW9kaWZ5RGF0ZT4NCgkJCTx4YXA6TWV0YWRhdGFEYXRlPjIwMTMtMTEtMjdUMTU6MjA6NDUtMDM6MDA8L3hhcDpNZXRhZGF0YURhdGU+DQoJCQk8eGFwOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBDUyBXaW5kb3dzPC94YXA6Q3JlYXRvclRvb2w+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0idXVpZDoyYjNiYjk3MS01Nzg4LTExZTMtOWEwNS04ODU5MDRjZjU2YjAiIHhtbG5zOnhhcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIj4NCgkJCTx4YXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpmZTVhNTU0YS01Nzg3LTExZTMtOWEwNS04ODU5MDRjZjU2YjA8L3hhcE1NOkRvY3VtZW50SUQ+DQoJCTwvcmRmOkRlc2NyaXB0aW9uPg0KCQk8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0idXVpZDoyYjNiYjk3MS01Nzg4LTExZTMtOWEwNS04ODU5MDRjZjU2YjAiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+DQoJCQk8ZGM6Zm9ybWF0PmltYWdlL2pwZWc8L2RjOmZvcm1hdD4NCgkJPC9yZGY6RGVzY3JpcHRpb24+DQoJPC9yZGY6UkRGPg0KPC94OnhtcG1ldGE+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSd3Jz8+/+ICQElDQ19QUk9GSUxFAAEBAAACMEFEQkUCEAAAbW50clJHQiBYWVogB88ABgADAAAAAAAAYWNzcEFQUEwAAAAAbm9uZQAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1BREJFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKY3BydAAAAPwAAAAyZGVzYwAAATAAAABrd3RwdAAAAZwAAAAUYmtwdAAAAbAAAAAUclRSQwAAAcQAAAAOZ1RSQwAAAdQAAAAOYlRSQwAAAeQAAAAOclhZWgAAAfQAAAAUZ1hZWgAAAggAAAAUYlhZWgAAAhwAAAAUdGV4dAAAAABDb3B5cmlnaHQgMTk5OSBBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZAAAAGRlc2MAAAAAAAAAEUFkb2JlIFJHQiAoMTk5OCkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABjdXJ2AAAAAAAAAAECMwAAY3VydgAAAAAAAAABAjMAAGN1cnYAAAAAAAAAAQIzAABYWVogAAAAAAAAnBgAAE+lAAAE/FhZWiAAAAAAAAA0jQAAoCwAAA+VWFlaIAAAAAAAACYxAAAQLwAAvpz/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMF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";

#endif

camera_pins.h

C Header File
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  21
#define SIOD_GPIO_NUM  26
#define SIOC_GPIO_NUM  27

#define Y9_GPIO_NUM    35
#define Y8_GPIO_NUM    34
#define Y7_GPIO_NUM    39
#define Y6_GPIO_NUM    36
#define Y5_GPIO_NUM    19
#define Y4_GPIO_NUM    18
#define Y3_GPIO_NUM    5
#define Y2_GPIO_NUM    4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM  23
#define PCLK_GPIO_NUM  22

#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  4
#define SIOD_GPIO_NUM  18
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    36
#define Y8_GPIO_NUM    37
#define Y7_GPIO_NUM    38
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    35
#define Y4_GPIO_NUM    14
#define Y3_GPIO_NUM    13
#define Y2_GPIO_NUM    34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM  27
#define PCLK_GPIO_NUM  25

#define LED_GPIO_NUM 22

#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM  27
#define SIOD_GPIO_NUM  25
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    19
#define Y8_GPIO_NUM    36
#define Y7_GPIO_NUM    18
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    5
#define Y4_GPIO_NUM    34
#define Y3_GPIO_NUM    35
#define Y2_GPIO_NUM    32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM  26
#define PCLK_GPIO_NUM  21

#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM  27
#define SIOD_GPIO_NUM  22
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    19
#define Y8_GPIO_NUM    36
#define Y7_GPIO_NUM    18
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    5
#define Y4_GPIO_NUM    34
#define Y3_GPIO_NUM    35
#define Y2_GPIO_NUM    32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM  26
#define PCLK_GPIO_NUM  21

#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM  27
#define SIOD_GPIO_NUM  22
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    19
#define Y8_GPIO_NUM    36
#define Y7_GPIO_NUM    18
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    5
#define Y4_GPIO_NUM    34
#define Y3_GPIO_NUM    35
#define Y2_GPIO_NUM    32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM  26
#define PCLK_GPIO_NUM  21

#define LED_GPIO_NUM 2

#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM  27
#define SIOD_GPIO_NUM  25
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    19
#define Y8_GPIO_NUM    36
#define Y7_GPIO_NUM    18
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    5
#define Y4_GPIO_NUM    34
#define Y3_GPIO_NUM    35
#define Y2_GPIO_NUM    17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM  26
#define PCLK_GPIO_NUM  21

#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM  27
#define SIOD_GPIO_NUM  25
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    19
#define Y8_GPIO_NUM    36
#define Y7_GPIO_NUM    18
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    5
#define Y4_GPIO_NUM    34
#define Y3_GPIO_NUM    35
#define Y2_GPIO_NUM    32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM  26
#define PCLK_GPIO_NUM  21

#elif defined(CAMERA_MODEL_M5STACK_CAMS3_UNIT)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM 21
#define XCLK_GPIO_NUM  11
#define SIOD_GPIO_NUM  17
#define SIOC_GPIO_NUM  41

#define Y9_GPIO_NUM    13
#define Y8_GPIO_NUM    4
#define Y7_GPIO_NUM    10
#define Y6_GPIO_NUM    5
#define Y5_GPIO_NUM    7
#define Y4_GPIO_NUM    16
#define Y3_GPIO_NUM    15
#define Y2_GPIO_NUM    6
#define VSYNC_GPIO_NUM 42
#define HREF_GPIO_NUM  18
#define PCLK_GPIO_NUM  12

#define LED_GPIO_NUM 14

#elif defined(CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM  32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  0
#define SIOD_GPIO_NUM  26
#define SIOC_GPIO_NUM  27

#define Y9_GPIO_NUM    35
#define Y8_GPIO_NUM    34
#define Y7_GPIO_NUM    39
#define Y6_GPIO_NUM    36
#define Y5_GPIO_NUM    21
#define Y4_GPIO_NUM    19
#define Y3_GPIO_NUM    18
#define Y2_GPIO_NUM    5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM  23
#define PCLK_GPIO_NUM  22

// 4 for flash led or 33 for normal led
#define LED_GPIO_NUM   4

#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM  0
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM  27
#define SIOD_GPIO_NUM  25
#define SIOC_GPIO_NUM  23

#define Y9_GPIO_NUM    19
#define Y8_GPIO_NUM    36
#define Y7_GPIO_NUM    18
#define Y6_GPIO_NUM    39
#define Y5_GPIO_NUM    5
#define Y4_GPIO_NUM    34
#define Y3_GPIO_NUM    35
#define Y2_GPIO_NUM    17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM  26
#define PCLK_GPIO_NUM  21

#elif defined(CAMERA_MODEL_XIAO_ESP32S3)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  10
#define SIOD_GPIO_NUM  40
#define SIOC_GPIO_NUM  39

#define Y9_GPIO_NUM    48
#define Y8_GPIO_NUM    11
#define Y7_GPIO_NUM    12
#define Y6_GPIO_NUM    14
#define Y5_GPIO_NUM    16
#define Y4_GPIO_NUM    18
#define Y3_GPIO_NUM    17
#define Y2_GPIO_NUM    15
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM  47
#define PCLK_GPIO_NUM  13

#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM    32
#define RESET_GPIO_NUM   33
#define XCLK_GPIO_NUM    4
#define SIOD_GPIO_NUM    18
#define SIOC_GPIO_NUM    23

#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 19
#define Y7_GPIO_NUM 21
#define Y6_GPIO_NUM 39
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 13
#else
#define Y5_GPIO_NUM 35
#endif
#define Y4_GPIO_NUM 14
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 35
#else
#define Y3_GPIO_NUM 13
#endif
#define Y2_GPIO_NUM    34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM  27
#define PCLK_GPIO_NUM  25

#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  40
#define SIOD_GPIO_NUM  17
#define SIOC_GPIO_NUM  18

#define Y9_GPIO_NUM    39
#define Y8_GPIO_NUM    41
#define Y7_GPIO_NUM    42
#define Y6_GPIO_NUM    12
#define Y5_GPIO_NUM    3
#define Y4_GPIO_NUM    14
#define Y3_GPIO_NUM    47
#define Y2_GPIO_NUM    13
#define VSYNC_GPIO_NUM 21
#define HREF_GPIO_NUM  38
#define PCLK_GPIO_NUM  11

#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM    1
#define RESET_GPIO_NUM   2
#define XCLK_GPIO_NUM    42
#define SIOD_GPIO_NUM    41
#define SIOC_GPIO_NUM    18

#define Y9_GPIO_NUM 16
#define Y8_GPIO_NUM 39
#define Y7_GPIO_NUM 40
#define Y6_GPIO_NUM 15
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 12
#else
#define Y5_GPIO_NUM 13
#endif
#define Y4_GPIO_NUM 5
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 13
#else
#define Y3_GPIO_NUM 12
#endif
#define Y2_GPIO_NUM    14
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM  4
#define PCLK_GPIO_NUM  3

#elif defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  15
#define SIOD_GPIO_NUM  4
#define SIOC_GPIO_NUM  5

#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16

#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM  7
#define PCLK_GPIO_NUM  13

#elif defined(CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3) || defined(CAMERA_MODEL_DFRobot_Romeo_ESP32S3)
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  45
#define SIOD_GPIO_NUM  1
#define SIOC_GPIO_NUM  2

#define Y9_GPIO_NUM    48
#define Y8_GPIO_NUM    46
#define Y7_GPIO_NUM    8
#define Y6_GPIO_NUM    7
#define Y5_GPIO_NUM    4
#define Y4_GPIO_NUM    41
#define Y3_GPIO_NUM    40
#define Y2_GPIO_NUM    39
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM  42
#define PCLK_GPIO_NUM  5

#else
#error "Camera model not selected"
#endif

CameraConfig.cpp

C/C++
// CameraConfig.cpp
#include "CameraConfig.h"
#include "esp_camera.h"          // Para el tipo `camera_config_t` y funciones de la cmara


camera_config_t getCameraConfig() {
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sccb_sda = SIOD_GPIO_NUM;
    config.pin_sccb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;  // for streaming
    config.grab_mode = CAMERA_GRAB_LATEST;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.jpeg_quality = 5;
    config.fb_count = 2;
    config.frame_size = FRAMESIZE_VGA;

    if (config.pixel_format == PIXFORMAT_JPEG) {
        if (psramFound()) {
            // Additional PSRAM configurations (if needed)
        } else {
            config.frame_size = FRAMESIZE_SVGA;
            config.fb_location = CAMERA_FB_IN_DRAM;
        }
    } else {
        config.frame_size = FRAMESIZE_240X240;
    }

#if defined(CAMERA_MODEL_XIAO_ESP32S3)
    pinMode(13, INPUT_PULLUP);
    pinMode(14, INPUT_PULLUP);
#endif

    return config;
}

CloudSpeechClient.h

C Header File
#ifndef _CLOUDSPEECHCLIENT_H
#define _CLOUDSPEECHCLIENT_H
#include <WiFiClientSecure.h>
#include "AudioMic.h"

extern const char* transcript;

enum Authentication {
  USE_ACCESSTOKEN,
  USE_APIKEY
};

class CloudSpeechClient {
  WiFiClientSecure client;
  void PrintHttpBody2(AudioMic* audio_Mic);
  Authentication authentication;

public:
  CloudSpeechClient(Authentication authentication);
  ~CloudSpeechClient();
  void Transcribe(AudioMic* audio_Mic);
  void client_stop();
  void client_begin();
};

#endif // _CLOUDSPEECHCLIENT_H

I2S.cpp

C/C++
#include "I2S.h"
#define SAMPLE_RATE (16000)
#define PIN_I2S_BCLK 26
#define PIN_I2S_LRC 22
#define PIN_I2S_DIN 34
#define PIN_I2S_DOUT 25

#define I2S_PORT I2S_NUM_0
// This I2S specification : 
//  -   LRC high is channel 2 (right).
//  -   LRC signal transitions once each word.
//  -   DATA is valid on the CLOCK rising edge.
//  -   Data bits are MSB first.
//  -   DATA bits are left-aligned with respect to LRC edge.
//  -   DATA bits are right-shifted by one with respect to LRC edges.


I2S::I2S(MicType micType) {
  

if (micType == SENSE) {
    BITS_PER_SAMPLE = I2S_BITS_PER_SAMPLE_16BIT;
    
  i2s_config_t i2s_config = {
      .mode                 = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM ),
      .sample_rate          = 16000U,
      .bits_per_sample      = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format       = I2S_CHANNEL_FMT_ONLY_RIGHT,     // Also works
      //.channel_format       = I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = I2S_COMM_FORMAT_PCM,            // Also works
      //.communication_format = I2S_COMM_FORMAT_I2S,
      .intr_alloc_flags     = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count        = 4,
      .dma_buf_len          = 1024,
      .use_apll             = false,
      .tx_desc_auto_clear   = false,
      .fixed_mclk           = 0
  };
   
  i2s_pin_config_t i2s_mic_pins = {
      .bck_io_num     = I2S_PIN_NO_CHANGE,
      .ws_io_num      = 42,
      .data_out_num   = I2S_PIN_NO_CHANGE,
      .data_in_num    = 41   
  };
  
  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_PORT, &i2s_mic_pins);
  i2s_set_clk(I2S_PORT, SAMPLE_RATE, BITS_PER_SAMPLE, I2S_CHANNEL_STEREO);

  }
}

int I2S::Read(char* data, int numData) {
    size_t bytes_read = 0;
    esp_err_t result = i2s_read(I2S_PORT, (void *)data, numData, &bytes_read, portMAX_DELAY);
    if (result == ESP_OK) {
        return bytes_read;
    } else {
        Serial.print("Error reading I2S data: ");
        Serial.println(result);
        return 0;
    }


    
}

int I2S::GetBitPerSample() {
  return (int)BITS_PER_SAMPLE;
}

I2S.h

C Header File
#ifndef _I2S_H
#define _I2S_H
#include <Arduino.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
#include "esp_system.h"

enum MicType {
  ADMP441,
  ICS43434,
  M5GO,
  M5STACKFIRE,
  SENSE
};

class I2S {
  i2s_bits_per_sample_t BITS_PER_SAMPLE;
public:
  I2S(MicType micType);
  int Read(char* data, int numData);
  int GetBitPerSample();
};

#endif // _I2S_H

Credits

JuanVi

JuanVi

3 projects • 5 followers

Comments