From 4ba0048bcb5ee092963c64fc160f63ee863bf20b Mon Sep 17 00:00:00 2001 From: Alan Johnston Date: Sat, 26 Aug 2023 16:15:40 -0400 Subject: [PATCH] Create payload_pico.ino payload OK only Copied from https://raw.githubusercontent.com/alanbjohnston/CubeSatSim/pico-payload-fm-rx/cubesatsim/cubesatsim.ino --- stempayload/payload_pico/payload_pico.ino | 1993 +++++++++++++++++++++ 1 file changed, 1993 insertions(+) create mode 100644 stempayload/payload_pico/payload_pico.ino diff --git a/stempayload/payload_pico/payload_pico.ino b/stempayload/payload_pico/payload_pico.ino new file mode 100644 index 00000000..b386fc7a --- /dev/null +++ b/stempayload/payload_pico/payload_pico.ino @@ -0,0 +1,1993 @@ +/* + * Transmits CubeSat Telemetry at 432.25MHz in AFSK, FSK, BPSK, or CW format + * + * Copyright Alan B. Johnston + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * along with this program. If not, see . + */ + +// This code is an Arduino sketch for the Raspberry Pi Pico +// based on the Raspberry Pi Code + +//#define PICO_0V1 // define for Pico v0.1 hardware + +#include "cubesatsim.h" +#include "DumbTXSWS.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "pico/stdlib.h" // stdlib +#include "hardware/irq.h" // interrupts +#include "hardware/pwm.h" // pwm +#include "hardware/sync.h" // wait for interrupt +#include "RPi_Pico_ISR_Timer.h" +#include "RPi_Pico_TimerInterrupt.h" +#include +#include "hardware/gpio.h" +#include "hardware/adc.h" +//#include "SSTV-Arduino-Scottie1-Library.h" +#include "LittleFS.h" +#include +#include "picosstvpp.h" +#include "pico/bootrom.h" +#include "hardware/watchdog.h" +#include +#include + +// jpg files to be stored in flash storage on Pico (FS 512kB setting) +#include "sstv1.h" +#include "sstv2.h" + +Adafruit_INA219 ina219_1_0x40; +Adafruit_INA219 ina219_1_0x41(0x41); +Adafruit_INA219 ina219_1_0x44(0x44); +//Adafruit_INA219 ina219_1_0x45(0x45); +Adafruit_INA219 ina219_2_0x40(0x40); +Adafruit_INA219 ina219_2_0x41(0x41); +Adafruit_INA219 ina219_2_0x44(0x44); +Adafruit_INA219 ina219_2_0x45(0x45); + +Adafruit_SI5351 clockgen = Adafruit_SI5351(); +TinyGPSPlus gps; + +unsigned long micros3; +bool show_gps = false; +volatile int skip = 0; + +//WiFiServer server(port); +//WiFiClient client; +WiFiClient net; +MQTTClient client; + +#define PICO_W // define if Pico W board. Otherwise, compilation fail for Pico or runtime fail if compile as Pico W + +//#define APRS_VHF + +byte green_led_counter = 0; +char call[] = "AMSAT"; // put your callsign here + +extern bool get_camera_image(bool debug); +extern bool start_camera(); + +float rand_float(float lower, float upper) { + + return (float)(random(lower*100, upper*100)/100.0); +} + +void setup() { + + set_sys_clock_khz(133000, true); + + Serial.begin(115200); + + delay(10000); + +// LittleFS.begin(); +// LittleFS.format(); // only format if files of size 0 keep showing up +//#ifdef APRS_VHF +// mode = AFSK; // force to APRS +//#else +// read_mode(); +//#endif + +// new_mode = mode; + +// pinMode(LED_BUILTIN, OUTPUT); +// blinkTimes(1); + +/// sleep(5.0); + +// otherwise, run CubeSatSim Pico code + + Serial.println("CubeSatSim Pico v0.40 starting...\n"); + +/**/ + if (check_for_wifi()) { + wifi = true; + led_builtin_pin = LED_BUILTIN; // use default GPIO for Pico W + pinMode(LED_BUILTIN, OUTPUT); +// configure_wifi(); + } else { + led_builtin_pin = 25; // manually set GPIO 25 for Pico board +// pinMode(25, OUTPUT); + pinMode(led_builtin_pin, OUTPUT); + } +/**/ + + config_gpio(); + + Serial.print("Pi Zero present, so running Payload OK code instead of CubeSatSim code."); + sr_frs_present = true; + program_radio(); + start_payload(); + + pinMode(15, INPUT_PULLUP); + pinMode(22, OUTPUT); + digitalWrite(22, 1); + pinMode(17, OUTPUT); + digitalWrite(17, 1); + + +} + +void loop() { + + payload_OK_only(); + sleep(1.0); + Serial.println(" "); + Serial.println(digitalRead(15)); + Serial.println(" "); +} + +void config_gpio() { + + // set all Pico GPIO connected pins to input + for (int i = 6; i < 22; i++) { + pinMode(i, INPUT); + } + pinMode(26, INPUT); + pinMode(27, INPUT); + pinMode(28, INPUT); +} + +void program_radio() { + if (sr_frs_present) { + Serial.println("Programming SR_FRS!"); + + pinMode(PD_PIN, OUTPUT); + pinMode(PTT_PIN, OUTPUT); + digitalWrite(PD_PIN, HIGH); // enable SR_FRS + digitalWrite(PTT_PIN, HIGH); // stop transmit + + DumbTXSWS mySerial(SWTX_PIN); // TX pin + mySerial.begin(9600); + + for (int i = 0; i < 5; i++) { + sleep(0.5); // delay(500); +// Serial1.println("AT+DMOSETGROUP=0,434.9100,434.9100,1,2,1,1\r"); +// mySerial.println("AT+DMOSETGROUP=0,434.9000,434.9000,1,2,1,1\r"); +// mySerial.println("AT+DMOSETGROUP=0,434.9000,434.9000,0,8,0,0\r"); +// mySerial.println("AT+DMOSETGROUP=0,432.2510,432.2510,0,8,0,0\r"); +// mySerial.println("AT+DMOSETGROUP=0,432.2500,432.2500,0,8,0,0\r"); +#ifdef APRS_VHF + mySerial.println("AT+DMOSETGROUP=0,144.3900,144.3900,0,8,0,0\r"); // can change to 144.39 for standard APRS +#else + mySerial.println("AT+DMOSETGROUP=0,435.0000,434.9000,0,3,0,0\r"); // squelch set to 3 +#endif + sleep(0.5); + mySerial.println("AT+DMOSETMIC=8,0\r"); // was 8 + + } + } + Serial.println("Programming FM tx 434.9, rx on 435.0 MHz"); + +// digitalWrite(PTT_PIN, LOW); // transmit carrier for 0.5 sec +// sleep(0.5); +// digitalWrite(PTT_PIN, HIGH); + digitalWrite(PD_PIN, LOW); // disable SR_FRS + pinMode(PD_PIN, INPUT); + pinMode(PTT_PIN, INPUT); +} + + +void read_reset_count() { + + long stored_reset, reset_flag; + EEPROM.get(16, reset_flag); + + if (reset_flag == 0xA07) // not first time, read stored reset count + { + + EEPROM.get(20, stored_reset); + reset_count = (int) stored_reset; + Serial.print("Reading reset count from EEPROM as "); + Serial.println(reset_count); + stored_reset += 1; // increment for next boot + EEPROM.put(20, stored_reset); + if (EEPROM.commit()) { + Serial.println("EEPROM successfully committed"); + } else { + Serial.println("ERROR! EEPROM commit failed"); + } + } else { // first time, store flag and reset count as 0 + + Serial.println("Storing initial reset count in EEPROM"); + Serial.println("Reset count is 0"); + reset_flag = 0xA07; + EEPROM.put(16, reset_flag); + stored_reset = 0; + EEPROM.put(20, stored_reset + 1); + if (EEPROM.commit()) { + Serial.println("EEPROM successfully committed"); + } else { + Serial.println("ERROR! EEPROM commit failed"); + } + } +} + +void read_config_file() { + char buff[255]; + // Open configuration file with callsign and reset count + Serial.println("Reading config file"); + File config_file = LittleFS.open("/sim.cfg", "r"); +// FILE * config_file = fopen("/sim.cfg", "r"); + if (!config_file) { + Serial.println("Creating config file."); +// config_file = fopen("/sim.cfg", "w+"); + config_file = LittleFS.open("/sim.cfg", "w+"); + +// fprintf(config_file, "%s %d", " ", 100); +// sprintf(buff, "%d\n", cnt); + sprintf(buff, "%s %d", "AMSAT", 0); + config_file.write(buff, strlen(buff)); + + + config_file.close(); + + config_file = LittleFS.open("/sim.cfg", "r"); + } + +// char * cfg_buf[100]; + config_file.read((uint8_t *)buff, 255); +// sscanf(buff, "%d", &cnt); + sscanf(buff, "%s %d %f %f %s", callsign, & reset_count, & lat_file, & long_file, sim_yes); + config_file.close(); + if (debug_mode) + Serial.printf("Config file /sim.cfg contains %s %d %f %f %s\n", callsign, reset_count, lat_file, long_file, sim_yes); + + reset_count = (reset_count + 1) % 0xffff; + + if ((fabs(lat_file) > 0) && (fabs(lat_file) < 90.0) && (fabs(long_file) > 0) && (fabs(long_file) < 180.0)) { + Serial.println("Valid latitude and longitude in config file\n"); +// convert to APRS DDMM.MM format + latitude = lat_file; // toAprsFormat(lat_file); + longitude = long_file; // toAprsFormat(long_file); + Serial.printf("Lat/Lon updated to: %f/%f\n", latitude, longitude); + } +// } else { // set default +// latitude = toAprsFormat(latitude); +// longitude = toAprsFormat(longitude); +// } +// Serial.printf("sim_yes: %s\n", sim_yes); + char yes_string[] = "yes"; +// if (strcmp(sim_yes, yes_string) == 0) { + if (sim_yes[0] == 'y') { + sim_mode = true; + Serial.println("Simulated telemetry mode set by config file"); + } + + config_file.close(); + + write_config_file(); +} + +void write_config_file() { + Serial.println("Writing /sim.cfg file"); + char buff[255]; + File config_file = LittleFS.open("/sim.cfg", "w+"); + +// sprintf(buff, "%s %d", callsign, ); + + if (sim_mode) + strcpy(sim_yes, "yes"); + else + strcpy(sim_yes, "no"); + + sprintf(buff, "%s %d %f %f %s", callsign, reset_count, latitude, longitude, sim_yes); + Serial.println("Writing string "); +// if (debug_mode) + print_string(buff); + config_file.write(buff, strlen(buff)); + + config_file.close(); +// Serial.println("Write complete"); + +} + +void read_sensors() +{ + +} + +// Returns lower digit of a number which must be less than 99 +// +int lower_digit(int number) { + + int digit = 0; + if (number < 100) + digit = number - ((int)(number / 10) * 10); + else + Serial.println("ERROR: Not a digit in lower_digit!\n"); + return digit; +} + +// Returns upper digit of a number which must be less than 99 +// +int upper_digit(int number) { + + int digit = 0; + if (number < 100) + + digit = (int)(number / 10); + else + Serial.println("ERROR: Not a digit in upper_digit!\n"); + return digit; +} + +void print_string(char *string) +{ + int count = 0; + while ((count < 250) && (string[count] != 0)) + { + Serial.print(string[count++]); + } + Serial.println(" "); +} + +void start_payload() { + +#ifdef APRS_VHF +// Serial2.setRX(9); +// Serial2.setRX(9); +// Serial2.setRX(1); + delay(100); +// Serial2.setTX(8); +// Serial2.setTX(8); +// Serial2.setRX(0); + +/* + delay(100); + Serial1.setRX(1); + delay(100); + Serial1.setTX(0); + delay(10); +*/ + Serial1.begin(115200); // serial to Pi + + Serial.println("Starting Serial1 for payload"); + + Serial2.begin(115200); // serial from GPS + + Serial.println("Starting Serial2 for GPS"); +#else + Serial1.setRX(1); + delay(100); + Serial1.setTX(0); + delay(100); + Serial1.begin(115200); // Pi UART faster speed +#endif + + Serial.println("Starting payload!"); + + blink_setup(); +/* + blink(500); + sleep(0.25); // delay(250); + blink(500); + sleep(0.25); // delay(250); + led_set(greenLED, HIGH); + sleep(0.25); // delay(250); + led_set(greenLED, LOW); + led_set(blueLED, HIGH); + sleep(0.25); // delay(250); + led_set(blueLED, LOW); +*/ + + if (bme.begin()) { + bmePresent = 1; + } else { + Serial.println("Could not find a valid BME280 sensor, check wiring!"); + bmePresent = 0; + } + + Wire.begin(); + Wire.beginTransmission(0x68); + if (Wire.endTransmission() != 0) { + Serial.println("Could not find a valid MPU6050 sensor, check wiring!"); + mpuPresent = 0; + } + else { + mpuPresent = 1; + mpu6050.begin(); + + long flag; + float xOffset; + float yOffset; + float zOffset; + EEPROM.get(0, flag); + + if ((flag == 0xA07) && (payload_command != PAYLOAD_RESET)) + { + Serial.println("Reading gyro offsets from EEPROM\n"); + + EEPROM.get(4, xOffset); + EEPROM.get(8, yOffset); + EEPROM.get(12, zOffset); + + Serial.println(xOffset, DEC); + Serial.println(yOffset, DEC); + Serial.println(zOffset, DEC); + + mpu6050.setGyroOffsets(xOffset, yOffset, zOffset); + + } + else + { + payload_command = false; + + Serial.println("Calculating gyro offsets and storing in EEPROM\n"); + + mpu6050.calcGyroOffsets(true); +/* + eeprom_word_write(0, 0xA07); + eeprom_word_write(1, (int)(mpu6050.getGyroXoffset() * 100.0) + 0.5); + eeprom_word_write(2, (int)(mpu6050.getGyroYoffset() * 100.0) + 0.5); + eeprom_word_write(3, (int)(mpu6050.getGyroZoffset() * 100.0) + 0.5); +*/ + flag = 0xA07; + xOffset = mpu6050.getGyroXoffset(); + yOffset = mpu6050.getGyroYoffset(); + zOffset = mpu6050.getGyroZoffset(); + + EEPROM.put(0, flag); + EEPROM.put(4, xOffset); + EEPROM.put(8, yOffset); + EEPROM.put(12, zOffset); + + if (EEPROM.commit()) { + Serial.println("EEPROM successfully committed"); + } else { + Serial.println("ERROR! EEPROM commit failed"); + } + + Serial.println(" "); + float f; + EEPROM.get(0, flag); + Serial.println(flag, HEX); + EEPROM.get(4, f); + Serial.println(f); + EEPROM.get(8, f); + Serial.println(f); + EEPROM.get(12, f); + Serial.println(f); + } + } + + if (!(payload = bmePresent || mpuPresent)) + Serial.println("No payload sensors detected"); + + pinMode(greenLED, OUTPUT); + pinMode(blueLED, OUTPUT); + +} + +void read_payload() +{ + unsigned long read_time = millis(); + payload_str[0] = '\0'; // clear the payload string +// print_string(payload_str); + +// if ((Serial.available() > 0)|| first_time == true) + { +// blink(50); + char result = Serial.read(); + char header[] = "OK BME280 "; + char str[100]; + + strcpy(payload_str, header); +// print_string(payload_str); + if (bmePresent) +// sprintf(str, "%4.2f %6.2f %6.2f %5.2f ", + sprintf(str, "%.1f %.2f %.1f %.2f ", + bme.readTemperature(), bme.readPressure() / 100.0, bme.readAltitude(SEALEVELPRESSURE_HPA), bme.readHumidity()); + else + sprintf(str, "0.0 0.0 0.0 0.0 "); + strcat(payload_str, str); +// print_string(payload_str); + if ((millis() - read_time) > 500) { + Serial.println("There is a bme280 sensor problem"); + bmePresent = false; + } + read_time = millis(); + + if (mpuPresent) { +// print_string(payload_str); + mpu6050.update(); + +// sprintf(str, " MPU6050 %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f ", + sprintf(str, "MPU6050 %.1f %.1f %.1f %.1f %.1f %.1f ", + mpu6050.getGyroX(), mpu6050.getGyroY(), mpu6050.getGyroZ(), mpu6050.getAccX(), mpu6050.getAccY(), mpu6050.getAccZ()); + + float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ()); + float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ()); +// Serial.print(rotation); +// Serial.print(" "); +// Serial.println(acceleration); + + if (acceleration > 1.2) + led_set(STEM_LED_GREEN, HIGH); + else + led_set(STEM_LED_GREEN, LOW); + + if (rotation > 5) + led_set(STEM_LED_BLUE, HIGH); + else + led_set(STEM_LED_BLUE, LOW); + + if ((millis() - read_time) > 500) { + Serial.println("There is an mpu6050 sensor problem"); + mpuPresent = false; + } + } else + sprintf(str, "MPU6050 0.0 0.0 0.0 0.0 0.0 0.0 "); + strcat(payload_str, str); +// print_string(payload_str); + + sensorValue = analogRead(TEMPERATURE_PIN); + //Serial.println(sensorValue); + Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1)); +// sprintf(str, "XS %.1f %.1f\n", Temp, Sensor1); + sprintf(str, "XS %.1f 0.0\n", Temp); + strcat(payload_str, str); + + if ((debug_mode) || (payload_command == PAYLOAD_QUERY)) { + payload_command = false; + print_string(payload_str); + } + +/* + if (result == 'R') { + Serial.println("OK"); + delay(100); + first_time = true; + setup(); + } + else if (result == 'C') { + Serial.println("Clearing stored gyro offsets in EEPROM\n"); + EEPROM.put(0, (float)0.0); + first_time = true; + setup(); + } +*/ +// if ((result == '?') || first_time == true) + +/* + if (true) + { + first_time = false; + if (bmePresent) { + Serial.print("OK BME280 "); + Serial.print(bme.readTemperature()); + Serial.print(" "); + Serial.print(bme.readPressure() / 100.0F); + Serial.print(" "); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.print(" "); + Serial.print(bme.readHumidity()); + } else + { + Serial.print("OK BME280 0.0 0.0 0.0 0.0"); + } + if (mpuPresent) { + mpu6050.update(); + + Serial.print(" MPU6050 "); + Serial.print(mpu6050.getGyroX()); + Serial.print(" "); + Serial.print(mpu6050.getGyroY()); + Serial.print(" "); + Serial.print(mpu6050.getGyroZ()); + + Serial.print(" "); + Serial.print(mpu6050.getAccX()); + Serial.print(" "); + Serial.print(mpu6050.getAccY()); + Serial.print(" "); + Serial.print(mpu6050.getAccZ()); + } + else + Serial.print(" MPU6050 0.0 0.0 0.0 0.0 0.0 0.0 "); + + Serial.print(" XS "); + Serial.print(Temp); + Serial.print(" "); + Serial.println(Sensor1); + + if (mpuPresent) { + float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ()); + float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ()); +// Serial.print(rotation); +// Serial.print(" "); +// Serial.println(acceleration); + + if (acceleration > 1.2) + led_set(greenLED, HIGH); + else + led_set(greenLED, LOW); + + if (rotation > 5) + led_set(blueLED, HIGH); + else + led_set(blueLED, LOW); + } +*/ + +// } + } + + if (Serial1.available() > 0) { + +// blink(50); + char result = Serial1.read(); + // Serial1.println(result); + + if (result == 'R') { + Serial1.println("OK"); + delay(100); + first_read = true; + start_payload(); +// setup(); + } + + if (result == '?') + { + if (bmePresent) { + Serial1.print("OK BME280 "); + Serial1.print(bme.readTemperature()); + Serial1.print(" "); + Serial1.print(bme.readPressure() / 100.0F); + Serial1.print(" "); + Serial1.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial1.print(" "); + Serial1.print(bme.readHumidity()); + } else + { + Serial1.print("OK BME280 0.0 0.0 0.0 0.0"); + } + mpu6050.update(); + + Serial1.print(" MPU6050 "); + Serial1.print(mpu6050.getGyroX()); + Serial1.print(" "); + Serial1.print(mpu6050.getGyroY()); + Serial1.print(" "); + Serial1.print(mpu6050.getGyroZ()); + + Serial1.print(" "); + Serial1.print(mpu6050.getAccX()); + Serial1.print(" "); + Serial1.print(mpu6050.getAccY()); + Serial1.print(" "); + Serial1.print(mpu6050.getAccZ()); + + sensorValue = analogRead(TEMPERATURE_PIN); + //Serial.println(sensorValue); + Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1)); + + Serial1.print(" XS "); + Serial1.print(Temp); + Serial1.print(" "); + Serial1.println(Sensor2); + + float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ()); + float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ()); +// Serial.print(rotation); +// Serial.print(" "); +// Serial.println(acceleration); + + if (first_read == true) { + first_read = false; + rest = acceleration; + } + + if (acceleration > 1.2 * rest) + led_set(greenLED, HIGH); + else + led_set(greenLED, LOW); + + if (rotation > 5) + led_set(blueLED, HIGH); + else + led_set(blueLED, LOW); + } + } + +// delay(100); +} + +/**/ +void payload_OK_only() +{ + payload_str[0] = '\0'; // clear the payload string + + if ((Serial.available() > 0)|| first_time == true) // commented back in + { + blink(50); + char result = Serial.read(); + char header[] = "OK BME280 "; + char str[100]; + + strcpy(payload_str, header); +// print_string(str); + if (bmePresent) +// sprintf(str, "%4.2f %6.2f %6.2f %5.2f ", + sprintf(str, "%.1f %.2f %.1f %.2f ", + bme.readTemperature(), bme.readPressure() / 100.0, bme.readAltitude(SEALEVELPRESSURE_HPA), bme.readHumidity()); + else + sprintf(str, "OK BME280 0.0 0.0 0.0 0.0 "); + strcat(payload_str, str); + + if (mpuPresent) { +// print_string(payload_str); + mpu6050.update(); + +// sprintf(str, " MPU6050 %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f ", + sprintf(str, " MPU6050 %.1f %.1f %.1f %.1f %.1f %.1f ", + mpu6050.getGyroX(), mpu6050.getGyroY(), mpu6050.getGyroZ(), mpu6050.getAccX(), mpu6050.getAccY(), mpu6050.getAccZ()); + + strcat(payload_str, str); +// print_string(payload_str); + } + if (result == 'R') { + Serial.println("OK"); + delay(100); +// first_time = true; + start_payload(); +// setup(); + } + else if (result == 'g') { + show_gps = !show_gps; + } + else if (result == 'C') { + Serial.println("Clearing stored gyro offsets in EEPROM\n"); + EEPROM.put(0, (float)0.0); +// first_time = true; + start_payload(); +// setup(); + } + if ((result == '?') || first_time == true) // commented back in + if (true) + { + +// first_time = false; + if (bmePresent) { + Serial.print("OK BME280 "); + Serial.print(bme.readTemperature()); + Serial.print(" "); + Serial.print(bme.readPressure() / 100.0F); + Serial.print(" "); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.print(" "); + Serial.print(bme.readHumidity()); + } else + { + Serial.print("OK BME280 0.0 0.0 0.0 0.0"); + } + if (mpuPresent) { + mpu6050.update(); + + Serial.print(" MPU6050 "); + Serial.print(mpu6050.getGyroX()); + Serial.print(" "); + Serial.print(mpu6050.getGyroY()); + Serial.print(" "); + Serial.print(mpu6050.getGyroZ()); + + Serial.print(" "); + Serial.print(mpu6050.getAccX()); + Serial.print(" "); + Serial.print(mpu6050.getAccY()); + Serial.print(" "); + Serial.print(mpu6050.getAccZ()); + } else + { + Serial.print(" MPU6050 0.0 0.0 0.0 0.0 0.0 0.0"); + } + + sensorValue = analogRead(TEMPERATURE_PIN); + //Serial.println(sensorValue); + Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1)); + + + Serial.print(" XS2 "); + Serial.print(Sensor1,4); + Serial.print(" "); + Serial.print(Sensor2,4); + Serial.print(" "); + Serial.print(Sensor3,2); + Serial.print(" MQ "); + Serial.println(sensorValue); // ,0); + + if (mpuPresent) { + float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ()); + float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ()); +// Serial.print(rotation); +// Serial.print(" "); +// Serial.println(acceleration); + + if (acceleration > 1.2) + led_set(greenLED, HIGH); + else + led_set(greenLED, LOW); + + if (rotation > 5) + led_set(blueLED, HIGH); + else + led_set(blueLED, LOW); + } + } + } + +// Serial2.print("b"); + delay(250); + +// if (Serial2.available() > 0) { + if (true) { +/* + while (Serial2.available() > 0) // read GPS + Serial.write(Serial2.read()); +*/ +// For one second we parse GPS data and report some key values + newData = false; + + unsigned long starting = millis(); + for (unsigned long start = millis(); millis() - start < 1000;) // 5000;) + { + while (Serial2.available()) + { + char c = Serial2.read(); + if (show_gps) + Serial.write(c); // uncomment this line if you want to see the GPS data flowing + if (gps.encode(c)) // Did a new valid sentence come in? + newData = true; + } + } + if (newData) + { + Serial.printf("GPS read new data in ms: %d\n", millis() - start); + float flon, flat, flalt; + unsigned long age; + starting = millis(); +// gps.f_get_position(&flat, &flon, &age); + + Serial.print(F("Location: ")); + if (gps.location.isValid()) + { + Serial.print(gps.location.lat(), 6); + Serial.print(F(",")); + Serial.print(gps.location.lng(), 6); + + flat = gps.location.lat(); + flon = gps.location.lng(); + flalt = gps.altitude.meters(); + } + else + { + Serial.print(F("INVALID")); + } + Serial.print("\r\n"); + + Sensor1 = flat; + Sensor2 = flon; + Sensor3 = flalt; // (float) gps.altitude.meters(); + Serial.printf("New GPS data: %f %f %f ms: %d\n", Sensor1, Sensor2, Sensor3, millis() - start); + } else + Serial.printf("GPS read no new data: %d\n", millis() - start); + + + blink(50); +/* + if (Serial1.available()) { + char result = Serial1.read(); +// Serial1.println(result); +// Serial.println(result); // don't print read result + + if (result == 'R') { + Serial1.println("OK"); + delay(100); + first_read = true; + start_payload(); +// setup(); + } + } +*/ +// if (result == '?') + if (true) // always send payload data over serial + { + if (bmePresent) { +// Serial1.print("START_FLAGOK BME280 "); + Serial1.print(sensor_start_flag); + Serial1.print("OK BME280 "); + Serial1.print(bme.readTemperature()); + Serial1.print(" "); + Serial1.print(bme.readPressure() / 100.0F); + Serial1.print(" "); + Serial1.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial1.print(" "); + Serial1.print(bme.readHumidity()); + } else + { +// Serial1.print("START_FLAGOK BME280 0.0 0.0 0.0 0.0"); + Serial1.print(sensor_start_flag); + Serial1.print("OK BME280 0.0 0.0 0.0 0.0"); + } + if (mpuPresent) { + mpu6050.update(); + + Serial1.print(" MPU6050 "); + Serial1.print(mpu6050.getGyroX()); + Serial1.print(" "); + Serial1.print(mpu6050.getGyroY()); + Serial1.print(" "); + Serial1.print(mpu6050.getGyroZ()); + + Serial1.print(" "); + Serial1.print(mpu6050.getAccX()); + Serial1.print(" "); + Serial1.print(mpu6050.getAccY()); + Serial1.print(" "); + Serial1.print(mpu6050.getAccZ()); + + } else + { + Serial1.print(" MPU6050 0.0 0.0 0.0 0.0 0.0 0.0"); + } + + sensorValue = analogRead(TEMPERATURE_PIN); + //Serial.println(sensorValue); + Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1)); + + Serial1.print(" XS2 "); + Serial1.print(Sensor1,4); + Serial1.print(" "); + Serial1.print(Sensor2,4); + Serial1.print(" "); + Serial1.print(Sensor3,2); + Serial1.print(" MQ "); + Serial1.print(sensorValue); //,0); +// Serial1.println("END_FLAG"); + Serial1.println(sensor_end_flag); + + blink(50); + delay(50); + blink(50); + + if (mpuPresent) { + float rotation = sqrt(mpu6050.getGyroX()*mpu6050.getGyroX() + mpu6050.getGyroY()*mpu6050.getGyroY() + mpu6050.getGyroZ()*mpu6050.getGyroZ()); + float acceleration = sqrt(mpu6050.getAccX()*mpu6050.getAccX() + mpu6050.getAccY()*mpu6050.getAccY() + mpu6050.getAccZ()*mpu6050.getAccZ()); +// Serial.print(rotation); +// Serial.print(" "); +// Serial.println(acceleration); + + if (first_read == true) { + first_read = false; + rest = acceleration; + } + + if (acceleration > 1.2 * rest) + led_set(greenLED, HIGH); + else + led_set(greenLED, LOW); + + if (rotation > 5) + led_set(blueLED, HIGH); + else + led_set(blueLED, LOW); + } + } + } + + delay(100); +} + +/**/ +/* +void eeprom_word_write(int addr, int val) +{ + EEPROM.write(addr * 2, lowByte(val)); + EEPROM.write(addr * 2 + 1, highByte(val)); +} + +short eeprom_word_read(int addr) +{ + return ((EEPROM.read(addr * 2 + 1) << 8) | EEPROM.read(addr * 2)); +} +*/ + +void blink_setup() +{ +#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4) + // initialize digital pin PB1 as an output. + pinMode(PC13, OUTPUT); + pinMode(PB9, OUTPUT); + pinMode(PB8, OUTPUT); +#endif + +#if defined __AVR_ATmega32U4__ || ARDUINO_ARCH_RP2040 + pinMode(RXLED, OUTPUT); // Set RX LED as an output + // TX LED is set as an output behind the scenes + pinMode(greenLED, OUTPUT); + pinMode(blueLED,OUTPUT); +#endif +} + +void blink(int length) +{ + if (wifi) + digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON + else + digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON + + sleep(length/1000.0); // delay(length); // wait for a lenth of time + + if (wifi) + digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF + else + digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF +} + +void led_set(int ledPin, bool state) +{ +#if defined(ARDUINO_ARCH_STM32F0) || defined(ARDUINO_ARCH_STM32F1) || defined(ARDUINO_ARCH_STM32F3) || defined(ARDUINO_ARCH_STM32F4) || defined(ARDUINO_ARCH_STM32L4) + if (ledPin == greenLED) + digitalWrite(PB9, state); + else if (ledPin == blueLED) + digitalWrite(PB8, state); +#endif + +#if defined __AVR_ATmega32U4__ || ARDUINO_ARCH_RP2040 + digitalWrite(ledPin, state); +#endif +} + + +void sleep(float timer) { // sleeps for intervals more than 0.01 milli seconds + + unsigned long time_us = (unsigned long)(timer * 1000000.0); + unsigned long startSleep = micros(); + while ((micros() - startSleep) < time_us) { +// busy_wait_us(100); + delayMicroseconds(100); + } +} + +void process_bootsel() { + + if ((new_mode != mode) || (prompt != false)) { + Serial.println("******* BOOTSEL bounce error!! *******\n\n"); + return; + } + + +// Serial.println("BOOTSEL pressed!"); + + int release = FALSE; + + if (wifi) + digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON + else + digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON + sleep(1.0); + +// int pb_value = digitalRead(MAIN_PB_PIN); +/* + if (!BOOTSEL) { + Serial.println("BOOTSEL: Reboot!"); + release = TRUE; + prompt = PROMPT_REBOOT; + } +*/ + blinkTimes(1); + sleep(1.5); + +// pb_value = digitalRead(MAIN_PB_PIN); + if ((!BOOTSEL) && (release == FALSE)) { + new_mode = AFSK; + Serial.println("BOOTSEL: Switch to AFSK"); + release = TRUE; +// setup(); + } + + if (release == FALSE) { + blinkTimes(2); + sleep(1.5); + } + +// pb_value = digitalRead(MAIN_PB_PIN); + if ((!BOOTSEL) && (release == FALSE)) { + new_mode = FSK; + Serial.println("BOOTSEL: Switch to FSK"); + release = TRUE; + } + + if (release == FALSE) { + blinkTimes(3); + sleep(1.5); + } + +// pb_value = digitalRead(MAIN_PB_PIN); + if ((!BOOTSEL) && (release == FALSE)) { + new_mode = BPSK; + Serial.println("BOOTSEL: Switch to BPSK"); + release = TRUE; + } + + if (release == FALSE) { + blinkTimes(4); + sleep(1.5); + } + +// pb_value = digitalRead(MAIN_PB_PIN); + if ((!BOOTSEL) && (release == FALSE)) { + new_mode = SSTV; + Serial.println("BOOTSEL: Switch to SSTV"); + release = TRUE; + } + + if (release == FALSE) { + blinkTimes(5); + sleep(1.5); + } + +// pb_value = digitalRead(MAIN_PB_PIN); + if ((!BOOTSEL) && (release == FALSE)) { + new_mode = CW; + Serial.println("BOOTSEL: Switch to CW"); + release = TRUE; + } + + if (release == FALSE) { + Serial.println("BOOTSEL: Reboot!"); + prompt = PROMPT_REBOOT; + digitalWrite(MAIN_LED_GREEN, LOW); + sleep(0.5); + digitalWrite(MAIN_LED_GREEN, HIGH); + sleep(0.5); + digitalWrite(MAIN_LED_GREEN, LOW); + sleep(0.5); + digitalWrite(MAIN_LED_GREEN, HIGH); + sleep(0.5); + digitalWrite(MAIN_LED_GREEN, LOW); + sleep(0.5); + digitalWrite(MAIN_LED_GREEN, HIGH); + sleep(0.5); + } + if (new_mode != mode) + transmit_off(); +// sleep(2.0); + + // make sure built-in LED is off + if (wifi) + digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF + else + digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF +} + +void blinkTimes(int blinks) { + for (int i = 0; i < blinks; i++) { + digitalWrite(MAIN_LED_GREEN, LOW); + + if (wifi) + digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF + else + digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF + + sleep(0.1); + digitalWrite(MAIN_LED_GREEN, HIGH); + + if (wifi) + digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON + else + digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON + + sleep(0.1); + } +} + +void blinkFastTimes(int blinks) { + for (int i = 0; i < blinks; i++) { + digitalWrite(MAIN_LED_GREEN, LOW); + + if (wifi) + digitalWrite(LED_BUILTIN, LOW); // set the built-in LED OFF + else + digitalWrite(led_builtin_pin, LOW); // set the built-in LED OFF + + sleep(0.05); + digitalWrite(MAIN_LED_GREEN, HIGH); + + if (wifi) + digitalWrite(LED_BUILTIN, HIGH); // set the built-in LED ON + else + digitalWrite(led_builtin_pin, HIGH); // set the built-in LED ON + + sleep(0.05); + } +} + +void blink_pin(int pin, int duration) { + + digitalWrite(pin, HIGH); + sleep((float)duration / 1000.00); + digitalWrite(pin, LOW); + +} + + +bool check_for_wifi() { + +#ifndef PICO_W + + Serial.println("WiFi disabled in software"); + return(false); // skip check if not Pico W board or compilation will fail + +#endif + +// stdio_init_all(); + +// adc_init(); +// adc_gpio_init(29); + pinMode(29, INPUT); +// adc_select_input(3); + const float conversion_factor = 3.3f / (1 << 12); +// uint16_t result = adc_read(); + uint16_t result = analogRead(29); +// Serial.printf("ADC3 value: 0x%03x, voltage: %f V\n", result, result * conversion_factor); + +// if (result < 0x100) { + if (result < 0x10) { + Serial.println("\nPico W detected!\n"); + return(true); + } + else { + Serial.println("\nPico detected!\n"); + return(false); + } +} + +void parse_payload() { + + if ((payload_str[0] == 'O') && (payload_str[1] == 'K')) // only process if valid payload response + { + int count1; + char * token; + + const char space[2] = " "; + token = strtok(payload_str, space); + for (count1 = 0; count1 < 17; count1++) { + if (token != NULL) { + sensor[count1] = (float) atof(token); +// Serial.print("sensor: "); +// Serial.println(sensor[count1]); + token = strtok(NULL, space); + } + } +// printf("\n"); +// } +// else +// payload = OFF; // turn off since STEM Payload is not responding +// } +// if ((payload_str[0] == 'O') && (payload_str[1] == 'K')) { + for (int count1 = 0; count1 < 17; count1++) { + if (sensor[count1] < sensor_min[count1]) + sensor_min[count1] = sensor[count1]; + if (sensor[count1] > sensor_max[count1]) + sensor_max[count1] = sensor[count1]; + // printf("Smin %f Smax %f \n", sensor_min[count1], sensor_max[count1]); + } + } +} + +void show_dir() { + LittleFS.begin(); + Dir dir = LittleFS.openDir("/"); +// or Dir dir = LittleFS.openDir("/data"); + Serial.println("FS directory:"); + while (dir.next()) { + Serial.print(dir.fileName()); + if(dir.fileSize()) { + File f = dir.openFile("r"); + Serial.print(" "); + Serial.println(f.size()); + } + } + Serial.println(">"); +} + +void serial_input() { + + if (prompt == false) { // only query if not in the middle of prompting + + if (Serial.available() > 0) { // check for user input on serial port + +// blink(50); + char result = Serial.read(); + + if ((result != '\n') && (result != '\r')) { + + Serial.println(result); + + switch(result) { + case 'h': + case 'H': + // Serial.println("Help"); + prompt = PROMPT_HELP; + break; + + case 'a': + case 'A': + Serial.println("Change to AFSK/APRS mode"); + new_mode = AFSK; + break; + + case 'm': + case 'M': + Serial.println("Change to CW mode"); + new_mode = CW; + break; + + case 'F': + Serial.println("Formatting flash memory"); + prompt = PROMPT_FORMAT; + break; + case 'f': + Serial.println("Change to FSK mode"); + new_mode = FSK; + break; + + case 'b': + case 'B': + Serial.println("Change to BPSK mode"); + new_mode = BPSK; + break; + + case 's': + Serial.println("Change to SSTV mode"); + new_mode = SSTV; + break; + + case 'S': + Serial.println("I2C scan"); + prompt = PROMPT_I2CSCAN; + break; + + case 'i': + case 'I': + Serial.println("Restart CubeSatsim software"); + prompt = PROMPT_RESTART; + break; + + case 'c': + Serial.println("Change the CALLSIGN"); + prompt = PROMPT_CALLSIGN; + break; + + case 'C': + Serial.println("Debug camera"); + debug_camera = true; + prompt = PROMPT_CAMERA; + break; + + case 't': + case 'T': + Serial.println("Change the Simulated Telemetry"); + prompt = PROMPT_SIM; + break; + + case 'p': + case 'P': + Serial.println("Reset payload EEPROM settings"); + prompt = PROMPT_PAYLOAD; + break; + + case 'r': + case 'R': + Serial.println("Change the Resets Count"); + prompt = PROMPT_RESET; + break; + + case 'o': + case 'O': + Serial.println("Read diode temperature"); + prompt = PROMPT_TEMP; + break; + + case 'l': + case 'L': + Serial.println("Change the Latitude and Longitude"); + prompt = PROMPT_LAT; + break; + + case 'v': + case 'V': + Serial.println("Read INA219 voltage and current"); + prompt = PROMPT_VOLTAGE; + break; + + case '?': + Serial.println("Query payload sensors"); + prompt = PROMPT_QUERY; + break; + + case 'd': + Serial.println("Change debug mode"); + prompt = PROMPT_DEBUG; + break; + + case 'w': + Serial.println(wifi); + Serial.println("Connect to WiFi"); + prompt = PROMPT_WIFI; + break; + + default: + Serial.println("Not a command\n"); + + break; + } + if ((mode == SSTV) && prompt) // stop SSTV if need to prompt for input + sstv_end(); + + if (new_mode != mode) + transmit_off(); +// sleep(2.0); + } + } + } +} + +void prompt_for_input() { + float float_result; + + if (!prompting) { + prompting = true; + + while (Serial.available() > 0) // clear any characters in serial input buffer + Serial.read(); + + switch(prompt) { + + case PROMPT_HELP: + Serial.println("\nChange settings by typing the letter:"); + Serial.println("h Help info"); + Serial.println("a AFSK/APRS mode"); + Serial.println("m CW mode"); + Serial.println("f FSK/DUV mode"); + Serial.println("F Format flash memory"); + Serial.println("b BPSK mode"); + Serial.println("s SSTV mode"); + Serial.println("S I2C scan"); + Serial.println("i Restart"); + Serial.println("c Change CALLSIGN"); + Serial.println("C Debug Camera"); + Serial.println("t Simulated Telemetry"); + Serial.println("r Reset Count"); + Serial.println("p Reset payload and stored EEPROM values"); + Serial.println("l Change Lat and Lon"); + Serial.println("? Query sensors"); + Serial.println("v Read INA219 voltage and current"); + Serial.println("o Read diode temperature"); + Serial.println("d Change debug mode"); + Serial.println("w Connect to WiFi\n"); + + Serial.printf("Software version v0.39 \nConfig file /sim.cfg contains %s %d %f %f %s\n\n", callsign, reset_count, lat_file, long_file, sim_yes); + + switch(mode) { + + case(AFSK): + Serial.println("AFSK mode"); + break; + + case(FSK): + Serial.println("FSK mode"); + break; + + case(BPSK): + Serial.println("BPSK mode"); + break; + + case(SSTV): + Serial.println("SSTV mode"); + break; + + case(CW): + Serial.println("CW mode"); + break; + } + + break; + + case PROMPT_CALLSIGN: + Serial.println("Editing the CALLSIGN in the onfiguration file for CubeSatSim"); + Serial.println("Return keeps current value."); + Serial.print("\nCurrent callsign is "); + Serial.println(callsign); + + Serial.print("Enter callsign in all capitals: "); + get_serial_string(); + + print_string(serial_string); + + if (strlen(serial_string) > 0) { + strcpy(callsign, serial_string); + if (mode == AFSK) { + char destination[] = "APCSS"; + set_callsign(callsign, destination); + } + Serial.println("Callsign updated!"); + write_config_file(); + } else + Serial.println("Callsign not updated!"); + + break; + + case PROMPT_SIM: + if (sim_mode == TRUE) + Serial.println("Simulted Telemetry mode is currently on"); + else + Serial.println("Simulted Telemetry mode is currently off"); + Serial.println("Do you want Simulated Telemetry on (y/n)"); + get_serial_char(); + if ((serial_string[0] == 'y') || (serial_string[0] == 'Y')) { + Serial.println("Setting Simulated telemetry to on"); + reset_min_max(); + config_simulated_telem(); + write_config_file(); + } else if ((serial_string[0] == 'n') || (serial_string[0] == 'N')) { + Serial.println("Setting Simulated telemetry to off"); + reset_min_max(); + sim_mode = false; + if (!ina219_started) + start_ina219(); + write_config_file(); + } else + Serial.println("No change to Simulated Telemetry mode"); + break; + + case PROMPT_LAT: + + Serial.println("Changing the latitude and longitude - only used for APRS telemetry"); + Serial.println("Hitting return keeps the current value."); + + Serial.print("Current value of latitude is "); + Serial.println(latitude); + Serial.println("Enter latitude (decimal degrees, positive is north): "); + get_serial_string(); + float_result = atof(serial_string); + if (float_result != 0.0) { + Serial.print("Latitude updated to "); + Serial.println(float_result); + latitude = float_result; + } else + Serial.println("Latitude not updated"); + + get_serial_clear_buffer(); + Serial.print("Current value of longitude is "); + Serial.println(longitude); + Serial.println("Enter longitude (decimal degrees, positive is east): "); + get_serial_string(); + float_result = atof(serial_string); + if (float_result != 0.0) { + Serial.print("Longitude updated to "); + Serial.println(float_result); + longitude = float_result; + } else + Serial.println("Longitude not updated"); + + write_config_file(); + if (mode == AFSK) + set_lat_lon(); + + break; + + case PROMPT_QUERY: + Serial.println("Querying payload sensors"); + payload_command = PAYLOAD_QUERY; + break; + + case PROMPT_CAMERA: + show_dir(); + get_camera_image(debug_camera); + show_dir(); + break; + + case PROMPT_TEMP: + sensorValue = analogRead(TEMPERATURE_PIN); + Serial.print("Raw diode voltage: "); + Serial.println(sensorValue); + Temp = T1 + (sensorValue - R1) *((T2 - T1)/(R2 - R1)); + Serial.print("Calculated temperature: "); + Serial.print(Temp); + Serial.println(" C"); + break; + + case PROMPT_VOLTAGE: + Serial.println("Querying INA219 voltage and current sensors"); + if (!ina219_started) + start_ina219(); + voltage_read = true; + read_ina219(); + break; + + case PROMPT_REBOOT: + Serial.println("Rebooting..."); + Serial.flush(); + watchdog_reboot (0, SRAM_END, 500); // restart Pico + sleep(20.0); + break; + + case PROMPT_FORMAT: + LittleFS.format(); +// Serial.println("Reboot or power cycle to restart the CubeSatSim"); + // while (1) ; // infinite loop + Serial.println("Rebooting..."); + Serial.flush(); + watchdog_reboot (0, SRAM_END, 500); // restart Pico + sleep(20.0); + break; + + case PROMPT_PAYLOAD: + Serial.println("Resetting the Payload"); + payload_command = PAYLOAD_RESET; + start_payload(); + break; + + case PROMPT_RESET: + Serial.println("Reset count is now 0"); + reset_count = 0; + write_config_file(); + break; + + case PROMPT_RESTART: + prompt = false; +// Serial.println("Restart not yet implemented"); + start_payload(); +// start_ina219(); + if ((mode != CW) || (!filter_present)) + transmit_callsign(callsign); + sleep(0.5); + config_telem(); + config_radio(); + sampleTime = (unsigned int) millis(); + break; + + case PROMPT_DEBUG: + Serial.print("Changing Debug Mode to "); + debug_mode = !debug_mode; + if (debug_mode) + Serial.println("on"); + else + Serial.println("off"); + break; + + case PROMPT_WIFI: + Serial.println(wifi); + if (wifi) { + char ssid[30], pass[30]; + Serial.println("Enter the credentials for your WiFi network"); + + Serial.print("Enter WiFi SSID: "); + get_serial_string(); + + print_string(serial_string); + + if (strlen(serial_string) > 0) { + strcpy(ssid, serial_string); + Serial.print("Enter WiFi password: "); + get_serial_string(); + if (strlen(serial_string) > 0) { + strcpy(pass, serial_string); + Serial.println("Connecting to Wifi"); +// Serial.printf("%s%s\n",ssid, pass); + + WiFi.begin(ssid, pass); + + unsigned int elapsed_timer = (unsigned int) millis(); + while ((WiFi.status() != WL_CONNECTED) && ((millis() - elapsed_timer) < 10000)) { + Serial.print("."); + delay(500); + } + if (((millis() - elapsed_timer) > 10000)) + Serial.println("Failed to connect!"); + else + Serial.println("Connected to WiFi!"); + } else + Serial.println("No password entered."); + } else + Serial.println("No SSID entered."); + } else + Serial.println("WiFi not available"); + + break; + + case PROMPT_I2CSCAN: + Serial.print("I2C scan"); + +// -------------------------------------- +// i2c_scanner +// +// Version 1 +// This program (or code that looks like it) +// can be found in many places. +// For example on the Arduino.cc forum. +// The original author is not know. +// Version 2, Juni 2012, Using Arduino 1.0.1 +// Adapted to be as simple as possible by Arduino.cc user Krodal +// Version 3, Feb 26 2013 +// V3 by louarnold +// Version 4, March 3, 2013, Using Arduino 1.0.3 +// by Arduino.cc user Krodal. +// Changes by louarnold removed. +// Scanning addresses changed from 0...127 to 1...119, +// according to the i2c scanner by Nick Gammon +// https://www.gammon.com.au/forum/?id=10896 +// Version 5, March 28, 2013 +// As version 4, but address scans now to 127. +// A sensor seems to use address 120. +// Version 6, November 27, 2015. +// Added waiting for the Leonardo serial communication. +// +// +// This sketch tests the standard 7-bit addresses +// Devices with higher bit address might not be seen properly. +// + + +{ + byte error, address; + int nDevices; + + Serial.println("Scanning I2C Bus 1"); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + Wire.beginTransmission(address); + error = Wire.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at bus 1 address 0x"); + if (address<16) + Serial.print("0"); + Serial.print(address,HEX); + Serial.println(" !"); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at bus 1 address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found on bus 1\n"); + else + Serial.println("done\n"); + + delay(5000); // wait 5 seconds for next scan + + Serial.println("Scanning I2C Bus 2"); + + nDevices = 0; + for(address = 1; address < 127; address++ ) + { + // The i2c_scanner uses the return value of + // the Write.endTransmisstion to see if + // a device did acknowledge to the address. + + Wire1.beginTransmission(address); + error = Wire1.endTransmission(); + + if (error == 0) + { + Serial.print("I2C device found at bus 2 address 0x"); + if (address<16) + Serial.print("0"); + Serial.print(address,HEX); + Serial.println(" !"); + + nDevices++; + } + else if (error==4) + { + Serial.print("Unknown error at bus 2 address 0x"); + if (address<16) + Serial.print("0"); + Serial.println(address,HEX); + } + } + if (nDevices == 0) + Serial.println("No I2C devices found on bus 2\n"); + else + Serial.println("done\n"); + +} + Serial.println("complete"); + break; + + } + prompt = false; + prompting = false; + } +// else +// Serial.println("Already prompting!"); +} + +void get_serial_string() { + int input = 0; + int i = 0; + unsigned int elapsed_time = (unsigned int) millis(); + while ((input != '\n') && (input!= '\r') && (i < 128) && ((millis() - elapsed_time) < 20000)) { + if (Serial.available() > 0) { + input = Serial.read(); + if ((input != '\n') && (input!= '\r')) { + serial_string[i++] = input; + Serial.write(input); + } + } + sleep(0.1); + } + serial_string[i] = 0; + Serial.println(" "); +} + +void get_serial_char() { + unsigned int elapsed_time = (unsigned int) millis(); + while (((millis() - elapsed_time) < 20000) && (Serial.available() < 1)) { } + if (Serial.available() > 0) { + serial_string[0] = Serial.read(); // get character + Serial.write(serial_string[0]); + serial_string[1] = 0; + Serial.println(" "); + } else + { + serial_string[0] = 0; // timeout - no character + } +} + +void get_serial_clear_buffer() { +// Serial.println("Emptying serial input buffer"); + while (Serial.available() > 0) + Serial.read(); + +} + + +void read_config() { + LittleFS.begin(); + Serial.println("Reading config file"); + char buff[32]; + File mode_file = LittleFS.open("/config.txt", "r"); + if (!mode_file) { + write_mode(mode); + } else { + if (mode_file.read((uint8_t *)buff, 31)) { +// Serial.println("Reading mode from .mode file"); + sscanf(buff, "%d", &mode); + mode_file.close(); +// Serial.print("Mode is "); +// Serial.print(mode); + + } + } +} + +void write_config(int save_mode) { + + char buff[32]; + Serial.println("Writing config file"); + File mode_file = LittleFS.open("/config.txt", "w+"); + + sprintf(buff, "%d", save_mode); + if (debug_mode) { + Serial.println("Writing string"); + print_string(buff); + } + + if (mode_file.write(buff, strlen(buff)) != strlen(buff)) { +// Serial.println(mode_file.write(buff, strlen(buff))); + Serial.println("*** config file write error! ***\n\n"); + blinkFastTimes(3); + } + + mode_file.close(); +// Serial.println("Write complete"); +} + + +void get_input() { + if (mode != SSTV) + Serial.print("+"); + if ((mode == CW) || (mode == SSTV)) + serial_input(); + +// check for button press + if (digitalRead(MAIN_PB_PIN) == PRESSED) // pushbutton is pressed + process_pushbutton(); + if (BOOTSEL) // boot selector button is pressed on Pico + process_bootsel(); + + if (prompt) { +// Serial.println("Need to prompt for input!"); + prompt_for_input(); + prompt = false; + } + + // check to see if the mode has changed + if (mode != new_mode) { + Serial.println("Changing mode"); + cw_stop = false; // enable CW or won't hear CW ID +/// if (mode == SSTV) { +/// ITimer1.detachInterrupt(); +/// start_button_isr(); // restart button isr +/// } + int old_mode = mode; + bool config_done = false; +// mode = new_mode; // change modes if button pressed + write_mode(new_mode); + + Serial.println("Rebooting..."); + Serial.flush(); + watchdog_reboot (0, SRAM_END, 500); //10); // restart Pico + + sleep(20.0); +/* + if (new_mode != CW) + transmit_callsign(callsign); + sleep(0.5); + + if (!config_done) + config_telem(); // run this here for all other modes + + config_radio(); + if ((mode == FSK) || (mode == BPSK)) { + digitalWrite(LED_BUILTIN, HIGH); + digitalWrite(MAIN_LED_BLUE, HIGH); + } + + sampleTime = (unsigned int) millis(); +*/ + } + +}