├── crowos.jpg ├── bateria.h ├── tempo.h ├── bateria.cpp ├── ir.h ├── tempo.cpp ├── README.md ├── ir.cpp └── Crow.ino /crowos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JonasLacerda/crowos/HEAD/crowos.jpg -------------------------------------------------------------------------------- /bateria.h: -------------------------------------------------------------------------------- 1 | #ifndef BATERIA_H 2 | #define BATERIA_H 3 | 4 | #include 5 | 6 | extern M5Canvas bateria; 7 | 8 | class Bateria { 9 | public: 10 | Bateria(); 11 | int verificador(); 12 | 13 | private: 14 | 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /tempo.h: -------------------------------------------------------------------------------- 1 | #ifndef TEMPO_H 2 | #define TEMPO_H 3 | 4 | #include 5 | 6 | extern M5Canvas sub_title2; 7 | 8 | class Tempo { 9 | public: 10 | void begin(); 11 | void update(); 12 | void setSeconds(int newSeconds); 13 | int getSeconds(); 14 | void setMinutes(int newMinutes); 15 | int getMinutes(); 16 | void setHours(int newHours); 17 | int getHours(); 18 | void getTime(); 19 | 20 | private: 21 | int seconds; 22 | int minutes; 23 | int hours; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /bateria.cpp: -------------------------------------------------------------------------------- 1 | #include "bateria.h" 2 | 3 | int Bateria::verificador() { 4 | float batteryADCValue = analogRead(G10) * 2.0f; 5 | float batteryVoltage = (batteryADCValue / 4095.0) * 3300.0; 6 | int batteryPercentage = map(batteryVoltage, 3200.0f, 4200.0f, 0, 100); 7 | batteryPercentage = constrain(batteryPercentage, 0, 100); 8 | int batteryLevel = batteryPercentage; 9 | //Serial.println(batteryLevel); 10 | return batteryLevel; // Correção: Retorne o valor ao invés de usar "void" 11 | } 12 | 13 | Bateria::Bateria() { 14 | // Implementação do construtor, se necessário 15 | } -------------------------------------------------------------------------------- /ir.h: -------------------------------------------------------------------------------- 1 | #ifndef IR_H 2 | #define IR_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Ir { 9 | public: 10 | void beginir(); 11 | void setFrequencia(int newFrequencia); 12 | void setPulsoMarcacao(int newPulsoMarcacao); 13 | void setIntervaloMarcacao(int newIntervaloMarcacao); 14 | void setPulsoEspaco(int newPulsoEspaco); 15 | void setIntervaloEspaco(int newIntervaloEspaco); 16 | void setPulsoInicio(int newPulsoInicio); 17 | void setIntervaloInicio(int newIntervaloInicio); 18 | std::vector getNomesBotoes(int b); 19 | 20 | private: 21 | static const int numBotoes = 15; 22 | String nomesBotoes[numBotoes]; 23 | StaticJsonDocument<1024> doc; 24 | void nomeBotao(int botao); 25 | 26 | int botao; 27 | int i; 28 | int count; 29 | int frequencia; //30 30 | int pulso_marcacao; // 4050 31 | int intervalo_marcacao; // 3950 32 | int pulso_espaco; //550 33 | int intervalo_espaco; // 2000 34 | int pulso_inicio; //550 35 | int intervalo_inicio; // 1000 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /tempo.cpp: -------------------------------------------------------------------------------- 1 | #include "tempo.h" 2 | 3 | void Tempo::update() { 4 | static unsigned long lastSecond = 0; 5 | unsigned long currentMillis = millis(); 6 | 7 | if (currentMillis - lastSecond >= 1000) { 8 | lastSecond = currentMillis; 9 | 10 | // Atualiza os segundos apenas a cada segundo 11 | seconds++; 12 | if (seconds >= 60) { 13 | seconds = 0; 14 | minutes++; 15 | if (minutes >= 60) { 16 | minutes = 0; 17 | hours++; 18 | if (hours >= 24) { 19 | hours = 0; 20 | } 21 | } 22 | } 23 | } 24 | } 25 | 26 | void Tempo::setSeconds(int newSeconds) { 27 | seconds = newSeconds; 28 | } 29 | 30 | int Tempo::getSeconds() { 31 | return seconds; 32 | } 33 | 34 | void Tempo::setMinutes(int newMinutes) { 35 | minutes = newMinutes; 36 | } 37 | 38 | int Tempo::getMinutes() { 39 | return minutes; 40 | } 41 | 42 | void Tempo::setHours(int newHours) { 43 | hours = newHours; 44 | } 45 | 46 | int Tempo::getHours() { 47 | return hours; 48 | } 49 | 50 | void Tempo::getTime() { 51 | Serial.print("Hora: "); 52 | Serial.print(hours % 24); // Limita a exibição às 24 horas 53 | Serial.print(":"); 54 | Serial.print(minutes % 60); 55 | Serial.print(":"); 56 | Serial.println(seconds % 60); 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crow OS 2 | Sistema para M5 Cardputer. 3 | ![crowos](https://github.com/JonasLacerda/crowos/assets/65193517/ee262874-0888-4b85-a8d9-d1258c3f7bbb) 4 | 5 | Os apps que estou desenvolvendo (tentando fazer funcionar): 6 | - Teclado USB 7 | - [x] Parcialmente feito, está funcional, mas precisa reiniciar o Carputer para voltar à serial. Só usa o teclado para inserir no dispositivo se estiver com o app de teclado na tela. 8 | - [x] Melhorei o atalho do brilho, utilizando opt + b para mudar o brilho. Está opção tambem disponivel nas configurações. 9 | - IR 10 | - [x] Em desenvolvimento. Minha TV é TCL e não encontrei os comandos dela. Isso me implica em montar um Arduino para capturar os inputs do controle IR e depois programar para o Carputer. 11 | - [ ] custoimizar os controles. 12 | - [ ] Criar um documento para configuração de cada controle no cartao sd. 13 | - Tempo 14 | - [x] Parcialmente feito. Criei as funções para definir o tempo correto, e o tempo corre bem favorável. Existe uma diferença de segundos que será corrigida com wifi no futuro. 15 | - [ ] Quero adicionar no app Tempo a técnica Pomodoro. 16 | - [ ] Capturar os tempos estilo de corrida. Acho legal um app assim para saber quanto tempo leva cada etapa de um problema ou de uma produção. 17 | - [ ] Mesmo que eu não tenha paciência para fazer, quero criar um alarme e adicionar uma função de start para que execute um determinado programa em um determinado horário. 18 | - SD 19 | - [ ] Choro e lagrimas... 20 | - [x] Ler o cartao de memoria, ta lendo... 21 | - [ ] fazer ler arquivo para carregar os botoes ir. 22 | 23 | Feito isso, vou programar a parte de Wi-Fi e Bluetooth. Só após isso vou iniciar os estudos para adaptar os módulos. Até o momento, o código compilado está usando 20% da memória do ESP32S3. 24 | 25 | nota: 26 | esptool.py --chip esp32s3 merge_bin --output Crow.bin 0x0000 Crow.ino.bootloader.bin 0x8000 Crow.ino.partitions.bin 0x10000 Crow.ino.bin 27 | 28 | esptool.py --port /dev/ttyACM0 write_flash 0x0 Crow.bin 29 | -------------------------------------------------------------------------------- /ir.cpp: -------------------------------------------------------------------------------- 1 | #include "ir.h" 2 | 3 | #define IR_TX_PIN 44 4 | #define SD_SPI_CS_PIN 12 5 | 6 | void Ir::beginir() { 7 | IrSender.begin(DISABLE_LED_FEEDBACK); // Start with IR_SEND_PIN as send pin 8 | IrSender.setSendPin(IR_TX_PIN); 9 | } 10 | 11 | void Ir::setFrequencia(int newFrequencia) { 12 | frequencia = newFrequencia; 13 | } 14 | 15 | void Ir::setPulsoMarcacao(int newPulsoMarcacao) { 16 | pulso_marcacao = newPulsoMarcacao; 17 | } 18 | 19 | void Ir::setIntervaloMarcacao(int newIntervaloMarcacao) { 20 | intervalo_marcacao = newIntervaloMarcacao; 21 | } 22 | 23 | void Ir::setPulsoEspaco(int newPulsoEspaco) { 24 | pulso_espaco = newPulsoEspaco; 25 | } 26 | 27 | void Ir::setIntervaloEspaco(int newIntervaloEspaco) { 28 | intervalo_espaco = newIntervaloEspaco; 29 | } 30 | 31 | void Ir::setPulsoInicio(int newPulsoInicio) { 32 | pulso_inicio = newPulsoInicio; 33 | } 34 | 35 | void Ir::setIntervaloInicio(int newIntervaloInicio) { 36 | intervalo_inicio = newIntervaloInicio; 37 | } 38 | 39 | /* 40 | "tvtcl": { 41 | "protocol": "custom", 42 | "config": { 43 | "frequencia": 38, 44 | "pulso_marcacao": 4050, 45 | "intervalo_marcacao": 3950, 46 | "pulso_espaco": 550, 47 | "intervalo_espaco": 2000, 48 | "pulso_inicio": 550, 49 | "intervalo_inicio": 1000, 50 | "tt": 24 51 | }, 52 | "comand": { 53 | "P": ["p", "0xAB054F"], 54 | "H": ["h", "0xEF010F"], 55 | "esc": ["`", "0x1B0E4F"], 56 | "menu": ["m", "0xB34CFE01"], 57 | "^": [";", "0x6509AF"], 58 | "": [".", "0xE501AF"], 59 | "<": [",", "0x9506AF"], 60 | ">": ["/", "0x150EAF"], 61 | "ok": ["ok", "0xD002FF"], 62 | "vol+": ["f", "0xB0F4F"], 63 | "vol-": ["c", "0x8B074F"], 64 | "ch+": ["d", "0x4B0B4F"], 65 | "ch-": ["x", "0xCB034F"], 66 | "...": ["i", "0x3A0C5F"], 67 | "ent": ["o", ""] 68 | } 69 | }, 70 | */ 71 | 72 | void Ir::nomeBotao(int botao) { 73 | File jsonFile =SD.open("irComand.json"); 74 | 75 | if (!jsonFile) { 76 | Serial.println("Erro ao abrir o arquivo JSON!"); 77 | return; 78 | } 79 | 80 | DeserializationError error = deserializeJson(doc, jsonFile); 81 | if (error) { 82 | Serial.print("Falha ao ler o JSON: "); 83 | Serial.println(error.f_str()); 84 | return; 85 | } 86 | 87 | // Acessa o objeto "tvtcl" do JSON primeiro objeto 88 | JsonObject botoes = doc[botao]; 89 | 90 | // Verifica se o objeto foi encontrado 91 | if (!botoes.isNull()) { 92 | Serial.println("Botão não encontrado no JSON."); 93 | jsonFile.close(); 94 | return; 95 | } 96 | 97 | // Acessa o objeto "comand" dentro de "tvtcl" 98 | JsonObject comand = botoes["comand"]; 99 | 100 | // Variável de contador para o array de botões 101 | i = 0; 102 | // Limpa o array nomesBotoes 103 | //std::fill(std::begin(nomesBotoes), std::end(nomesBotoes), ""); 104 | for (int j = 0; j < numBotoes; j++) { 105 | nomesBotoes[j] = ""; 106 | } 107 | 108 | // Itera sobre as chaves do objeto "comand" e armazena no array nomesBotoes 109 | 110 | for (JsonPair p : comand) { 111 | if (i < numBotoes) { 112 | nomesBotoes[i] = p.key().c_str(); // Armazena o nome do botão 113 | i++; 114 | } 115 | } 116 | 117 | // Fecha o arquivo JSON 118 | jsonFile.close(); 119 | 120 | // Exibe os nomes dos botões para verificação 121 | for (int j = 0; j < i; j++) { 122 | Serial.println(nomesBotoes[j]); 123 | //retornar o arrey com o nome dos botoes 124 | } 125 | } 126 | 127 | std::vector Ir::getNomesBotoes(int b) { 128 | nomeBotao(b); // Chama a função para preencher o array de botões 129 | 130 | std::vector botoes; // Usando vector para retornar os botões 131 | 132 | // Adiciona os nomes ao vector 133 | for (int i = 0; i < numBotoes; i++) { 134 | if (nomesBotoes[i] != "") { // Verifica se o nome do botão não está vazio 135 | botoes.push_back(nomesBotoes[i]); 136 | } 137 | } 138 | 139 | return botoes; // Retorna o vector com os nomes dos botões 140 | } 141 | -------------------------------------------------------------------------------- /Crow.ino: -------------------------------------------------------------------------------- 1 | /* 2 | bateria sao duas 120mAh + 1400mAh pino da bateria é G10 e tem uma correção de 2.0f 3 | tela é de 240px * 135px ST7789 4 | 5 | */ 6 | #include 7 | #include "M5Cardputer.h" 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include "bateria.h" 15 | #include "tempo.h" 16 | 17 | #include "USB.h" 18 | #include "USBHIDKeyboard.h" 19 | 20 | USBHIDKeyboard Keyboard; 21 | 22 | #define tela M5Cardputer.Display 23 | 24 | #define DISABLE_CODE_FOR_RECEIVER 25 | #define IR_TX_PIN 44 26 | 27 | #define SD_SPI_SCK_PIN 40 28 | #define SD_SPI_MISO_PIN 39 29 | #define SD_SPI_MOSI_PIN 14 30 | #define SD_SPI_CS_PIN 12 31 | 32 | M5Canvas dataConfig(&M5Cardputer.Display); 33 | 34 | //13 35 | LGFX_Button btnIr[15]; 36 | 37 | Bateria bateriaLevel; 38 | Tempo tempo; 39 | 40 | unsigned long tempoInicio; 41 | const unsigned long duracaoDelay = 2000; 42 | const unsigned long updateInterval = 1000; 43 | 44 | int brilho[] = {0, 50, 65, 80, 100}; 45 | int b = 2; 46 | 47 | //escrever numero 48 | int dataC; 49 | 50 | int menuSelecionado = 0; 51 | int menuSelectConfig = 0; 52 | 53 | String tituloNome; 54 | unsigned long tempoUltimaAtualizacao = 0; 55 | 56 | String texto; 57 | 58 | //indexTela = [menuStart(), menuConfig(), appTeclado(), appIR(), sd()] 59 | int indexTela = 0; 60 | 61 | int frequencia = 38; 62 | int pulso_marcacao = 4050; 63 | int intervalo_marcacao = 3950; 64 | int pulso_espaco = 550; 65 | int intervalo_espaco = 2000; 66 | int pulso_inicio = 550; 67 | int intervalo_inicio = 1000; 68 | 69 | std::map irCodes = { 70 | {'p', 0xAB054F}, 71 | {';', 0x6509AF}, 72 | {'h', 0xEF010F}, 73 | {'d', 0x4B0B4F}, 74 | {'f', 0xB0F4F}, 75 | {',', 0x9506AF}, 76 | {'/', 0x150EAF}, 77 | {'x', 0xCB034F}, 78 | {'c', 0x8B074F}, 79 | {'.', 0xE501AF}, 80 | {'`', 0x1B0E4F}, 81 | {'o', 0x3A0C5F} 82 | }; 83 | 84 | 85 | // Função para exibir o título 8 caracter 86 | void titulo(String nome) { 87 | tituloNome = nome.substring(0, 8); 88 | tela.fillRect(0, 0, tela.width(), 26, TFT_DARKGREEN); 89 | tela.setCursor(15, 5); 90 | tela.setTextColor(WHITE); 91 | tela.setTextSize(1.75); 92 | tela.print(tituloNome); 93 | } 94 | 95 | // Função para exibir o nível da bateria 96 | void bateriaM5() { 97 | tela.fillRect(190, 0, 50, 26, TFT_DARKGREEN); 98 | tela.setCursor(190, 5); 99 | tela.setTextColor(WHITE); 100 | tela.setTextSize(1.75); 101 | tela.print((bateriaLevel.verificador() < 100) ? " " : ""); 102 | tela.print(bateriaLevel.verificador()); 103 | tela.print("%"); 104 | } 105 | 106 | // Função para exibir a hora 107 | void hourTile() { 108 | tela.fillRect(100, 0, 90, 26, TFT_DARKGREEN); 109 | tela.setCursor(100, 5); 110 | tela.setTextColor(WHITE); 111 | tela.setTextSize(1.75); 112 | 113 | // Obtendo as horas, minutos e segundos usando a instância da classe Tempo 114 | uint8_t hours = tempo.getHours(); 115 | uint8_t minutes = tempo.getMinutes(); 116 | uint8_t seconds = tempo.getSeconds(); 117 | 118 | // Imprimindo as horas, minutos e segundos formatados 119 | tela.print((hours < 10) ? "0" : ""); 120 | tela.print(hours); 121 | tela.print(":"); 122 | tela.print((minutes < 10) ? "0" : ""); 123 | tela.print(minutes); 124 | tela.print(":"); 125 | tela.print((seconds < 10) ? "0" : ""); 126 | tela.print(seconds); 127 | } 128 | 129 | void brilhoTela(){ 130 | tela.setBrightness(brilho[b]); 131 | b++; 132 | if(b > 4){ 133 | b = 0; 134 | } 135 | } 136 | 137 | void menuStart() { 138 | titulo("Home"); 139 | bateriaM5(); 140 | hourTile(); 141 | tela.fillRect(0, 30, tela.width(), 110, TFT_DARKCYAN); 142 | 143 | for (int i = 0; i < 5; i++) { 144 | int yPosition = 30 + i * 20; 145 | 146 | if (i == menuSelecionado) { 147 | tela.fillRect(15, yPosition, 120, 23, TFT_DARKCYAN); 148 | tela.setTextColor(GOLD, TFT_DARKCYAN); 149 | } else { 150 | tela.setTextColor(TFT_WHITE); 151 | } 152 | 153 | tela.setCursor(20, yPosition); 154 | 155 | switch (i) { 156 | case 0: 157 | tela.println("Controle IR"); 158 | break; 159 | case 1: 160 | tela.println("Tempo"); 161 | break; 162 | case 2: 163 | tela.println("Teclado"); 164 | break; 165 | case 3: 166 | tela.println("Configuracao"); 167 | break; 168 | case 4: 169 | tela.println("SD Info"); 170 | break; 171 | } 172 | } 173 | } 174 | 175 | void menuConfig(){ 176 | tela.fillRect(0, 30, tela.width(), 110, TFT_DARKCYAN); 177 | titulo("Config"); 178 | bateriaM5(); 179 | hourTile(); 180 | 181 | for (int i = 0; i < 4; i++) { 182 | int yPosition = 30 + i * 20; 183 | 184 | if (i == menuSelectConfig) { 185 | tela.fillRect(15, yPosition, 120, 23, TFT_DARKCYAN); 186 | tela.setTextColor(GOLD, TFT_DARKCYAN); 187 | } else { 188 | tela.setTextColor(TFT_WHITE); 189 | } 190 | 191 | tela.setCursor(20, yPosition); 192 | 193 | switch (i) { 194 | case 0: 195 | tela.print("Hora: "); 196 | tela.print((tempo.getHours() < 10) ? "0" : ""); 197 | tela.print(tempo.getHours()); 198 | tela.print(":"); 199 | tela.print((tempo.getMinutes() < 10) ? "0" : ""); 200 | tela.print(tempo.getMinutes()); 201 | break; 202 | case 1: 203 | tela.print("Data: "); 204 | tela.print("01"); 205 | tela.print("/"); 206 | tela.print("02"); 207 | tela.print("/"); 208 | tela.println("24"); 209 | break; 210 | case 2: 211 | tela.print("Brilho(0-3): "); 212 | tela.println(b+1); 213 | break; 214 | case 3: 215 | tela.println("Tema: padrao"); 216 | break; 217 | } 218 | } 219 | } 220 | 221 | void appTeclado(){ 222 | if(indexTela !=2){ 223 | indexTela = 2; 224 | }else { 225 | Keyboard.begin(); 226 | USB.begin(); 227 | } 228 | tela.fillRect(0, 30, tela.width(), 110, TFT_DARKCYAN); 229 | titulo("Teclado"); 230 | bateriaM5(); 231 | hourTile(); 232 | tela.setCursor(15, 50); 233 | tela.setTextScroll(true); 234 | tela.println(texto); 235 | } 236 | 237 | void appIR() { 238 | IrSender.begin(DISABLE_LED_FEEDBACK); // Start with IR_SEND_PIN as send pin 239 | IrSender.setSendPin(IR_TX_PIN); 240 | 241 | tela.fillRect(0, 30, tela.width(), 110, TFT_DARKCYAN); 242 | titulo("IR"); 243 | bateriaM5(); 244 | hourTile(); 245 | tela.setCursor(15, 50); 246 | tela.setTextScroll(true); 247 | tela.drawString("TCL", 15, 35); 248 | tela.setTextColor(TFT_SILVER, TFT_BLACK); 249 | int numLinhas = 3; 250 | int numColunas = 5; 251 | int larguraBotao = 30; 252 | int alturaBotao = 25; 253 | int espacamentoHorizontal = 5; 254 | int espacamentoVertical = 5; 255 | 256 | // Nomes dos botões 257 | String nomesBotoes[15] = { 258 | "P", "^", "H", "ch+", "vol+", 259 | "<", "ok", ">", "ch-", "vol-", 260 | "conf", "", "esc", "...", "ent" 261 | }; 262 | 263 | // Inicialize e desenhe os botões 264 | for (int i = 0; i < 15; ++i) { 265 | int linha = i / numColunas; 266 | int coluna = i % numColunas; 267 | int x = espacamentoHorizontal + coluna * (larguraBotao + espacamentoHorizontal) + 75; 268 | int y = 50 + linha * (alturaBotao + espacamentoVertical); 269 | 270 | btnIr[i].initButton(&M5.Lcd, x, y, larguraBotao, alturaBotao, TFT_DARKGREEN, TFT_YELLOW, TFT_DARKGREEN, nomesBotoes[i].c_str()); 271 | btnIr[i].drawButton(); 272 | } 273 | } 274 | 275 | void sd(){ 276 | tela.fillRect(0, 30, tela.width(), 110, TFT_DARKCYAN); 277 | titulo("SD"); 278 | bateriaM5(); 279 | hourTile(); 280 | 281 | // SD Card Initialization 282 | SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN); 283 | if (!SD.begin(SD_SPI_CS_PIN, SPI, 25000000)) { 284 | // Print a message if the SD card initialization 285 | // fails orif the SD card does not exist. 286 | Serial.println("Card failed, or not present"); 287 | tela.drawString("Nao esta presente ou cartao falhou", 15, 35); 288 | while (1) 289 | ; 290 | } 291 | 292 | uint8_t cardType = SD.cardType(); 293 | 294 | if (cardType == CARD_NONE) { 295 | Serial.println("No SD card attached"); 296 | tela.drawString("sem sd card", 15, 35); 297 | return; 298 | } 299 | 300 | Serial.print("SD Card Type: "); 301 | if (cardType == CARD_MMC) { 302 | Serial.println("MMC"); 303 | tela.drawString("MMC", 15, 35); 304 | } else if (cardType == CARD_SD) { 305 | Serial.println("SDSC"); 306 | tela.drawString("SDSC", 15, 35); 307 | } else if (cardType == CARD_SDHC) { 308 | Serial.println("SDHC"); 309 | tela.drawString("SDHC", 15, 35); 310 | } else { 311 | Serial.println("UNKNOWN"); 312 | tela.drawString("UNKNOWN", 15, 35); 313 | } 314 | 315 | uint64_t cardSize = SD.cardSize() / (1024 * 1024); 316 | tela.drawString("SD Card:", 15, 60); 317 | tela.drawString(String(cardSize) + " MB", 100, 60); 318 | tela.drawString(String(cardSize) + " MB", 100, 60); 319 | tela.drawString("Total: " + String(SD.totalBytes() / (1024 * 1024)) + "MB", 15, 75); 320 | tela.drawString("Usado: " + String(SD.usedBytes() / (1024 * 1024)) + "MB", 15, 90); 321 | tela.drawString("Para formatar digite f", 15, 120); 322 | } 323 | 324 | 325 | void lsb_first(unsigned long cod, int tt){ 326 | IrSender.sendPulseDistanceWidth(frequencia, pulso_marcacao, intervalo_marcacao, pulso_espaco, intervalo_espaco, pulso_inicio, intervalo_inicio, cod, tt, PROTOCOL_IS_LSB_FIRST, 0, 0); 327 | } 328 | 329 | void sendIRSignal(char letter) { 330 | // Verifica se a letra está presente no mapa 331 | if (irCodes.find(letter) != irCodes.end()) { 332 | // Se estiver, chama a função lsb_first com o código correspondente 333 | lsb_first(irCodes[letter], 24); 334 | } else { 335 | // Caso contrário, não faz nada ou executa alguma ação padrão 336 | } 337 | } 338 | 339 | void setup() { 340 | auto cfg = M5.config(); 341 | M5Cardputer.begin(cfg, true); 342 | 343 | Serial.begin(115200); 344 | 345 | tela.setBrightness(50); 346 | tela.setRotation(1); 347 | 348 | // Cobre a tela toda 349 | tela.fillScreen(TFT_DARKCYAN); 350 | menuStart(); 351 | } 352 | 353 | void loop() { 354 | M5Cardputer.update(); 355 | tempo.update(); 356 | unsigned long tempoAtual = millis(); 357 | 358 | // Verificando se passou pelo menos 1 segundo desde a última atualização do display 359 | if (tempoAtual - tempoUltimaAtualizacao >= updateInterval) { 360 | // Atualizando o display 361 | bateriaM5(); 362 | hourTile(); 363 | 364 | // Atualizando o tempo da última atualização 365 | tempoUltimaAtualizacao = tempoAtual; 366 | } 367 | 368 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ENTER)){ 369 | switch (menuSelecionado) { 370 | case 0 : 371 | if(indexTela != 3){ 372 | indexTela = 3; 373 | appIR(); 374 | delay(60); 375 | }else{ 376 | IrSender.sendPulseDistanceWidth(38, 4050, 4000, 550, 2000, 550, 1000, 0xD002FF, 24, PROTOCOL_IS_LSB_FIRST, 0, 0); 377 | btnIr[6].press(true); 378 | btnIr[6].drawButton(true); 379 | } 380 | break; 381 | case 2 : 382 | if(indexTela != 2){ 383 | appTeclado(); 384 | } 385 | break; 386 | case 3 : 387 | if(indexTela != 1){ 388 | menuConfig(); 389 | indexTela = 1; 390 | } 391 | break; 392 | case 4 : 393 | if(indexTela != 4){ 394 | sd(); 395 | indexTela = 4; 396 | } 397 | break; 398 | 399 | } 400 | } 401 | 402 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_BACKSPACE)){ 403 | switch (menuSelecionado) { 404 | case 3 : 405 | if(indexTela != 0){ 406 | indexTela = 0; 407 | menuStart(); 408 | } 409 | break; 410 | } 411 | } 412 | 413 | if(M5Cardputer.BtnA.wasPressed()){ 414 | if(indexTela != 0){ 415 | indexTela = 0; 416 | menuStart(); 417 | } 418 | } 419 | 420 | if (M5Cardputer.Keyboard.isChange()){ 421 | if (M5Cardputer.Keyboard.isPressed()) { 422 | Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState(); 423 | 424 | if (indexTela == 2){ 425 | //envio do que digitar por usb 426 | KeyReport report = {0}; 427 | report.modifiers = status.modifiers; 428 | uint8_t index = 0; 429 | for (auto i : status.hid_keys) { 430 | report.keys[index] = i; 431 | index++; 432 | if (index > 5) { 433 | index = 5; 434 | } 435 | } 436 | 437 | Keyboard.sendReport(&report); 438 | Keyboard.releaseAll(); 439 | 440 | for (auto i : status.word) { 441 | texto += i; 442 | Serial.println(texto); 443 | if(indexTela == 2){ 444 | appTeclado(); 445 | } 446 | } 447 | 448 | if (status.del) { 449 | texto.remove(texto.length() - 1); 450 | Serial.println(texto); 451 | if(indexTela == 2){ 452 | appTeclado(); 453 | } 454 | } 455 | 456 | if (status.enter) { 457 | texto.remove(0, 2); 458 | texto = ""; 459 | appTeclado(); 460 | } 461 | 462 | //fim do codigo pra enviar por usb 463 | } 464 | 465 | if (M5Cardputer.Keyboard.isKeyPressed(KEY_OPT)){ 466 | if (M5Cardputer.Keyboard.isKeyPressed('b')) { 467 | M5Cardputer.Speaker.tone(4000,50); 468 | brilhoTela(); 469 | } 470 | } 471 | 472 | if (M5Cardputer.Keyboard.isKeyPressed('.')) { 473 | //M5Cardputer.Speaker.tone(4000,50); 474 | switch (indexTela) { 475 | case 0: 476 | menuSelecionado++; 477 | if (menuSelecionado >= 5) { 478 | menuSelecionado = 0; 479 | } 480 | menuStart(); 481 | break; 482 | case 1: 483 | menuSelectConfig++; 484 | if (menuSelectConfig >= 4) { 485 | menuSelectConfig = 0; 486 | } 487 | menuConfig(); 488 | break; 489 | } 490 | 491 | } 492 | 493 | if (M5Cardputer.Keyboard.isKeyPressed(';')) { 494 | //M5Cardputer.Speaker.tone(4000,50); 495 | switch (indexTela) { 496 | case 0: 497 | menuSelecionado--; 498 | if (menuSelecionado < 0) { 499 | menuSelecionado = 4; 500 | } 501 | menuStart(); 502 | break; 503 | case 1: 504 | menuSelectConfig--; 505 | if (menuSelectConfig < 0) { 506 | menuSelectConfig = 3; 507 | } 508 | menuConfig(); 509 | break; 510 | } 511 | } 512 | 513 | if (M5Cardputer.Keyboard.isKeyPressed('/')) { 514 | //M5Cardputer.Speaker.tone(4000,50); 515 | switch (menuSelectConfig) { 516 | case 1 : 517 | tela.fillRect(95, 50, 103, 16, TFT_DARKCYAN); 518 | break; 519 | 520 | case 2 : 521 | b++; 522 | if(b > 4){ 523 | b = 0; 524 | } 525 | menuConfig(); 526 | tela.setBrightness(brilho[b]); 527 | break; 528 | } 529 | } 530 | 531 | if (M5Cardputer.Keyboard.isKeyPressed(',')) { 532 | //M5Cardputer.Speaker.tone(4000,50); 533 | switch (menuSelectConfig) { 534 | case 1 : 535 | tela.fillRect(95, 50, 103, 16, TFT_DARKCYAN); 536 | break; 537 | 538 | case 2 : 539 | b--; 540 | if(b < 0){ 541 | b = 4; 542 | } 543 | menuConfig(); 544 | tela.setBrightness(brilho[b]); 545 | break; 546 | } 547 | } 548 | 549 | if (M5Cardputer.Keyboard.isKeyPressed('f')) { 550 | if(indexTela == 4){ 551 | tela.fillRect(0, 30, tela.width(), 110, TFT_DARKCYAN); 552 | titulo("SD"); 553 | bateriaM5(); 554 | hourTile(); 555 | // Formate o cartão SD 556 | tela.drawString("nao desenvolvi ainda", 15, 35); 557 | 558 | } 559 | } 560 | } 561 | 562 | if(indexTela == 3){ 563 | if (M5Cardputer.Keyboard.isPressed()) { 564 | Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState(); 565 | switch (menuSelecionado){ 566 | case 0 : 567 | for (auto key : status.word) { 568 | if (indexTela == 3) { 569 | Serial.println(key); 570 | // Mapeamento de letras para índices de botões 571 | String letters[] = {"p", ";", "h", "d", "f", 572 | ",", "", "/", "x", "c", 573 | "1", ".", "`", "i", "o"}; 574 | for (int j = 0; j < 15; ++j) { 575 | // Convertendo char para String antes de comparar 576 | if (String(key) == letters[j]) { 577 | btnIr[j].press(true); 578 | btnIr[j].drawButton(true); 579 | sendIRSignal(key); 580 | } 581 | } 582 | } 583 | } 584 | break; 585 | } 586 | }else { 587 | switch (menuSelecionado){ 588 | case 0 : 589 | // Desativa todos os botões 590 | for (int j = 0; j < 15; ++j) { 591 | btnIr[j].press(false); 592 | btnIr[j].drawButton(false); 593 | } 594 | break; 595 | } 596 | } 597 | 598 | } 599 | 600 | 601 | 602 | delay(30); 603 | } 604 | } --------------------------------------------------------------------------------