// Copyright 2025 Elizabeth Cray // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "cw.h" /* TODO: * - Implement sending strings * - Add OLED Support */ boolean debug = true; uint8_t input_dit = 3, input_dah = 6, input_pot = A6; uint8_t output = 7; uint16_t dit = 200, dah = 500; uint8_t debounce = 50; uint16_t p_tol = 30, p_min = 50, p_max = 2000, p_buf = 0, p_cache = 0; String serial_buffer = ""; char buf; void key_string(String); void adjust_length(uint16_t); void set_length(uint16_t, uint16_t); void send(bool); void process_input(String); void log(String); void setup() { Serial.begin(115200); log("Set PinModes\n"); pinMode(input_dit, INPUT_PULLUP); pinMode(input_dah, INPUT_PULLUP); pinMode(input_pot, INPUT); pinMode(output, OUTPUT); digitalWrite(output, LOW); log("Read EEPROM\n"); dit = EEPROM.read(20); dah = EEPROM.read(21); debug = EEPROM.read(22); p_buf = analogRead(input_pot); // adjust_length(p_buf); log("Setup complete\n"); log("Dit length: "); log(String(dit)); log("\n"); log("Dah length: "); log(String(dah)); log("\n"); log("Potentiometer: "); log(String(p_buf)); log("\n"); } void loop() { if (!digitalRead(input_dah)){ send(true); }else if (!digitalRead(input_dit)){ send(false); } p_cache = analogRead(input_pot); if (abs(p_cache - p_buf) > p_tol){ p_buf = p_cache; if (p_cache < p_min){ p_cache = p_min; } else if (p_cache > p_max){ p_cache = p_max; } adjust_length(p_cache); } if (Serial.available() > 0) { buf = Serial.read(); if ((uint16_t) buf == 13){ process_input(serial_buffer); serial_buffer = ""; } else if ((uint8_t) buf > 27 ){ serial_buffer += buf; } } delay(debounce); } void adjust_length(uint16_t adjusted_length){ uint16_t new_dah = map(adjusted_length, 20, 1000, p_min, p_max); set_length(new_dah/2, new_dah); } void process_input(String input){ // Commands: // S send string as CW, unavail chars become " " // I set did length (ms) // A set dah length (ms) // D<0/1> set debug mode log("Processing input: "); log(input); log("\n"); char command = input[0]; input.remove(0,1); log("Command: "); log(String(command)); log(" - "); log(input); log("\n"); uint16_t length = 0; if (islower(command)){ command = toupper(command); } switch(command){ case 'S': key_string(input); break; case 'I': length = input.toInt(); set_length(length, dah); break; case 'A': length = input.toInt(); set_length(dit, length); break; case 'D': debug = boolean(input.toInt()==1); log("Debug mode enabled"); EEPROM.write(22, debug); break; default: Serial.println('?'); break; } } void key_string(String input){ // log("Sending string: "); // log(input); // log("\n"); uint8_t b = 0; for (uint8_t i = 0; i < input.length(); i++){ char c = input[i]; if ((uint8_t)c != 32){ b = convertASCII(c); for(uint8_t y = 0; y < strlen(morseCode[b]); y++){ send(morseCode[b][y] == '.'); delay(dit); } if(debug){ Serial.print(' '); } delay(dit); } else { if (debug){ Serial.println(""); } delay(dah); } } } void send(bool b) { if (debug){ Serial.print(b?"+":"="); } digitalWrite(output, HIGH); delay(b?dit:dah); digitalWrite(output, LOW); } void set_length(uint16_t length_dit, uint16_t length_dah) { log("Setting dit length to "); log(String(length_dit)); log(" and dah length to "); log(String(length_dah)); log("\n"); dit = length_dit; dah = length_dah; EEPROM.write(20, length_dit); EEPROM.write(21, length_dah); return; } void log(String content){ if (debug){ Serial.print(content); } }