├── Archive ├── IC-705_BLE_Decoder_Simple │ └── IC-705_BLE_Decoder_Simple.ino ├── IC705_ESP32_BLE_client_uart │ └── IC705_ESP32_BLE_client_uart.ino └── M5StampC3U_Decoder │ ├── BLE.cpp │ ├── BLE.h │ ├── BLEScan.h │ ├── BT_CIV_Band_Decoder.cpp │ ├── CIV.cpp │ ├── CIV.h │ ├── DebugPrint.h │ ├── Decoder.cpp │ ├── Decoder.h │ ├── M5StampC3U_Decoder.h │ └── M5StampC3U_Decoder.ino ├── M5Stack_CI-V_Band_Decoder ├── BLE.cpp ├── BLE.h ├── BLEScan.h ├── BT_USB_CIV_Band_Decoder.cpp ├── CIV.cpp ├── CIV.h ├── DebugPrint.h ├── Decoder.cpp ├── Decoder.h ├── M5Stack_CI-V_Band_Decoder.h ├── M5Stack_CI-V_Band_Decoder.ino └── usbh_helper.h ├── Pictures ├── 50W 28VDC 903MHz RF Amp pallet.jpg ├── 50W 28VDC 903MHz RF Amp pallet internal .jpg ├── 900Mhz 50W RF amp installed and working.jpg ├── 900Mhz 50W amp mounted on heat sinking end panel.jpg ├── Aug-10-2024_UI_Xvtr_grid.jpg ├── Aug-9-2024_UI_makeover-small-aug9.jpg ├── Chassis end panels have heat sink fins.jpg ├── Core Basic and Core3.jpg ├── Core Basic in early dev.jpg ├── Core3 Se connected by BLE to IC-705.jpg ├── K7MDL BT CI-V decoders.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Xvtr icons ON.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Band.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - current.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - voltage -TX icon on.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - voltage.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 -TX and Xvtr icons ON.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - 12V power distribution.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Back View.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Control Board with M5StampC3U.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View Front.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View Side 2.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top view 1.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Wiring it up.jpg ├── K7MDL IC-705 3-Band Transverter Box - Dec 2024 M5Core2 Radio side - BT connected.jpg ├── M5AtomS3 rotated.jpg └── XvtrBox OLED Voltage.jpg └── README.md /Archive/IC-705_BLE_Decoder_Simple/IC-705_BLE_Decoder_Simple.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IC705_BLE_Decoder_Simple.ino 3 | * 4 | * Central Mode (client) BLE UART for ESP32 - Tested on CoreS3 SE 5 | * 6 | * Modifed by K7MDL Aug 2024 for BLE Serial port (uart) connection to the IC-705 via BLE serial on a M5Stack Core3 and Core 3 SE. Tested on a SE version 7 | * 8 | * This is a simplified example program showing a BLE connection to an IC-705 and getting CI-V frequency and PTT state. 9 | * The UI is simply a title, frequency, band number, and PTT status, with PTT (Rx/Tx) turning red during Tx. 10 | * Future example programs could show more info on the display, process button touches, and have configurable band decoder outputs 11 | * 12 | *********************************************** Usage ************************************************************************* 13 | * 14 | * To use: 15 | * 1. On the IC-705 press menu 16 | * 2. Navigate to to Set -> Bluetooth Set -> <> 17 | * 3. The device will pair silently with the radio and display the given name in the Pairing Connect page. 18 | * 19 | * Once paired it will auto-reconnect as long as it is paired with the radio. 20 | * The name shown in the Pairing/Connect menu is hard coded today. See below byte arrays to edit. 21 | * 22 | ******************************** Below is the original code header/credits ************************************************** 23 | * 24 | * This sketch is a central mode (client) Nordic UART Service (NUS) that connects automatically to a peripheral (server) 25 | * Nordic UART Service. NUS is what most typical "blueart" servers emulate. This sketch will connect to your BLE uart 26 | * device in the same manner the nRF Connect app does. 27 | * 28 | * Once connected this sketch will switch notification on using BLE2902 for the charUUID_TX characteristic which is the 29 | * characteristic that our server is making data available on via notification. The data received from the server 30 | * characteristic charUUID_TX will be printed to Serial on this device. Every five seconds this device will send the 31 | * string "Time since boot: #" to the server characteristic charUUID_RX, this will make that data available in the BLE 32 | * uart and trigger a notifyCallback or similar depending on your BLE uart server setup. 33 | * 34 | * 35 | * A brief explanation of BLE client/server actions and rolls: 36 | * 37 | * Central Mode (client) - Connects to a peripheral (server). 38 | * -Scans for devices and reads service UUID. 39 | * -Connects to a server's address with the desired service UUID. 40 | * -Checks for and makes a reference to one or more characteristic UUID in the current service. 41 | * -The client can send data to the server by writing to this RX Characteristic. 42 | * -If the client has enabled notifications for the TX characteristic, the server can send data to the client as 43 | * notifications to that characteristic. This will trigger the notifyCallback function. 44 | * 45 | * Peripheral (server) - Accepts connections from a central mode device (client). 46 | * -Advertises a service UUID. 47 | * -Creates one or more characteristic for the advertised service UUID 48 | * -Accepts connections from a client. 49 | * -The server can send data to the client by writing to this TX Characteristic. 50 | * -If the server has enabled notifications for the RX characteristic, the client can send data to the server as 51 | * notifications to that characteristic. This the default function on most "Nordic UART Service" BLE uart sketches. 52 | * 53 | * 54 | * Copyright <2018> 55 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 56 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 57 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 58 | * permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright 59 | * notice and this permission notice shall be included in all copies or substantial portions of the Software. THE 60 | * SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 61 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 62 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 63 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 | * 65 | * 66 | * Based on the "BLE_Client" example by Neil Kolban: 67 | * https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino 68 | * With help from an example by Andreas Spiess: 69 | * https://github.com/SensorsIot/Bluetooth-BLE-on-Arduino-IDE/blob/master/Polar_Receiver/Polar_Receiver.ino 70 | * Nordic UART Service info: 71 | * https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fble_sdk_app_nus_eval.html 72 | * 73 | */ 74 | 75 | //#include 76 | #include "BLEDevice.h" 77 | #include "esp_bt_main.h" 78 | #include "esp_bt_device.h" 79 | #include 80 | #include "MODULE_4IN8OUT.h" 81 | 82 | #define MOD_4IN_8OUT // enable the 4input 8output MOSFET IO module 83 | //#define WATCH_SERIAL // Print data received from the radio over the CI-V bus 84 | #define WATCH_DECODER // monitor the decoder in and output pin state 85 | #define POLL_TX 90 // poll the radio for TX/RX status. Can pass through PTT to specific IO pins per band (PTT breakout) 86 | #define POLL_FREQ 250 // poll the radio for frequency and other parameters - can add transverter offsets 87 | 88 | // #define IC905 // future use: The IC-905 has 5 bytes for frequency for bands < 10Ghz and 6 bytes above to support bands 10GHz and higher 89 | #define IC705 // Specify which radio. Some CIV commands have different numbers 90 | 91 | //#define M5BTNS 92 | #ifdef M5BTNS 93 | #include 94 | goblib::UnifiedButton unifiedButton; 95 | #endif 96 | 97 | MODULE_4IN8OUT module; 98 | 99 | // The remote Nordic UART service service we wish to connect to. 100 | // This service exposes two characteristics: one for transmitting and one for receiving (as seen from the client). 101 | static BLEUUID serviceUUID("14cf8001-1ec2-d408-1b04-2eb270f14203"); 102 | 103 | // The characteristics of the above service we are interested in. 104 | // The client can send data to the server by writing to this characteristic. 105 | static BLEUUID charUUID_RX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // RX Characteristic 106 | 107 | // If the client has enabled notifications for this characteristic, 108 | // the server can send data to the client as notifications. 109 | static BLEUUID charUUID_TX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // TX Characteristic 110 | 111 | // For testing I hard coded the pairing messages to the IC-705! 112 | 113 | // UUID, 41 bytes total. Anyu less and wil lnot get a reply from teh Name msg 0x42. It is made up nunmber for testing amd shoudl bne unique on each device 114 | // The radio uses the combination of UUID and Name to identity each device paired. 115 | uint8_t CIV_ID0[] = {0xFE,0xF1,0x00,0x61,0x30,0x30,0x30,0x30,0x31,0x31,0x30,0x31,0x2D,0x30,0x30,0x30,0x30,0x2D,0x31,0x30,0x30,0x30,0x2D,0x38,0x30,0x30,0x30,0x2D,0x30,0x30,0x38,0x30,0x35,0x46,0x39,0x42,0x33,0x34,0x46,0x42,0xFD}; // Send our UUID 116 | 117 | // name is "IC705 Decoder 04" 21 bytes total - YOu can change this but teh name must be exactly 16 bytes. Can pad with spaces 118 | uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0x2D, 0x30, 0x34, 0xFD}; // Send Name 119 | // name is "IC705 BT Decoder" 120 | // uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x42, 0x54, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0xFD}; // Send Name 121 | 122 | 123 | // ToDo: Make configurable the target radio's service and characteristic UUIDs. Only needed if future radios use differenmt UUIDs. 124 | // The RX and Tx UUIDs are the same number. Unlike most devices, the CI-V bus is not full duplex, 125 | // they share the same wire for Rx and TX and so it goes for the digital wire here. 126 | 127 | 128 | int scanTime = 5; //In seconds 129 | static BLEScan *pBLEScan = NULL; 130 | static BLEClient *pClient = NULL; 131 | static BLEAddress *pServerAddress; 132 | static boolean doConnect = false; 133 | static boolean connected = false; 134 | static BLERemoteCharacteristic* pTXCharacteristic; 135 | static BLERemoteCharacteristic* pRXCharacteristic; 136 | uint8_t radio_address = 0xA4; // A4 for IC-705, AC for IC-905 137 | uint16_t background_color = BLACK; 138 | uint16_t text_color = WHITE; 139 | uint64_t frequency = 0; 140 | const uint32_t decMulti[] = {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1}; 141 | uint64_t prev_frequency = 0; 142 | uint8_t band = 254; 143 | uint8_t PTT = 0; 144 | uint8_t prev_PTT = 1; 145 | static bool BT_ADDR_confirm = false; 146 | static bool Name_confirm = false; 147 | static bool Token_confirm = false; 148 | static bool Pairing_Accepted = false; 149 | static bool CIV_granted = false; 150 | static bool BLE_connected = false; 151 | const uint8_t notificationOff[] = {0x0, 0x0}; 152 | const uint8_t notificationOn[] = {0x1, 0x0}; 153 | bool onoff = true; 154 | 155 | #define NUM_OF_BANDS 13 156 | const uint32_t bands[][2] = 157 | { 158 | { 1800, 2000 }, // 160m 159 | { 3500, 4000 }, // 80m 160 | { 5351, 5367 }, // 60m 161 | { 7000, 7300 }, // 40m 162 | { 10100, 10150 }, // 30m 163 | { 14000, 14350 }, // 20m 164 | { 18068, 18168 }, // 17m 165 | { 21000, 21450 }, // 15m 166 | { 24890, 24990 }, // 12m 167 | { 28000, 29700 }, // 10m 168 | { 50000, 54000 }, // 6m 169 | { 144000,148000 }, // 2m 170 | { 430000,450000 } // UHF 171 | }; 172 | 173 | // ---------------------------------------- 174 | // Print the received frequency 175 | // ---------------------------------------- 176 | void printFrequency(const uint8_t freq[]) 177 | { 178 | frequency = 0; 179 | //FE FE E0 42 03 <00 00 58 45 01 10> FD ic-905 6byes on 10G+ bands 180 | //FE FE E0 42 03 <00 00 58 45 01> FD ic-820 and IC-705 5 bytes 181 | //FE FE 00 40 00 <00 60 06 14> FD ic-732 4 bytes 182 | for (uint8_t i = 0; i < 5; i++) { 183 | if (freq[9 - i] == 0xFD) continue; //spike 184 | frequency += (freq[9 - i] >> 4) * decMulti[i * 2]; 185 | frequency += (freq[9 - i] & 0x0F) * decMulti[i * 2 + 1]; 186 | } 187 | } 188 | 189 | // 190 | // formatVFO() 191 | // 192 | char* formatVFO(uint64_t vfo) 193 | { 194 | static char vfo_str[20] = {""}; 195 | //if (ModeOffset < -1 || ModeOffset > 1) 196 | //vfo += ModeOffset; // Account for pitch offset when in CW mode, not others 197 | 198 | uint32_t MHz = (vfo/1000000 % 1000000); 199 | uint16_t Hz = (vfo % 1000); 200 | uint16_t KHz = ((vfo % 1000000) - Hz)/1000; 201 | sprintf(vfo_str, "%lu.%03u.%03u", MHz, KHz, Hz); 202 | 203 | ///sprintf(vfo_str, "%-13s", "012345.123.123"); // 999GHZ max 47G = 47000.000.000 204 | ///DPRINT("New VFO: ");DPRINTLN(vfo_str); 205 | return vfo_str; 206 | } 207 | 208 | // The onDisconnect() callback functioun worked but am using pClient->isCOnnected() instead. 209 | // It also arrives asynchronously which has to be handled as such. Not using this now. 210 | // TO use these, uncomment the 211 | class MyClientCallback : public BLEClientCallbacks 212 | { 213 | void onConnect(BLEClient* pclient) { 214 | //doConnect = true; 215 | BLE_connected = true; // tracks state of BLE level connection 216 | Serial.println("Now Connected to BLE server"); 217 | } 218 | 219 | void onDisconnect(BLEClient* pclient) { 220 | connected = false; // tacks state of CIV connection 221 | doConnect = false; // gateway to connect and pair processes. 222 | BLE_connected = false; // tracks state of BLE level connection 223 | Name_confirm = Token_confirm = CIV_granted = false; // reset 224 | Serial.println("Lost BLE server connection event flag set on Disconnect "); 225 | //Scan_BLE_Servers(); 226 | } 227 | }; 228 | 229 | static void notifyCallback( 230 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 231 | uint8_t* pData, 232 | size_t length, 233 | bool isNotify) 234 | { 235 | //Serial.printf("Callback Notify value = \n",isNotify); 236 | //Serial.println("Notify callback for TX characteristic received. Data:"); 237 | for (int i = 0; i < length; i++) 238 | { 239 | // Serial.print((char)pData[i]); // Print character to uart 240 | #ifdef WATCH_SERIAL 241 | Serial.print(pData[i], HEX); // print raw data to uart 242 | Serial.print(","); 243 | #endif 244 | if (pData[i] == 0xFD) 245 | { 246 | #ifdef WATCH_SERIAL 247 | Serial.println(); 248 | #endif 249 | 250 | if (pData[1] == 0xF1 && pData[2] == 0x00) 251 | { 252 | switch (pData[3]) 253 | { 254 | case 0x61: 255 | Serial.println("Got BT_ADDR message confirmation, proceed"); 256 | BT_ADDR_confirm = true; 257 | break; 258 | case 0x62: 259 | Serial.println("Got NAME message confirmation, proceed"); 260 | Name_confirm = true; 261 | break; 262 | case 0x63: 263 | Serial.println("Got TOKEN message confirmation, proceed"); 264 | Token_confirm = true; 265 | if (pData[4] == 0x01) 266 | Pairing_Accepted = true; // Pairing action worked. Once pair this wil return 0 267 | break; 268 | case 0x64: 269 | Serial.println("CI-V bus ACCESS granted, proceed"); 270 | CIV_granted = true; 271 | connected = true; 272 | break; 273 | } 274 | } 275 | } 276 | } 277 | 278 | if (connected) 279 | { 280 | switch (pData[4]) 281 | { 282 | case 0x00: 283 | case 0x03: 284 | case 0x05: 285 | printFrequency(pData); // VFO frequency 286 | band = getBand(frequency/1000); 287 | break; 288 | case 0x1C: 289 | if (pData[5] == 0) // RX/TX state message 290 | PTT = pData[6]; 291 | break; 292 | default: break; 293 | } 294 | } 295 | } 296 | 297 | //************************************************************************************** 298 | // 299 | // Connect to Server 300 | // 301 | //************************************************************************************** 302 | bool connectToServer(BLEAddress pAddress) { 303 | Serial.print("Establishing a connection to device address: "); 304 | Serial.println(pAddress.toString().c_str()); 305 | 306 | pClient = BLEDevice::createClient(); 307 | //BLEClient* pClient = BLEDevice::createClient(); 308 | Serial.println(" - Created client"); 309 | 310 | // Connect to the remove BLE Server. 311 | pClient->connect(pAddress); 312 | Serial.println(" - Connected to server"); 313 | pClient->setMTU(517); //set client to request maximum MTU from 314 | //server (default is 23 otherwise) 315 | 316 | // Obtain a reference to the Nordic UART service on the remote BLE server. 317 | BLERemoteService* pRemoteService = pClient->getService(serviceUUID); 318 | if (pRemoteService == nullptr) { 319 | Serial.print("Failed to find Nordic UART service UUID: "); 320 | Serial.println(serviceUUID.toString().c_str()); 321 | pClient->disconnect(); 322 | return false; 323 | } 324 | Serial.print(" - Found our service "); 325 | //Serial.println(pClient->getPeerAddress()); 326 | 327 | // Obtain a reference to the TX characteristic of the Nordic UART service on the remote BLE server. 328 | pTXCharacteristic = pRemoteService->getCharacteristic(charUUID_TX); 329 | if (pTXCharacteristic == nullptr) { 330 | Serial.print("Failed to find TX characteristic UUID: "); 331 | Serial.println(charUUID_TX.toString().c_str()); 332 | pClient->disconnect(); 333 | return false; 334 | } 335 | Serial.println(" - Remote BLE TX characteristic reference established"); 336 | 337 | // Read the value of the TX characteristic. 338 | //if(pTXCharacteristic->canRead()) { 339 | std::string value = pTXCharacteristic->readValue(); 340 | Serial.print("The characteristic value is currently: "); 341 | Serial.println(value.c_str()); 342 | //} 343 | 344 | // Obtain a reference to the RX characteristic of the Nordic UART service on the remote BLE server. 345 | pRXCharacteristic = pRemoteService->getCharacteristic(charUUID_RX); 346 | if (pRXCharacteristic == nullptr) { 347 | Serial.print("Failed to find our characteristic UUID: "); 348 | Serial.println(charUUID_RX.toString().c_str()); 349 | return false; 350 | } 351 | Serial.println(" - Remote BLE RX characteristic reference established"); 352 | 353 | // Read the value of the characteristic. 354 | //if(pRXCharacteristic->canRead()) { 355 | value = pRXCharacteristic->readValue(); 356 | Serial.print("The characteristic value was: "); 357 | Serial.println(value.c_str()); 358 | //} 359 | 360 | if(pTXCharacteristic->canNotify()) 361 | pTXCharacteristic->registerForNotify(notifyCallback); 362 | 363 | // UUID is 32 bytes, msg is 41 total. Any less and the reply for the Name msg will be suppressed. Weird, probably a radio bug. 364 | pRXCharacteristic->writeValue(CIV_ID0, sizeof(CIV_ID0)); 365 | pRXCharacteristic->canNotify(); 366 | delay(20); 367 | 368 | // Device name must be 16 bytes exactly, msg total 21 bytes. 369 | pRXCharacteristic->writeValue(CIV_ID1, sizeof(CIV_ID1)); 370 | pRXCharacteristic->canNotify(); 371 | M5.delay(20); // a small delay was required or this message would be missed (collision likely). 372 | 373 | // Send Token - A fixed value 9 bytes long total. 374 | uint8_t CIV_ID2[] = {0xFE, 0xF1, 0x00, 0x63, 0xEE, 0x39, 0x09, 0x10, 0xFD}; // Send Token 375 | pRXCharacteristic->writeValue(CIV_ID2, 9); 376 | pRXCharacteristic->canNotify(); 377 | M5.delay(20); 378 | 379 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x62, 0xFD // no reply when reconnecting 380 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x01, 0xFD // pair confirmed 381 | // if already paired, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x00, 0xFD // already paired 382 | // if all good, will get reply with 0xFE, 0xF1, 0x00, 0x64, 0xFD // CI-V bus access granted 383 | 384 | //String helloValue = "Hello Remote Server"; 385 | //pRXCharacteristic->writeValue(helloValue.c_str(), helloValue.length()); 386 | 387 | //connected = true; 388 | return true; 389 | } 390 | 391 | void printDeviceAddress() { 392 | const uint8_t* point = esp_bt_dev_get_address(); 393 | 394 | for (int i = 0; i < 6; i++) { 395 | char str[3]; 396 | 397 | sprintf(str, "%02X", (int)point[i]); 398 | Serial.print(str); 399 | 400 | if (i < 5){ 401 | Serial.print(":"); 402 | } 403 | } 404 | Serial.println(""); 405 | } 406 | 407 | /************************************************************************************** 408 | Scan for BLE servers and find the first one that advertises the Nordic UART service. 409 | ***************************************************************************************/ 410 | class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { 411 | /** 412 | Called for each advertising BLE server. 413 | */ 414 | void onResult(BLEAdvertisedDevice advertisedDevice) { 415 | Serial.print("BLE Advertised Device found - "); 416 | Serial.println(advertisedDevice.toString().c_str()); 417 | 418 | // We have found a device, check to see if it contains the Nordic UART service. 419 | if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { 420 | 421 | Serial.println("Found a device with the desired ServiceUUID!"); 422 | advertisedDevice.getScan()->stop(); 423 | 424 | pServerAddress = new BLEAddress(advertisedDevice.getAddress()); 425 | doConnect = true; // Trigger to process server connection 426 | 427 | } // Found our server 428 | } // onResult 429 | }; // MyAdvertisedDeviceCallbacks 430 | 431 | void Scan_BLE_Servers(void) 432 | { 433 | // Retrieve a Scanner and set the callback we want to use to be informed when we 434 | // have detected a new device. Specify that we want active scanning and start the 435 | // scan to run for 30 seconds 436 | BLEScan* pBLEScan = BLEDevice::getScan(); 437 | pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); 438 | pBLEScan->setInterval(1349); 439 | pBLEScan->setWindow(449); // less or equal setInterval value 440 | pBLEScan->setActiveScan(true); 441 | BLEScanResults foundDevices = pBLEScan->start(scanTime, false); 442 | ////pBLEScan->start(scanTime, false); 443 | Serial.print("Devices found: "); Serial.println(foundDevices.getCount()); 444 | Serial.println("Scan done!"); 445 | pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory 446 | } 447 | 448 | // ---------------------------------------- 449 | // get band from frequency 450 | // ---------------------------------------- 451 | byte getBand(uint32_t freq) 452 | { 453 | for(uint8_t i=0; i= bands[i][0] && freq <= bands[i][1] ) { 455 | if(i==NUM_OF_BANDS) return NUM_OF_BANDS; // T1 tuner does not have different settings for 2m and UHF 456 | return i+1; 457 | } 458 | } 459 | return 0xFF; // no band for considered frequency found 460 | } 461 | 462 | void display_PTT(uint8_t PTT_state) 463 | { 464 | static uint8_t prev_PTT_state = 1; 465 | char PTT_Tx[] = " Tx "; 466 | char PTT_Rx[] = " Rx "; 467 | 468 | if (PTT_state != prev_PTT_state) 469 | { 470 | Serial.print("*** PTT = ");Serial.println(PTT_state); 471 | 472 | M5.Lcd.setTextSize(3); // to Set the size of text from 0 to 255 473 | M5.Lcd.setCursor(230, 190); //Set the location of the cursor to the coordinates X and Y 474 | if (prev_PTT_state) 475 | { 476 | M5.Lcd.setTextColor(LIGHTGREY, BLACK); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 477 | M5.Lcd.printf("%s", PTT_Tx); 478 | } 479 | else 480 | { 481 | M5.Lcd.setTextColor(WHITE, RED); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 482 | M5.Lcd.printf("%s", PTT_Rx); 483 | } 484 | 485 | M5.Lcd.setCursor(230, 190); //Set the location of the cursor to the coordinates X and Y 486 | if (PTT_state) 487 | { 488 | M5.Lcd.setTextColor(WHITE, RED); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 489 | M5.Lcd.printf("%s", PTT_Tx); 490 | } 491 | else 492 | { 493 | M5.Lcd.setTextColor(LIGHTGREY, BLACK); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 494 | M5.Lcd.printf("%s", PTT_Rx); 495 | } 496 | prev_PTT_state = PTT_state; 497 | } 498 | } 499 | 500 | void display_Band(uint8_t _band) 501 | { 502 | static uint8_t prev_band = 255; 503 | 504 | if (_band != prev_band) 505 | { 506 | Serial.printf("Band %d\n", band); 507 | 508 | //sendBand(band); // change the IO pins to match band 509 | M5.Lcd.setTextColor(background_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 510 | M5.Lcd.setCursor(80, 120); //Set the location of the cursor to the coordinates X and Y 511 | M5.Lcd.printf("Band: %3d", prev_band); 512 | 513 | M5.Lcd.setTextColor(CYAN); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 514 | M5.Lcd.setCursor(80, 120); //Set the location of the cursor to the coordinates X and Y 515 | M5.Lcd.printf("Band: %3d", band); 516 | prev_band = _band; 517 | } 518 | } 519 | 520 | void display_Freq(uint64_t freq) 521 | { 522 | static uint64_t prev_freq; 523 | if (freq != prev_freq) 524 | { 525 | Serial.printf("VFOA: %13sMHz - Band: %d\n", formatVFO(freq), band); 526 | 527 | M5.Lcd.setTextSize(3); // to Set the size of text from 0 to 255 528 | 529 | M5.Lcd.setTextColor(background_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 530 | M5.Lcd.setCursor(20, 80); //Set the location of the cursor to the coordinates X and Y 531 | M5.Lcd.printf( "%13sMHz", formatVFO(prev_freq)); 532 | 533 | M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 534 | M5.Lcd.setCursor(20, 80); //Set the location of the cursor to the coordinates X and Y 535 | M5.Lcd.printf( "%13sMHz", formatVFO(freq)); 536 | 537 | prev_freq = freq; 538 | } 539 | } 540 | 541 | //-------------------------------------------- // 542 | // BLE 543 | // SendMessage by BLE Slow in packets of 20 chars 544 | // or fast in one long string. 545 | // Fast can be used in IOS app BLESerial Pro 546 | //------------------------------ 547 | void SendMessageBLE(std::string Message) 548 | { 549 | if(connected) 550 | { 551 | if (1) 552 | //if (Mem.UseBLELongString) // If Fast transmission is possible 553 | { 554 | pRXCharacteristic->writeValue(Message.c_str()); 555 | pRXCharacteristic->canNotify(); 556 | delay(10); // Bluetooth stack will go into congestion, if too many packets are sent 557 | } 558 | else // Packets of max 20 bytes 559 | { 560 | int parts = (Message.length()/20) + 1; 561 | for(int n=0;nwriteValue(Message.substr(n*20, 20).c_str()); 564 | pRXCharacteristic->canNotify(); 565 | delay(40); // Bluetooth stack will go into congestion, if too many packets are sent 566 | } 567 | } 568 | } 569 | } 570 | 571 | void draw_initial_screen(void) 572 | { 573 | M5.Lcd.fillScreen(background_color); 574 | M5.Lcd.setTextSize(2); // to Set the size of text from 0 to 255 575 | M5.Lcd.setCursor(20, 30); //Set the location of the cursor to the coordinates X and Y 576 | M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 577 | M5.Lcd.printf("IC-705 BLE Band Decoder"); 578 | 579 | M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 580 | M5.Lcd.setCursor(5, 80); //Set the location of the cursor to the coordinates X and Y 581 | M5.Lcd.printf("Connected to CI-V"); 582 | 583 | delay(1000); 584 | 585 | M5.Lcd.fillScreen(background_color); 586 | M5.Lcd.setTextSize(2); // to Set the size of text from 0 to 255 587 | M5.Lcd.setCursor(20, 30); //Set the location of the cursor to the coordinates X and Y 588 | M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 589 | M5.Lcd.printf("IC-705 BLE Band Decoder"); 590 | } 591 | 592 | void Mod_4in8out(void) 593 | { 594 | //M5.Lcd.drawString("4IN8OUT MODULE", 60, 80, 4); 595 | //M5.Lcd.drawString("FW VERSION:" + String(module.getVersion()), 70, 120, 4); 596 | //M5.Lcd.drawString("Click BtnB Update Addr to 0x66", 60, 160, 2); 597 | if (M5.BtnB.wasPressed()) { 598 | //if (module.setDeviceAddr(0x66)) { 599 | // Serial.println("Update Addr: 0x66"); 600 | Serial.println("BtnB pressed"); 601 | // M5.Lcd.drawString("Update Addr: 0x66 success", 60, 200, 2); 602 | //} 603 | } 604 | } 605 | 606 | void setup() 607 | { 608 | M5.begin(); 609 | Serial.begin(115200); 610 | 611 | #ifdef MOD_4IN_8OUT 612 | while (!module.begin(&Wire1, 12, 11, MODULE_4IN8OUT_ADDR)) 613 | { 614 | Serial.println("4IN8OUT INIT ERROR"); 615 | M5.Lcd.setTextSize(1); // to Set the size of text from 0 to 255 616 | M5.Lcd.println("4IN8OUT INIT ERROR"); 617 | delay(1000); 618 | }; 619 | Serial.println("4IN8OUT INIT SUCCESS"); 620 | #endif 621 | 622 | #ifdef M5BTNS 623 | unifiedButton.begin(&M5.Display); 624 | #endif 625 | 626 | Serial.println("Starting Arduino BLE Central Mode (Client) Nordic UART Service"); 627 | 628 | M5.Lcd.fillScreen(background_color); 629 | M5.Lcd.setTextSize(2); // to Set the size of text from 0 to 255 630 | M5.Lcd.setCursor(20, 30); //Set the location of the cursor to the coordinates X and Y 631 | M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 632 | M5.Lcd.printf("IC-705 BLE Band Decoder"); 633 | 634 | BLEDevice::init(""); 635 | doConnect = false; 636 | Scan_BLE_Servers(); 637 | } // End of setup. 638 | 639 | void loop() { 640 | 641 | static uint32_t time_freq = 0; 642 | static uint32_t time_tx = 0; 643 | 644 | M5.update(); 645 | 646 | #ifdef M5BTNS 647 | check_M5Buttons(); 648 | #endif 649 | 650 | #ifdef MOD_4IN_8OUT 651 | Mod_4in8out(); 652 | #endif 653 | 654 | M5.Lcd.setTextSize(2); // to Set the size of text from 0 to 255 655 | 656 | // If the flag "doConnect" is true then we have scanned for and found the desired 657 | // BLE Server with which we wish to connect. Now we connect to it. Once we are 658 | // connected we set the connected flag to be true. 659 | if (doConnect == true) 660 | { 661 | if (connectToServer(*pServerAddress)) 662 | { 663 | Serial.println("We are now connected to the BLE Server."); 664 | // should have CIV results by now, see if we have access to the CI-V bus or not 665 | Serial.printf("doConnect1 - post CIV_Connect - connected = %d Token = %d CIV_Granted = %d BLE_connected = %d\n", connected, Token_confirm, CIV_granted, BLE_connected); 666 | 667 | if (Token_confirm) 668 | BLE_connected = true; // tracks BLE layer sta 669 | 670 | if (Pairing_Accepted && Token_confirm) 671 | Serial.println("Pairing_Accepted"); // only get this whe a pairing is request. false on regular sign in 672 | 673 | if (!Pairing_Accepted && Token_confirm) // continue on 674 | Serial.println("Paired already, continue to sign in"); 675 | 676 | if (BLE_connected && CIV_granted) 677 | { 678 | connected = true; // tracks CIV layer state can be connected to BLE but not CIV (not paired for example) 679 | draw_initial_screen(); 680 | } 681 | } 682 | else 683 | { 684 | Serial.println("We have failed to connect to the server; there is nothin more we will do."); 685 | draw_initial_screen(); 686 | M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 687 | M5.Lcd.setCursor(5, 80); //Set the location of the cursor to the coordinates X and Y 688 | M5.Lcd.printf("Failed Connection to Radio"); 689 | connected = false; 690 | } 691 | doConnect = false; 692 | } 693 | 694 | if (pClient != nullptr && !pClient->isConnected()) 695 | { 696 | if (BLE_connected) 697 | Serial.println("BLE not connected to radio"); // detect if we are not connected 698 | delay(100); 699 | connected = false; 700 | BLE_connected = false; 701 | } 702 | else 703 | BLE_connected = true; 704 | 705 | if(connected) 706 | { 707 | onoff = 1; // want to read from the radio 708 | // Can toggle notifications for the TX Characteristic on and off. 709 | // Update the RX characteristic with the current time since boot string. 710 | if (onoff) { 711 | //Serial.println("Notifications turned on"); 712 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); 713 | } else { 714 | //Serial.println("Notifications turned off"); 715 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOff, 2, true); 716 | } 717 | 718 | // Toggle on/off value for notifications. 719 | //onoff = onoff ? 0 : 1; 720 | 721 | 722 | if (millis() >= time_freq + POLL_FREQ) // poll every X ms 723 | { 724 | //Serial.println("Poll radio"); 725 | uint8_t CIV_frequency[] = {0xFE, 0xFE, radio_address, 0xE0, 0x03, 0xFD}; 726 | pRXCharacteristic->writeValue(CIV_frequency, sizeof(CIV_frequency), true); 727 | pRXCharacteristic->canNotify(); 728 | delay(10); 729 | time_freq = millis(); 730 | } 731 | 732 | if (millis() >= time_tx + POLL_TX) // poll every X ms 733 | { 734 | //Serial.println("Poll radio for TX/RX state"); 735 | uint8_t CIV_TX[] = {0xFE, 0xFE, radio_address, 0xE0, 0x1C, 0x00, 0xFD}; 736 | pRXCharacteristic->writeValue(CIV_TX, sizeof(CIV_TX), true); 737 | pRXCharacteristic->canNotify(); 738 | //delay(10); 739 | time_tx = millis(); 740 | } 741 | 742 | //SendMessageBLE(CIV_frequency); 743 | //pRXCharacteristic->writeValue(timeSinceBoot.c_str(), timeSinceBoot.length()); 744 | //pRXCharacteristic->canNotify(); 745 | 746 | // Update the M5 screen 747 | display_Freq(frequency); 748 | display_PTT(PTT); 749 | display_Band(band); 750 | 751 | }// if connected 752 | else 753 | { 754 | Scan_BLE_Servers(); 755 | } 756 | 757 | delay(1); // Delay five seconds between loops. 758 | } // End of loop 759 | -------------------------------------------------------------------------------- /Archive/IC705_ESP32_BLE_client_uart/IC705_ESP32_BLE_client_uart.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * IC705_ESP32_BLE_client_uart.ino 3 | * 4 | * Central Mode (client) BLE UART for ESP32 - Tested on CoreS3 SE 5 | * 6 | * Modifed by K7MDL Aug 4, 2024 for BT connection to the IC-705 via BLE serial on a M5Stack Core3 and Core 3 SE. Tested on a SE version 7 | * 8 | * This is a simplified example program showing a BLE connection to an IC-705 and getting CI-V frequency and PTT state. 9 | * All UI is on the serial terminal only. Other example programs on this repo show info on the display, process button touches 10 | * Go to the IC-705 Pairing Reception menu 11 | * Reset the M5Stack Core3 12 | * It will autoconnect and display the name in the Pairing/Connect menu 13 | * If a connection is lost, you must reset to reconnect, there is no live scan and reconnect in this version. 14 | * See the other more advanced programs for auto-reconnect upon connection loss. 15 | * 16 | * NOTE: This version only takes one BLE server scan. Sometimes it needs more passes. 17 | * If you do not see a connection reset again, it was probably missed, or not in the pairing screen. 18 | * 19 | ******************************** Below is the original code header/credits ************************************************** 20 | * 21 | * This sketch is a central mode (client) Nordic UART Service (NUS) that connects automatically to a peripheral (server) 22 | * Nordic UART Service. NUS is what most typical "blueart" servers emulate. This sketch will connect to your BLE uart 23 | * device in the same manner the nRF Connect app does. 24 | * 25 | * Once connected this sketch will switch notification on using BLE2902 for the charUUID_TX characteristic which is the 26 | * characteristic that our server is making data available on via notification. The data received from the server 27 | * characteristic charUUID_TX will be printed to Serial on this device. Every five seconds this device will send the 28 | * string "Time since boot: #" to the server characteristic charUUID_RX, this will make that data available in the BLE 29 | * uart and trigger a notifyCallback or similar depending on your BLE uart server setup. 30 | * 31 | * 32 | * A brief explanation of BLE client/server actions and rolls: 33 | * 34 | * Central Mode (client) - Connects to a peripheral (server). 35 | * -Scans for devices and reads service UUID. 36 | * -Connects to a server's address with the desired service UUID. 37 | * -Checks for and makes a reference to one or more characteristic UUID in the current service. 38 | * -The client can send data to the server by writing to this RX Characteristic. 39 | * -If the client has enabled notifications for the TX characteristic, the server can send data to the client as 40 | * notifications to that characteristic. This will trigger the notifyCallback function. 41 | * 42 | * Peripheral (server) - Accepts connections from a central mode device (client). 43 | * -Advertises a service UUID. 44 | * -Creates one or more characteristic for the advertised service UUID 45 | * -Accepts connections from a client. 46 | * -The server can send data to the client by writing to this TX Characteristic. 47 | * -If the server has enabled notifications for the RX characteristic, the client can send data to the server as 48 | * notifications to that characteristic. This the default function on most "Nordic UART Service" BLE uart sketches. 49 | * 50 | * 51 | * Copyright <2018> 52 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 53 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 54 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 55 | * permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright 56 | * notice and this permission notice shall be included in all copies or substantial portions of the Software. THE 57 | * SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 58 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 59 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 60 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | * 62 | * 63 | * Based on the "BLE_Client" example by Neil Kolban: 64 | * https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino 65 | * With help from an example by Andreas Spiess: 66 | * https://github.com/SensorsIot/Bluetooth-BLE-on-Arduino-IDE/blob/master/Polar_Receiver/Polar_Receiver.ino 67 | * Nordic UART Service info: 68 | * https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fble_sdk_app_nus_eval.html 69 | * 70 | */ 71 | 72 | 73 | #include "BLEDevice.h" 74 | #include "esp_bt_main.h" 75 | #include "esp_bt_device.h" 76 | 77 | 78 | // The remote Nordic UART service service we wish to connect to. 79 | // This service exposes two characteristics: one for transmitting and one for receiving (as seen from the client). 80 | static BLEUUID serviceUUID("14cf8001-1ec2-d408-1b04-2eb270f14203"); 81 | 82 | // The characteristics of the above service we are interested in. 83 | // The client can send data to the server by writing to this characteristic. 84 | static BLEUUID charUUID_RX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // RX Characteristic 85 | 86 | // If the client has enabled notifications for this characteristic, 87 | // the server can send data to the client as notifications. 88 | static BLEUUID charUUID_TX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // TX Characteristic 89 | 90 | static BLEAddress *pServerAddress; 91 | static boolean doConnect = false; 92 | static boolean connected = false; 93 | static BLERemoteCharacteristic* pTXCharacteristic; 94 | static BLERemoteCharacteristic* pRXCharacteristic; 95 | uint8_t radio_address = 0xA4; // A4 for IC-705, AC for IC-905 96 | 97 | 98 | static void notifyCallback( 99 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 100 | uint8_t* pData, 101 | size_t length, 102 | bool isNotify) { 103 | //Serial.println("Notify callback for TX characteristic received. Data:"); 104 | for (int i = 0; i < length; i++) { 105 | // Serial.print((char)pData[i]); // Print character to uart 106 | Serial.print(pData[i], HEX); // print raw data to uart 107 | Serial.print(" "); 108 | if (pData[i] == 0xFD) 109 | Serial.println(); 110 | } 111 | } 112 | 113 | bool connectToServer(BLEAddress pAddress) { 114 | Serial.print("Establishing a connection to device address: "); 115 | Serial.println(pAddress.toString().c_str()); 116 | 117 | BLEClient* pClient = BLEDevice::createClient(); 118 | Serial.println(" - Created client"); 119 | 120 | // Connect to the remove BLE Server. 121 | pClient->connect(pAddress); 122 | Serial.println(" - Connected to server"); 123 | pClient->setMTU(517); //set client to request maximum MTU from 124 | //server (default is 23 otherwise) 125 | 126 | // Obtain a reference to the Nordic UART service on the remote BLE server. 127 | BLERemoteService* pRemoteService = pClient->getService(serviceUUID); 128 | if (pRemoteService == nullptr) { 129 | Serial.print("Failed to find Nordic UART service UUID: "); 130 | Serial.println(serviceUUID.toString().c_str()); 131 | pClient->disconnect(); 132 | return false; 133 | } 134 | Serial.print(" - Found our service "); 135 | //Serial.println(pClient->getPeerAddress()); 136 | 137 | // Obtain a reference to the TX characteristic of the Nordic UART service on the remote BLE server. 138 | pTXCharacteristic = pRemoteService->getCharacteristic(charUUID_TX); 139 | if (pTXCharacteristic == nullptr) { 140 | Serial.print("Failed to find TX characteristic UUID: "); 141 | Serial.println(charUUID_TX.toString().c_str()); 142 | pClient->disconnect(); 143 | return false; 144 | } 145 | Serial.println(" - Remote BLE TX characteristic reference established"); 146 | 147 | // Read the value of the TX characteristic. 148 | //if(pTXCharacteristic->canRead()) { 149 | std::string value = pTXCharacteristic->readValue(); 150 | Serial.print("The characteristic value is currently: "); 151 | Serial.println(value.c_str()); 152 | //} 153 | 154 | // Obtain a reference to the RX characteristic of the Nordic UART service on the remote BLE server. 155 | pRXCharacteristic = pRemoteService->getCharacteristic(charUUID_RX); 156 | if (pRXCharacteristic == nullptr) { 157 | Serial.print("Failed to find our characteristic UUID: "); 158 | Serial.println(charUUID_RX.toString().c_str()); 159 | return false; 160 | } 161 | Serial.println(" - Remote BLE RX characteristic reference established"); 162 | 163 | // Read the value of the characteristic. 164 | //if(pRXCharacteristic->canRead()) { 165 | value = pRXCharacteristic->readValue(); 166 | Serial.print("The characteristic value was: "); 167 | Serial.println(value.c_str()); 168 | //} 169 | 170 | if(pTXCharacteristic->canNotify()) 171 | pTXCharacteristic->registerForNotify(notifyCallback); 172 | 173 | // For tesating I hard codeded the pairing messages to the IC-705! 174 | 175 | 176 | uint8_t CIV_ID0[] = {0xFE,0xF1,0x00,0x61,0x30,0x30,0x30,0x30,0x31,0x31,0x30,0x31,0x2D,0x30,0x30,0x30,0x30,0x2D,0x31,0x30,0x30,0x30,0x2D,0x38,0x30,0x30,0x30,0x2D,0x30,0x30,0x38,0x30,0x35,0x46,0x39,0x42,0x33,0x34,0x46,0x42,0xFD}; // Send our UUID 177 | pRXCharacteristic->writeValue(CIV_ID0, sizeof(CIV_ID0)); 178 | pRXCharacteristic->canNotify(); 179 | delay(20); 180 | 181 | // name is "IC705 BT Decoder" 182 | uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x42, 0x54, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0xFD}; // Send Name 183 | pRXCharacteristic->writeValue(CIV_ID1, sizeof(CIV_ID1)); 184 | pRXCharacteristic->canNotify(); 185 | delay(20); // a small delay was required or this message would be missed (collision likely). 186 | 187 | // Send Token 188 | uint8_t CIV_ID2[] = {0xFE, 0xF1, 0x00, 0x63, 0xEE, 0x39, 0x09, 0x10, 0xFD}; // Send Token 189 | pRXCharacteristic->writeValue(CIV_ID2, 9); 190 | pRXCharacteristic->canNotify(); 191 | delay(20); 192 | 193 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x62, 0xFD 194 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x01, 0xFD // pair confirmed 195 | // if already paired, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x00, 0xFD // already paired 196 | // if all good, will get reply with 0xFE, 0xF1, 0x00, 0x64, 0xFD // CI-V bus access granted 197 | 198 | //String helloValue = "Hello Remote Server"; 199 | //pRXCharacteristic->writeValue(helloValue.c_str(), helloValue.length()); 200 | 201 | connected = true; 202 | return true; 203 | } 204 | 205 | void printDeviceAddress() { 206 | const uint8_t* point = esp_bt_dev_get_address(); 207 | 208 | for (int i = 0; i < 6; i++) { 209 | char str[3]; 210 | 211 | sprintf(str, "%02X", (int)point[i]); 212 | Serial.print(str); 213 | 214 | if (i < 5){ 215 | Serial.print(":"); 216 | } 217 | } 218 | Serial.println(""); 219 | } 220 | 221 | /** 222 | Scan for BLE servers and find the first one that advertises the Nordic UART service. 223 | */ 224 | class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { 225 | /** 226 | Called for each advertising BLE server. 227 | */ 228 | void onResult(BLEAdvertisedDevice advertisedDevice) { 229 | Serial.print("BLE Advertised Device found - "); 230 | Serial.println(advertisedDevice.toString().c_str()); 231 | 232 | // We have found a device, check to see if it contains the Nordic UART service. 233 | if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { 234 | 235 | Serial.println("Found a device with the desired ServiceUUID!"); 236 | advertisedDevice.getScan()->stop(); 237 | 238 | pServerAddress = new BLEAddress(advertisedDevice.getAddress()); 239 | doConnect = true; 240 | 241 | } // Found our server 242 | } // onResult 243 | }; // MyAdvertisedDeviceCallbacks 244 | 245 | 246 | void setup() { 247 | Serial.begin(115200); 248 | Serial.println("Starting Arduino BLE Central Mode (Client) Nordic UART Service"); 249 | 250 | BLEDevice::init(""); 251 | 252 | // Retrieve a Scanner and set the callback we want to use to be informed when we 253 | // have detected a new device. Specify that we want active scanning and start the 254 | // scan to run for 30 seconds. 255 | BLEScan* pBLEScan = BLEDevice::getScan(); 256 | pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); 257 | pBLEScan->setActiveScan(true); 258 | //pBLEScan->start(30); 259 | BLEScanResults foundDevices = pBLEScan->start(5, false); 260 | Serial.print("Devices found: "); 261 | Serial.println(foundDevices.getCount()); 262 | Serial.println("Scan done!"); 263 | } // End of setup. 264 | 265 | 266 | const uint8_t notificationOff[] = {0x0, 0x0}; 267 | const uint8_t notificationOn[] = {0x1, 0x0}; 268 | bool onoff = true; 269 | 270 | void loop() { 271 | 272 | // If the flag "doConnect" is true then we have scanned for and found the desired 273 | // BLE Server with which we wish to connect. Now we connect to it. Once we are 274 | // connected we set the connected flag to be true. 275 | if (doConnect == true) { 276 | if (connectToServer(*pServerAddress)) { 277 | Serial.println("We are now connected to the BLE Server."); 278 | connected = true; 279 | } else { 280 | Serial.println("We have failed to connect to the server; there is nothin more we will do."); 281 | } 282 | doConnect = false; 283 | } 284 | 285 | onoff = 1; // want to read from the radio 286 | // Can toggle notifications for the TX Characteristic on and off. 287 | // Update the RX characteristic with the current time since boot string. 288 | if (connected) { 289 | if (onoff) { 290 | //Serial.println("Notifications turned on"); 291 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); 292 | } else { 293 | //Serial.println("Notifications turned off"); 294 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOff, 2, true); 295 | } 296 | 297 | // Toggle on/off value for notifications. 298 | //onoff = onoff ? 0 : 1; 299 | 300 | 301 | //Serial.println("Poll radio"); 302 | // uncomment this if you have BT CIV echo back turned off 303 | uint8_t CIV_frequency[] = {0xFE, 0xFE, radio_address, 0xE0, 0x03, 0xFD}; 304 | pRXCharacteristic->writeValue(CIV_frequency, sizeof(CIV_frequency)); 305 | pRXCharacteristic->canNotify(); 306 | delay(20); 307 | 308 | //Serial.println("Poll radio for TX/RX state"); 309 | uint8_t CIV_TX[] = {0xFE, 0xFE, radio_address, 0xE0, 0x1C, 0x00, 0xFD}; 310 | pRXCharacteristic->writeValue(CIV_TX, sizeof(CIV_TX)); 311 | pRXCharacteristic->canNotify(); 312 | } 313 | 314 | delay(100); // Delay five seconds between loops. 315 | } // End of loop 316 | 317 | 318 | //-------------------------------------------- // 319 | // BLE 320 | // SendMessage by BLE Slow in packets of 20 chars 321 | // or fast in one long string. 322 | // Fast can be used in IOS app BLESerial Pro 323 | //------------------------------ 324 | void SendMessageBLE(std::string Message) 325 | { 326 | if(connected) 327 | { 328 | if (1) 329 | //if (Mem.UseBLELongString) // If Fast transmission is possible 330 | { 331 | pRXCharacteristic->writeValue(Message.c_str()); 332 | pRXCharacteristic->canNotify(); 333 | delay(10); // Bluetooth stack will go into congestion, if too many packets are sent 334 | } 335 | else // Packets of max 20 bytes 336 | { 337 | int parts = (Message.length()/20) + 1; 338 | for(int n=0;nwriteValue(Message.substr(n*20, 20).c_str()); 341 | pRXCharacteristic->canNotify(); 342 | delay(40); // Bluetooth stack will go into congestion, if too many packets are sent 343 | } 344 | } 345 | } 346 | } 347 | 348 | -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/BLE.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * IC705_BLE_Decoder_Simple.ino 3 | * 4 | * Central Mode (client) BLE UART for ESP32 - Tested on CoreS3 SE 5 | * 6 | * Modifed by K7MDL Aug 2024 for BLE Serial port (uart) connection to the IC-705 via BLE serial on a M5Stack Core3 and Core 3 SE. Tested on a SE version 7 | * 8 | * This is a simplified example program showing a BLE connection to an IC-705 and getting CI-V frequency and PTT state. 9 | * The UI is simply a title, frequency, band number, and PTT status, with PTT (Rx/Tx) turning red during Tx. 10 | * Future example programs could show more info on the display, process button touches, and have configurable band decoder outputs 11 | * 12 | *********************************************** Usage ************************************************************************* 13 | * 14 | * To use: 15 | * 1. On the IC-705 press menu 16 | * 2. Navigate to to Set -> Bluetooth Set -> <> 17 | * 3. The device will pair silently with the radio and display the given name in the Pairing Connect page. 18 | * 19 | * Once paired it will auto-reconnect as long as it is paired with the radio. 20 | * The name shown in the Pairing/Connect menu is hard coded today. See below byte arrays to edit. 21 | * 22 | ******************************** Below is the original code header/credits ************************************************** 23 | * 24 | * This sketch is a central mode (client) Nordic UART Service (NUS) that connects automatically to a peripheral (server) 25 | * Nordic UART Service. NUS is what most typical "blueart" servers emulate. This sketch will connect to your BLE uart 26 | * device in the same manner the nRF Connect app does. 27 | * 28 | * Once connected this sketch will switch notification on using BLE2902 for the charUUID_TX characteristic which is the 29 | * characteristic that our server is making data available on via notification. The data received from the server 30 | * characteristic charUUID_TX will be printed to Serial on this device. Every five seconds this device will send the 31 | * string "Time since boot: #" to the server characteristic charUUID_RX, this will make that data available in the BLE 32 | * uart and trigger a notifyCallback or similar depending on your BLE uart server setup. 33 | * 34 | * 35 | * A brief explanation of BLE client/server actions and rolls: 36 | * 37 | * Central Mode (client) - Connects to a peripheral (server). 38 | * -Scans for devices and reads service UUID. 39 | * -Connects to a server's address with the desired service UUID. 40 | * -Checks for and makes a reference to one or more characteristic UUID in the current service. 41 | * -The client can send data to the server by writing to this RX Characteristic. 42 | * -If the client has enabled notifications for the TX characteristic, the server can send data to the client as 43 | * notifications to that characteristic. This will trigger the notifyCallback function. 44 | * 45 | * Peripheral (server) - Accepts connections from a central mode device (client). 46 | * -Advertises a service UUID. 47 | * -Creates one or more characteristic for the advertised service UUID 48 | * -Accepts connections from a client. 49 | * -The server can send data to the client by writing to this TX Characteristic. 50 | * -If the server has enabled notifications for the RX characteristic, the client can send data to the server as 51 | * notifications to that characteristic. This the default function on most "Nordic UART Service" BLE uart sketches. 52 | * 53 | * 54 | * Copyright <2018> 55 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 56 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 57 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 58 | * permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright 59 | * notice and this permission notice shall be included in all copies or substantial portions of the Software. THE 60 | * SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 61 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 62 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 63 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 | * 65 | * 66 | * Based on the "BLE_Client" example by Neil Kolban: 67 | * https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino 68 | * With help from an example by Andreas Spiess: 69 | * https://github.com/SensorsIot/Bluetooth-BLE-on-Arduino-IDE/blob/master/Polar_Receiver/Polar_Receiver.ino 70 | * Nordic UART Service info: 71 | * https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fble_sdk_app_nus_eval.html 72 | * 73 | */ 74 | #ifndef BLE_ 75 | #define BLE_ 76 | 77 | #include "BLEDevice.h" 78 | #include "esp_bt_main.h" 79 | #include "esp_bt_device.h" 80 | #include "BLEScan.h" 81 | #include "CIV.h" 82 | //#include "M5Stack_CI-V_Band_Decoder.h" 83 | #include "sdkconfig.h" 84 | #if defined(CONFIG_BLUEDROID_ENABLED) 85 | #include 86 | #include 87 | #include "BLEAdvertisedDevice.h" 88 | #include "BLEClient.h" 89 | #include "RTOS.h" 90 | #include "M5StampC3U_Decoder.h" 91 | #include "BLE.h" 92 | //#include "BLEAddress.h" 93 | 94 | // The remote Nordic UART service service we wish to connect to. 95 | // This service exposes two characteristics: one for transmitting and one for receiving (as seen from the client). 96 | static BLEUUID serviceUUID("14cf8001-1ec2-d408-1b04-2eb270f14203"); 97 | 98 | // The characteristics of the above service we are interested in. 99 | // The client can send data to the server by writing to this characteristic. 100 | static BLEUUID charUUID_RX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // RX Characteristic 101 | 102 | // If the client has enabled notifications for this characteristic, 103 | // the server can send data to the client as notifications. 104 | static BLEUUID charUUID_TX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // TX Characteristic 105 | 106 | // For testing I hard coded the pairing messages to the IC-705! 107 | 108 | // UUID, 41 bytes total. Any less and will not get a reply from the Name msg 0x42. It is too generated nunmber which iodeally should be unique on each device 109 | // The radio uses the combination of UUID and Name to identity each device paired. 110 | // Here is a generated UUID from https://www.uuidgenerator.net/version4 111 | // 56a56730- e8bc- 4930- 81b6- ef33e973842b 112 | uint8_t CIV_ID0[] = {0xFE,0xF1,0x00,0x61, 0x35,0x36,0x41,0x35,0x36,0x37,0x33,0x30,0x2D, 0x45,0x38,0x42,0x43,0x2D, 0x34,0x39,0x30,0x30,0x2D, 0x38,0x31,0x42,0x36,0x2D, 0x45,0x46,0x33,0x33,0x45,0x39,0x37,0x33,0x38,0x34,0x32,0x42,0xFD}; // Send our UUID 113 | 114 | // name is "IC705 Decoder 04" 21 bytes total - YOu can change this but teh name must be exactly 16 bytes. Can pad with spaces 115 | uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0x2D, 0x30, 0x34, 0xFD}; // Send Name 116 | // name is "IC705 BT Decoder" 117 | // uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x42, 0x54, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0xFD}; // Send Name 118 | 119 | // ToDo: Make configurable the target radio's service and characteristic UUIDs. Only needed if future radios use differenmt UUIDs. 120 | // The RX and Tx UUIDs are the same number. Unlike most devices, the CI-V bus is not full duplex, 121 | // they share the same wire for Rx and TX and so it goes for the digital wire here. 122 | 123 | 124 | int scanTime = 5; //In seconds 125 | static BLEScan *pBLEScan = NULL; 126 | static BLEClient *pClient = NULL; 127 | static BLEAddress *pServerAddress = NULL; 128 | //static boolean doConnect = false; 129 | static bool connected = false; 130 | static BLERemoteCharacteristic* pTXCharacteristic; 131 | static BLERemoteCharacteristic* pRXCharacteristic; 132 | //const uint32_t decMulti[] = {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1}; 133 | static bool BT_ADDR_confirm = false; 134 | static bool Name_confirm = false; 135 | static bool Token_confirm = false; 136 | static bool Pairing_Accepted = false; 137 | static bool CIV_granted = false; 138 | extern bool BLE_connected; 139 | const uint8_t notificationOff[] = {0x0, 0x0}; 140 | const uint8_t notificationOn[] = {0x1, 0x0}; 141 | bool onoff = true; 142 | extern uint8_t band; 143 | extern uint8_t PTT; 144 | extern uint8_t radio_address; 145 | extern bool XVTR_enabled; 146 | extern uint8_t XVTR_Band; 147 | //extern byte getBand(uint64_t _freq); 148 | //extern struct Bands bands[]; 149 | //extern uint64_t frequency; 150 | extern uint8_t read_buffer[]; //Read buffer 151 | extern bool BLE_buff_flag; 152 | 153 | static void notifyCallback( 154 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 155 | uint8_t* pData, 156 | size_t length, 157 | bool isNotify); 158 | 159 | void printFrequency(void); 160 | 161 | 162 | // The onDisconnect() callback function worked but am using pClient->isConnected() instead. 163 | // It also arrives asynchronously which has to be handled as such. Not using this now. 164 | // To use these, uncomment the 165 | class MyClientCallback : public BLEClientCallbacks 166 | { 167 | void onConnect(BLEClient* pclient) { 168 | //doConnect = true; 169 | //BLE_connected = true; // tracks state of BLE level connection 170 | Serial.println("Now Connected to BLE server"); 171 | } 172 | 173 | void onDisconnect(BLEClient* pclient) { 174 | connected = false; // tacks state of CIV connection 175 | doConnect = false; // gateway to connect and pair processes. 176 | BLE_connected = false; // tracks state of BLE level connection 177 | Name_confirm = Token_confirm = CIV_granted = false; // reset 178 | Serial.println("Lost BLE server connection event flag set on Disconnect "); 179 | //Scan_BLE_Servers(); 180 | } 181 | }; 182 | 183 | // ---------------------------------------- 184 | // Print the received frequency 185 | // ---------------------------------------- 186 | void printFrequency(const uint8_t freq[]) 187 | { 188 | if (BLE_connected) { 189 | frequency = 0; 190 | //FE FE E0 42 03 <00 00 58 45 01 10> FD ic-905 6byes on 10G+ bands 191 | //FE FE E0 42 03 <00 00 58 45 01> FD ic-820 and IC-705 5 bytes 192 | //FE FE 00 40 00 <00 60 06 14> FD ic-732 4 bytes 193 | for (uint8_t i = 0; i < 5; i++) { 194 | if (freq[9 - i] == 0xFD) continue; //spike 195 | frequency += (freq[9 - i] >> 4) * decMulti[i * 2]; 196 | frequency += (freq[9 - i] & 0x0F) * decMulti[i * 2 + 1]; 197 | } 198 | Serial.print("VFO:"); Serial.println(frequency); 199 | } 200 | } 201 | 202 | uint8_t *r = read_buffer; 203 | 204 | static void notifyCallback( 205 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 206 | uint8_t* pData, 207 | size_t length, 208 | bool isNotify) 209 | { 210 | //Serial.printf("Callback Notify value = \n",isNotify); 211 | //Serial.println("Notify callback for TX characteristic received. Data:"); 212 | for (int i = 0; i < length; i++) 213 | { 214 | // Serial.print((char)pData[i]); // Print character to uart 215 | #ifdef WATCH_BLE_SERIAL 216 | Serial.print(pData[i], HEX); // print raw data to uart 217 | Serial.print(","); 218 | #endif 219 | 220 | r[i] = pData[i]; // copy into main read buffer 221 | 222 | if (pData[i] == 0xFD) 223 | { 224 | r[i+1] = 0; 225 | 226 | #ifdef WATCH_BLE_SERIAL 227 | Serial.println(); 228 | #endif 229 | 230 | if (pData[1] == 0xF1 && pData[2] == 0x00) 231 | { 232 | switch (pData[3]) 233 | { 234 | case 0x61: 235 | Serial.println("Got BT_ADDR message confirmation, proceed"); 236 | BT_ADDR_confirm = true; 237 | break; 238 | case 0x62: 239 | Serial.println("Got NAME message confirmation, proceed"); 240 | Name_confirm = true; 241 | break; 242 | case 0x63: 243 | Serial.println("Got TOKEN message confirmation, proceed"); 244 | Token_confirm = true; 245 | if (pData[4] == 0x01) 246 | Pairing_Accepted = true; // Pairing action worked. Once pair this wil return 0 247 | break; 248 | case 0x64: 249 | Serial.println("CI-V bus ACCESS granted, proceed"); 250 | CIV_granted = true; 251 | connected = true; 252 | break; 253 | } 254 | } 255 | BLE_buff_flag = true; // consuming functions wil reset this once it is read and won't waste time reading stale data 256 | } 257 | } 258 | 259 | //CIV_Action(const uint8_t cmd_num, const uint8_t data_start_idx, const uint8_t data_len, const uint8_t msg_len, const uint8_t read_buffer[]) 260 | //CIV_Action(pData[4], data_start_idx, data_len, sizeof(pData), read_buffer[]) 261 | if (connected) 262 | { 263 | /* Replaced with app_loop sharing processing with USB host and BT Classic 264 | for (int i = 0; i < length; i++) 265 | Serial.print(r[i],HEX); 266 | Serial.println(""); 267 | 268 | switch (pData[4]) 269 | { 270 | case 0x00: 271 | case 0x03: 272 | case 0x05: 273 | printFrequency(pData); // VFO frequency 274 | //read_Frequency(sizeof(pData)); 275 | break; 276 | case 0x1C: 277 | if (pData[5] == 0) // RX/TX state message 278 | PTT = pData[6]; 279 | break; 280 | default: break; 281 | } 282 | */ 283 | } 284 | } 285 | 286 | //************************************************************************************** 287 | // 288 | // Connect to Server 289 | // 290 | //************************************************************************************** 291 | 292 | bool connectToServer(BLEAddress pAddress) { 293 | Serial.print("Establishing a connection to device address: "); 294 | Serial.println(pAddress.toString().c_str()); 295 | 296 | pClient = BLEDevice::createClient(); 297 | //BLEClient* pClient = BLEDevice::createClient(); 298 | Serial.println(" - Created client"); 299 | 300 | // Connect to the remove BLE Server. 301 | pClient->connect(pAddress); 302 | Serial.println(" - Connected to server"); 303 | pClient->setMTU(517); //set client to request maximum MTU from 304 | //server (default is 23 otherwise) 305 | 306 | // Obtain a reference to the Nordic UART service on the remote BLE server. 307 | BLERemoteService* pRemoteService = pClient->getService(serviceUUID); 308 | if (pRemoteService == nullptr) { 309 | Serial.print("Failed to find Nordic UART service UUID: "); 310 | Serial.println(serviceUUID.toString().c_str()); 311 | pClient->disconnect(); 312 | return false; 313 | } 314 | Serial.print(" - Found our service "); 315 | //Serial.println(pClient->getPeerAddress()); 316 | 317 | // Obtain a reference to the TX characteristic of the Nordic UART service on the remote BLE server. 318 | pTXCharacteristic = pRemoteService->getCharacteristic(charUUID_TX); 319 | if (pTXCharacteristic == nullptr) { 320 | Serial.print("Failed to find TX characteristic UUID: "); 321 | Serial.println(charUUID_TX.toString().c_str()); 322 | pClient->disconnect(); 323 | return false; 324 | } 325 | Serial.println(" - Remote BLE TX characteristic reference established"); 326 | 327 | // Read the value of the TX characteristic. 328 | //if(pTXCharacteristic->canRead()) { 329 | //std::string value = pTXCharacteristic->readValue(); 330 | String value = pTXCharacteristic->readValue(); 331 | Serial.print("The characteristic value is currently: "); 332 | Serial.println(value.c_str()); 333 | //} 334 | 335 | // Obtain a reference to the RX characteristic of the Nordic UART service on the remote BLE server. 336 | pRXCharacteristic = pRemoteService->getCharacteristic(charUUID_RX); 337 | if (pRXCharacteristic == nullptr) { 338 | Serial.print("Failed to find our characteristic UUID: "); 339 | Serial.println(charUUID_RX.toString().c_str()); 340 | return false; 341 | } 342 | Serial.println(" - Remote BLE RX characteristic reference established"); 343 | 344 | // Read the value of the characteristic. 345 | if(pRXCharacteristic->canRead()) { 346 | value = pRXCharacteristic->readValue(); 347 | Serial.print("The characteristic value was: "); 348 | Serial.println(value.c_str()); 349 | } 350 | 351 | if(pTXCharacteristic->canNotify()) 352 | pTXCharacteristic->registerForNotify(notifyCallback); 353 | 354 | // UUID is 32 bytes, msg is 41 total. Any less and the reply for the Name msg will be suppressed. Weird, probably a radio bug. 355 | pRXCharacteristic->writeValue(CIV_ID0, sizeof(CIV_ID0)); 356 | pRXCharacteristic->canNotify(); 357 | delay(20); 358 | 359 | // Device name must be 16 bytes exactly, msg total 21 bytes. 360 | pRXCharacteristic->writeValue(CIV_ID1, sizeof(CIV_ID1)); 361 | pRXCharacteristic->canNotify(); 362 | delay(20); // a small delay was required or this message would be missed (collision likely). 363 | 364 | // Send Token - A fixed value 9 bytes long total. 365 | uint8_t CIV_ID2[] = {0xFE, 0xF1, 0x00, 0x63, 0xEE, 0x39, 0x09, 0x10, 0xFD}; // Send Token 366 | pRXCharacteristic->writeValue(CIV_ID2, 9); 367 | pRXCharacteristic->canNotify(); 368 | delay(20); 369 | 370 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x62, 0xFD // no reply when reconnecting 371 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x01, 0xFD // pair confirmed 372 | // if already paired, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x00, 0xFD // already paired 373 | // if all good, will get reply with 0xFE, 0xF1, 0x00, 0x64, 0xFD // CI-V bus access granted 374 | 375 | //String helloValue = "Hello Remote Server"; 376 | //pRXCharacteristic->writeValue(helloValue.c_str(), helloValue.length()); 377 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); 378 | //connected = true; 379 | return true; 380 | } 381 | 382 | void printDeviceAddress() { 383 | const uint8_t* point = esp_bt_dev_get_address(); 384 | 385 | for (int i = 0; i < 6; i++) { 386 | char str[3]; 387 | 388 | sprintf(str, "%02X", (int)point[i]); 389 | Serial.print(str); 390 | 391 | if (i < 5){ 392 | Serial.print(":"); 393 | } 394 | } 395 | Serial.println(""); 396 | } 397 | 398 | /************************************************************************************** 399 | Scan for BLE servers and find the first one that advertises the Nordic UART service. 400 | ***************************************************************************************/ 401 | class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { 402 | /** 403 | Called for each advertising BLE server. 404 | */ 405 | void onResult(BLEAdvertisedDevice advertisedDevice) { 406 | Serial.print("BLE Advertised Device found - "); 407 | Serial.println(advertisedDevice.toString().c_str()); 408 | 409 | // We have found a device, check to see if it contains the Nordic UART service. 410 | if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { 411 | 412 | Serial.println("Found a device with the desired ServiceUUID!"); 413 | advertisedDevice.getScan()->stop(); 414 | 415 | pServerAddress = new BLEAddress(advertisedDevice.getAddress()); 416 | doConnect = true; // Trigger to process server connection 417 | 418 | } // Found our server 419 | } // onResult 420 | }; // MyAdvertisedDeviceCallbacks 421 | 422 | void Scan_BLE_Servers(void) 423 | { 424 | // Retrieve a Scanner and set the callback we want to use to be informed when we 425 | // have detected a new device. Specify that we want active scanning and start the 426 | // scan to run for 30 seconds 427 | BLEScan* pBLEScan = BLEDevice::getScan(); 428 | pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); 429 | pBLEScan->setInterval(1349); 430 | pBLEScan->setWindow(449); // less or equal setInterval value 431 | pBLEScan->setActiveScan(true); 432 | BLEScanResults *foundDevices = pBLEScan->start(scanTime, false); 433 | //pBLEScan->start(scanTime, false); 434 | Serial.print("Devices found: "); Serial.println(foundDevices->getCount()); 435 | Serial.println("Scan done!"); 436 | pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory 437 | } 438 | 439 | //-------------------------------------------- // 440 | // BLE 441 | // SendMessage by BLE Slow in packets of 20 chars 442 | // or fast in one long string. 443 | // Fast can be used in IOS app BLESerial Pro 444 | //------------------------------ 445 | void SendMessageBLE(uint8_t Message[], uint8_t len) 446 | { 447 | if(connected) 448 | { 449 | //if (Mem.UseBLELongString) // If Fast transmission is possible 450 | pRXCharacteristic->writeValue(Message, len, false); //.c_str()); 451 | pRXCharacteristic->canNotify(); 452 | //delay(10); // Bluetooth stack will go into congestion, if too many packets are sent 453 | 454 | /*} 455 | else // Packets of max 20 bytes 456 | { 457 | int parts = (Message.length()/20) + 1; 458 | for(int n=0;nwriteValue(Message.substr(n*20, 20).c_str()); 461 | pRXCharacteristic->canNotify(); 462 | //delay(40); // Bluetooth stack will go into congestion, if too many packets are sent 463 | } 464 | }*/ 465 | } 466 | } 467 | 468 | void BLE_Setup(void) 469 | { 470 | Serial.println("BLE_Setup entry"); 471 | BLEDevice::init(""); 472 | doConnect = false; 473 | } 474 | 475 | // If the flag "doConnect" is true then we have scanned for and found the desired 476 | // BLE Server with which we wish to connect. Now we connect to it. Once we are 477 | // connected we set the connected flag to be true. 478 | void BLE_loop(void) 479 | { 480 | static uint32_t time_freq = 0; 481 | static uint32_t time_tx = 0; 482 | 483 | if (doConnect == true) 484 | { 485 | if (connectToServer(*pServerAddress)) 486 | { 487 | //Serial.println("We are now connected to the BLE Server."); 488 | // should have CIV results by now, see if we have access to the CI-V bus or not 489 | Serial.printf("doConnect1 - post CIV_Connect - connected = %d Token = %d CIV_Granted = %d BLE_connected = %d\n", connected, Token_confirm, CIV_granted, BLE_connected); 490 | 491 | if (Token_confirm) 492 | ; 493 | 494 | if (Pairing_Accepted && Token_confirm) 495 | Serial.println("Pairing_Accepted"); // only get this whe a pairing is request. false on regular sign in 496 | 497 | if (!Pairing_Accepted && Token_confirm) // continue on 498 | Serial.println("Paired already, continue to sign in"); 499 | 500 | if (!BLE_connected && CIV_granted) 501 | { 502 | connected = true; // tracks CIV layer state can be connected to BLE but not CIV (not paired for example) 503 | BLE_connected = true; // tracks CIV layer more glabal than the connected var, almost redundant 504 | Serial.println("BLE Connected"); 505 | } 506 | onoff = true; // want to read from the radio 507 | // Can toggle notifications for the TX Characteristic on and off. 508 | // Update the RX characteristic with the current time since boot string. 509 | if (onoff) { 510 | //Serial.println("Notifications turned on"); 511 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); 512 | } else { 513 | //Serial.println("Notifications turned off"); 514 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOff, 2, true); 515 | } 516 | } 517 | else 518 | { 519 | Serial.println("We have failed to connect to the server; there is nothin more we will do."); 520 | //draw_initial_screen(); 521 | //M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 522 | //M5.Lcd.setCursor(5, 80); //Set the location of the cursor to the coordinates X and Y 523 | //M5.Lcd.printf("Failed Connection to Radio"); 524 | connected = false; 525 | } 526 | doConnect = false; 527 | } 528 | 529 | if (pClient != nullptr && !pClient->isConnected()) 530 | { 531 | if (BLE_connected) 532 | Serial.println("BLE not connected to radio"); // detect if we are not connected 533 | //delay(100); 534 | connected = false; 535 | BLE_connected = false; 536 | } 537 | 538 | if(connected) 539 | { 540 | /* 541 | if (millis() >= time_freq + POLL_RADIO_FREQ) // poll every X ms 542 | { 543 | //Serial.println("Poll radio"); 544 | uint8_t CIV_frequency[] = {0xFE, 0xFE, radio_address, 0xE0, 0x03, 0xFD}; 545 | pRXCharacteristic->writeValue(CIV_frequency, sizeof(CIV_frequency), false); 546 | //pRXCharacteristic->writeValue(&cmds[CIV_C_F_READ].cmdData[1], cmds[CIV_C_F_READ].cmdData[0], true); 547 | pRXCharacteristic->canNotify(); 548 | //delay(10); 549 | time_freq = millis(); 550 | } 551 | 552 | if (millis() >= time_tx + POLL_PTT_DEFAULT) // poll every X ms 553 | { 554 | //Serial.println("Poll radio for TX/RX state"); 555 | uint8_t CIV_TX[] = {0xFE, 0xFE, radio_address, 0xE0, 0x1C, 0x00, 0xFD}; 556 | pRXCharacteristic->writeValue(CIV_TX, sizeof(CIV_TX), false); 557 | //pRXCharacteristic->writeValue(CIV_C_TX, cmds[CIV_C_TX].cmdData[0], true); 558 | pRXCharacteristic->canNotify(); 559 | //delay(10); 560 | time_tx = millis(); 561 | } 562 | */ 563 | }// if connected 564 | else 565 | { 566 | Scan_BLE_Servers(); 567 | } 568 | } // End of loop 569 | 570 | #endif 571 | #endif 572 | 573 | -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/BLE.h: -------------------------------------------------------------------------------- 1 | #ifndef BLE_H_ 2 | #define BLE_H_ 3 | 4 | void Scan_BLE_Servers(void); 5 | static bool doConnect = false; 6 | void BLE_loop(void); 7 | void BLE_Setup(void); 8 | 9 | #endif -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/BLEScan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BLEScan.h 3 | * 4 | * Created on: Jul 1, 2017 5 | * Author: kolban 6 | */ 7 | 8 | #ifndef COMPONENTS_CPP_UTILS_BLESCAN_H_ 9 | #define COMPONENTS_CPP_UTILS_BLESCAN_H_ 10 | #include "sdkconfig.h" 11 | #if defined(CONFIG_BLUEDROID_ENABLED) 12 | #include 13 | 14 | // #include 15 | #include 16 | #include "BLEAdvertisedDevice.h" 17 | #include "BLEClient.h" 18 | #include "RTOS.h" 19 | 20 | class BLEAdvertisedDevice; 21 | class BLEAdvertisedDeviceCallbacks; 22 | class BLEExtAdvertisingCallbacks; 23 | class BLEClient; 24 | class BLEScan; 25 | class BLEPeriodicScanCallbacks; 26 | 27 | 28 | struct esp_ble_periodic_adv_sync_estab_param_t { 29 | uint8_t status; /*!< periodic advertising sync status */ 30 | uint16_t sync_handle; /*!< periodic advertising sync handle */ 31 | uint8_t sid; /*!< periodic advertising sid */ 32 | esp_ble_addr_type_t adv_addr_type; /*!< periodic advertising address type */ 33 | esp_bd_addr_t adv_addr; /*!< periodic advertising address */ 34 | esp_ble_gap_phy_t adv_phy; /*!< periodic advertising phy type */ 35 | uint16_t period_adv_interval; /*!< periodic advertising interval */ 36 | uint8_t adv_clk_accuracy; /*!< periodic advertising clock accuracy */ 37 | }; 38 | 39 | /** 40 | * @brief The result of having performed a scan. 41 | * When a scan completes, we have a set of found devices. Each device is described 42 | * by a BLEAdvertisedDevice object. The number of items in the set is given by 43 | * getCount(). We can retrieve a device by calling getDevice() passing in the 44 | * index (starting at 0) of the desired device. 45 | */ 46 | class BLEScanResults { 47 | public: 48 | void dump(); 49 | int getCount(); 50 | BLEAdvertisedDevice getDevice(uint32_t i); 51 | 52 | private: 53 | friend BLEScan; 54 | std::map m_vectorAdvertisedDevices; 55 | }; 56 | 57 | /** 58 | * @brief Perform and manage %BLE scans. 59 | * 60 | * Scanning is associated with a %BLE client that is attempting to locate BLE servers. 61 | */ 62 | class BLEScan { 63 | public: 64 | void setActiveScan(bool active); 65 | void setAdvertisedDeviceCallbacks( 66 | BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, 67 | bool wantDuplicates = false, 68 | bool shouldParse = true); 69 | void setInterval(uint16_t intervalMSecs); 70 | void setWindow(uint16_t windowMSecs); 71 | bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false); 72 | BLEScanResults start(uint32_t duration, bool is_continue = false); 73 | void stop(); 74 | void erase(BLEAddress address); 75 | BLEScanResults getResults(); 76 | void clearResults(); 77 | 78 | #ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED 79 | void setExtendedScanCallback(BLEExtAdvertisingCallbacks* cb); 80 | void setPeriodicScanCallback(BLEPeriodicScanCallbacks* cb); 81 | 82 | esp_err_t stopExtScan(); 83 | esp_err_t setExtScanParams(); 84 | esp_err_t setExtScanParams(esp_ble_ext_scan_params_t* ext_scan_params); 85 | esp_err_t startExtScan(uint32_t duration, uint16_t period); 86 | private: 87 | BLEExtAdvertisingCallbacks* m_pExtendedScanCb = nullptr; 88 | BLEPeriodicScanCallbacks* m_pPeriodicScanCb = nullptr; 89 | #endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED 90 | 91 | private: 92 | BLEScan(); // One doesn't create a new instance instead one asks the BLEDevice for the singleton. 93 | friend class BLEDevice; 94 | void handleGAPEvent( 95 | esp_gap_ble_cb_event_t event, 96 | esp_ble_gap_cb_param_t* param); 97 | 98 | 99 | esp_ble_scan_params_t m_scan_params; 100 | BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; 101 | bool m_stopped = true; 102 | bool m_shouldParse = true; 103 | FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd"); 104 | BLEScanResults m_scanResults; 105 | bool m_wantDuplicates; 106 | void (*m_scanCompleteCB)(BLEScanResults scanResults); 107 | }; // BLEScan 108 | 109 | class BLEPeriodicScanCallbacks { 110 | public: 111 | virtual ~BLEPeriodicScanCallbacks() {} 112 | 113 | virtual void onCreateSync(esp_bt_status_t status) {} 114 | virtual void onCancelSync(esp_bt_status_t status) {} 115 | virtual void onTerminateSync(esp_bt_status_t status) {} 116 | virtual void onLostSync(uint16_t sync_handle) {} 117 | virtual void onSync(esp_ble_periodic_adv_sync_estab_param_t) {} 118 | virtual void onReport(esp_ble_gap_periodic_adv_report_t params) {} 119 | virtual void onStop(esp_bt_status_t status) {} 120 | }; 121 | 122 | #endif /* CONFIG_BLUEDROID_ENABLED */ 123 | #endif /* COMPONENTS_CPP_UTILS_BLESCAN_H_ */ 124 | -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/CIV.h: -------------------------------------------------------------------------------- 1 | // CIV.h 2 | 3 | #ifndef CIV_h 4 | #define CIV_h 5 | 6 | //#include 7 | 8 | //inline uint8_t bcdByte(const uint8_t x) const { return (((x & 0xf0) >> 4) * 10) + (x & 0x0f); } 9 | inline uint8_t bcdByte(const uint8_t x) { return (((x & 0xf0) >> 4) * 10) + (x & 0x0f); } 10 | // input is between 0 and 99 decimal. output 0 to 0x99 11 | //inline uint8_t bcdByteEncode(const uint8_t x) const { return ((x / 10) << 4) + (x % 10); } 12 | inline uint8_t bcdByteEncode(const uint8_t x) { return ((x / 10) << 4) + (x % 10); } 13 | 14 | /* ======================================== 15 | * geo.c 16 | * 17 | * Converts Lat and Long to extended maidenhead grid squares 18 | * 19 | * ======================================== 20 | */ 21 | 22 | /* geo.c Ham Radio functions for orientation on earth – Copyright 2010 This program is free software; you can redistribute it 23 | * and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either 24 | * version 3, or (at your option) any later version. 25 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 26 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 27 | * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software 28 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 29 | */ 30 | /* 31 | * 32 | * Next the function that converts the position to the Maidenhead locator. It could easily have been written just to 33 | * accept two arguments for the position, but in this case the structure is passed by address to the function for evaluation. 34 | * 35 | * The return value of the function is best provided by the calling routine, so the second argument is the address of a string 36 | * (i.e. an array of type char) where the function will return the result. This is quite a bit more complicated that most 37 | * languages which use dynamic memory allocation and garbage collection to allow functions to return strings. 38 | * 39 | * I use the return value here to indicate success or failure, but have no failure conditions. I suppose a latitude of less than -90 or more than +90 would suffice. For longitude I thing wrapping (e.g. 181E = 179W) is sufficient, which is what the function does. 40 | * 41 | */ 42 | 43 | /* Global variables for handling GPS conversion to Maindernhead grid square */ 44 | #define NMEA_MAX_LENGTH (120) 45 | #define GRIDSQUARE_LEN (9u) 46 | 47 | struct position { 48 | double latitude; 49 | double longitude; 50 | }; 51 | 52 | static char Latitude[14]; /* size to hold longest values supplied by GPS, assuming 10 plus null for now */ 53 | static char Longitude[14]; 54 | void CIV_Action(const uint8_t cmd_num, const uint8_t data_start_idx, const uint8_t data_len, const uint8_t msg_len, const uint8_t read_buffer[]); 55 | void reverse(char *str, int len); 56 | void ftoa(float n, char *res, int afterpoint); 57 | int positionToMaidenhead(char m[]); 58 | int Convert_to_MH(void); 59 | void ConvertToMinutes(char _gps_msg[]); 60 | void SetMode(uint8_t _band); 61 | void SetAGC(uint8_t _band); 62 | void SetPre(uint8_t _band); 63 | void SetAttn(uint8_t _band); 64 | 65 | // command "body" of the CIV commands currently in use 66 | // Add new command to this list. Then add array values to the structure below. The row is the same as the enum value here. 67 | enum cmds { 68 | CIV_C_F_SEND, 69 | CIV_C_F1_SEND, 70 | CIV_C_F_READ, 71 | CIV_C_F26, 72 | CIV_C_F26A, 73 | CIV_C_F26B, 74 | CIV_C_F25A_SEND, 75 | CIV_C_F25B_SEND, 76 | CIV_C_MOD_READ, 77 | CIV_C_MOD_SET, 78 | CIV_C_MOD_SEND, 79 | CIV_C_MOD1_SEND, 80 | CIV_C_MOD_USB_F1_SEND, 81 | CIV_C_MOD_USB_SEND, 82 | CIV_C_USB_D0_F2_SEND, 83 | CIV_C_USB_D1_F2_SEND, 84 | CIV_C_LSB_D0_F2_SEND, 85 | CIV_C_LSB_D1_F2_SEND, 86 | CIV_C_FM_D1_F1_SEND, 87 | CIV_C_ATTN_READ, 88 | CIV_C_ATTN_OFF, 89 | CIV_C_ATTN_ON, 90 | CIV_C_SPLIT_OFF_READ, 91 | CIV_C_SPLIT_ON_READ, 92 | CIV_C_SPLIT_OFF_SEND, 93 | CIV_C_SPLIT_ON_SEND, 94 | CIV_C_RFGAIN, 95 | CIV_C_AFGAIN, 96 | CIV_C_RFPOWER, 97 | CIV_C_S_MTR_LVL, 98 | CIV_C_PREAMP_READ, 99 | CIV_C_PREAMP_OFF, 100 | CIV_C_PREAMP_ON, 101 | CIV_C_PREAMP_ON2, 102 | CIV_C_AGC_READ, 103 | CIV_C_AGC_FAST, 104 | CIV_C_AGC_MID, 105 | CIV_C_AGC_SLOW, 106 | CIV_C_CW_MSGS, 107 | CIV_C_BSTACK, 108 | CIV_C_MY_POSIT_READ, 109 | CIV_C_MY_POSIT_DATA, 110 | CIV_C_RF_POW, 111 | CIV_C_TRX_ON_OFF, 112 | CIV_C_TRX_ID, 113 | CIV_C_TX, 114 | CIV_C_DATE, 115 | CIV_C_TIME, 116 | CIV_C_UTC_READ_905, 117 | CIV_C_UTC_READ_705, 118 | CIV_C_DUPLEX_READ, 119 | CIV_C_DUPLEX_SEND, 120 | CIV_C_RIT_XIT, 121 | CIV_C_RIT_ON_OFF, 122 | CIV_C_XIT_ON_OFF, 123 | CIV_C_RADIO_OFF, 124 | CIV_C_RADIO_ON, 125 | End_of_Cmd_List 126 | }; 127 | 128 | struct cmdList { 129 | cmds cmd; 130 | uint8_t cmdData[6]; // first byte is number of bytes in the command (sub commands) 131 | }; 132 | 133 | #endif // CIV.h header file 134 | -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/DebugPrint.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUGPRINT_H_ 2 | #define DEBUGPRINT_H_ 3 | 4 | #define DEBUG //set for debug output 5 | 6 | #ifdef DEBUG 7 | #define DEBUG_ERROR true 8 | #define DEBUG_ERROR_SERIAL if(DEBUG_ERROR)Serial 9 | 10 | #define DEBUG_WARNING true 11 | #define DEBUG_WARNING_SERIAL if(DEBUG_WARNING)Serial 12 | 13 | #define DEBUG_INFORMATION true 14 | #define DEBUG_INFORMATION_SERIAL if(DEBUG_INFORMATION)Serial 15 | #define DSERIALBEGIN(...) Serial.begin(__VA_ARGS__) 16 | #define DPRINTLN(...) Serial.println(__VA_ARGS__) 17 | #define DPRINT(...) Serial.print(__VA_ARGS__) 18 | #define DPRINTF(...) Serial.print(F(__VA_ARGS__)) 19 | #define DPRINTLNF(...) Serial.println(F(__VA_ARGS__)) //printing text using the F macro 20 | #define DELAY(...) delay(__VA_ARGS__) 21 | #define PINMODE(...) pinMode(__VA_ARGS__) 22 | #define TOGGLEd13 PINB = 0x20 //UNO's pin D13 23 | #define DEBUG_PRINT(...) Serial.print(F(#__VA_ARGS__" = ")); Serial.print(__VA_ARGS__); Serial.print(F(" ")) 24 | #define DEBUG_PRINTLN(...) DEBUG_PRINT(__VA_ARGS__); Serial.println() 25 | #define DEBUG_PRINTF(...) Serial.printf(__VA_ARGS__) 26 | #else 27 | #define DSERIALBEGIN(...) 28 | #define DPRINTLN(...) 29 | #define DPRINT(...) 30 | #define DPRINTF(...) 31 | #define DPRINTLNF(...) 32 | #define DELAY(...) 33 | #define PINMODE(...) 34 | #define TOGGLEd13 35 | #define DEBUG_PRINT(...) 36 | #define DEBUG_PRINTLN(...) 37 | #define DEBUG_PRINTF(...) 38 | #endif 39 | 40 | #endif //DEBUGPRINT_H_ -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/Decoder.cpp: -------------------------------------------------------------------------------- 1 | // Band Decoder Input and Output. Customize the IO pin patterns for band 2 | // Borrowed from my IC-905 Band Decoder dev project, applying it to the 4in/8out module example code. 3 | #ifndef _DECODER_ 4 | #define _DECODER_ 5 | 6 | #include "Decoder.h" 7 | #include "MODULE_4IN8OUT.h" 8 | #include 9 | #include "DebugPrint.h" 10 | #include "M5Stamp_Decoder.h" 11 | 12 | #ifdef IO_MODULE 13 | MODULE_4IN8OUT module; 14 | #endif 15 | 16 | #ifdef RELAY2 17 | #if defined ( CORE3 ) // Use Port A OK 18 | // Core 3 Port A 19 | #define pinR1 2 // 32 P.a works on core 2, PB 26 works on M5Core 20 | #define pinR2 1 // 33 P.a works on Core2. Pb 36 does not work in M5Core 21 | // Core 3 Port B 22 | //#define pinR1 9 // 32 P.a works on core 2, PB 26 works on M5Core 23 | //#define pinR2 8 // 33 P.a works on Core2. Pb 36 does not work in M5Core 24 | // Core 3 Port C 25 | //#define pinR1 18 // 32 P.a works on core 2, PB 26 works on M5Core 26 | //#define pinR2 17 // 33 P.a works on Core2. Pb 36 does not work in M5Core 27 | 28 | #elif defined ( CORE2 ) 29 | // Core 2 Port A 30 | #define pinR1 32 // 32 P.a works on core 2, PB 26 works on M5Core 31 | #define pinR2 33 // 33 P.a works on Core2. Pb 36 does not work in M5Core 32 | // Core 2 Port B 33 | //#define pinR1 26 // 32 P.a works on core 2, PB 26 works on M5Core 34 | //#define pinR2 36 // 33 P.a works on Core2. Pb 36 does not work in M5Core 35 | // Core 2 Port C 36 | //#define pinR1 13 // 32 P.a works on core 2, PB 26 works on M5Core 37 | //#define pinR2 14 // 33 P.a works on Core2. Pb 36 does not work in M5Core 38 | 39 | #else 40 | // Use Port C preferred 41 | // Core basic Port Be 42 | //#define pinR1 26 // 32 P.a works on core 2, PB 26 works on M5Core 43 | //#define pinR2 36 // 33 P.a works on Core2. Pb 36 does not work in M5Core 44 | // Core basic Port C 45 | #define pinR1 16 // 32 P.a works on core 2, PB 26 works on M5Core 46 | #define pinR2 17 // 33 P.a works on Core2. Pb 36 does not work in M5Core 47 | #endif // CPU type 48 | #endif // relay2 49 | 50 | // Very basic - outputs a set pattern for each band. Follows the Elecraft K3 patther for combined HF and VHF used for transverters and antenna switching 51 | // This may control a external band decoder that accept wired inputs. Other decoder outpout can be serial or ethernet 52 | void Band_Decode_Output(uint8_t band) 53 | { 54 | // Convert frequency band to a parallel wire GPIO output pattern. 55 | // On an Elecraft K3 this is equivalent to the HF-TRN mode. DigOut is used in combo with Band Decode BCD 0-3 pins. 56 | // The pattern 0xYYXX where YY is 01 for VHF+ band group and 00 for HF band group. XX is the band identifier witin each HF and VHF group. 57 | // Set your desired patterns in RadioConfig.h 58 | // ToDo: Eventually create a local UI screen to edit and monitor pin states 59 | 60 | DPRINTF("Band_Decode_Output: Band: "); DPRINTLN(band); 61 | 62 | switch (band) 63 | { 64 | case BAND_AM : GPIO_Out(DECODE_BANDAM); break; //160M 65 | case BAND_160M : GPIO_Out(DECODE_BAND160M); break; //160M 66 | case BAND_80M : GPIO_Out(DECODE_BAND80M); break; //80M 67 | case BAND_60M : GPIO_Out(DECODE_BAND60M); break; //60M 68 | case BAND_40M : GPIO_Out(DECODE_BAND40M); break; //40M 69 | case BAND_30M : GPIO_Out(DECODE_BAND30M); break; //30M 70 | case BAND_20M : GPIO_Out(DECODE_BAND20M); break; //20M 71 | case BAND_17M : GPIO_Out(DECODE_BAND17M); break; //17M 72 | case BAND_15M : GPIO_Out(DECODE_BAND15M); break; //15M 73 | case BAND_12M : GPIO_Out(DECODE_BAND12M); break; //12M 74 | case BAND_10M : GPIO_Out(DECODE_BAND10M); break; //10M 75 | case BAND_6M : GPIO_Out(DECODE_BAND6M); break; //6M 76 | case BAND_FM : GPIO_Out(DECODE_BANDFM); break; //6M 77 | case BAND_AIR : GPIO_Out(DECODE_BANDAIR); break; //6M 78 | 79 | //case BAND70 : GPIO_Out(0x01); break; //6M 80 | case BAND_2M : GPIO_Out(DECODE_BAND144); break; //2M 81 | case BAND_1_25M: GPIO_Out(DECODE_BAND222); break; //222 82 | case BAND_70cm : GPIO_Out(DECODE_BAND432); break; //432 83 | case BAND_33cm : GPIO_Out(DECODE_BAND902); break; //902 84 | case BAND_23cm : GPIO_Out(DECODE_BAND1296); break; //1296 85 | case BAND_13cm : GPIO_Out(DECODE_BAND2400); break; //2400 86 | case BAND_9cm : GPIO_Out(DECODE_BAND3400); break; //3400 87 | case BAND_6cm : GPIO_Out(DECODE_BAND5760); break; //5760M 88 | case BAND_3cm : GPIO_Out(DECODE_BAND10G); break; //10.368.1G 89 | case BAND_24G : GPIO_Out(DECODE_BAND24G); break; //24.192G 90 | case BAND_47G : GPIO_Out(DECODE_BAND47G); break; //47.1G 91 | case BAND_76G : GPIO_Out(DECODE_BAND76G); break; //76.1G 92 | case BAND_122G : GPIO_Out(DECODE_BAND122G); break; //122G 93 | case B_GENERAL : GPIO_Out(DECODE_B_GENERAL); break; //122G 94 | } 95 | } 96 | 97 | void GPIO_Out(uint8_t pattern) 98 | { 99 | DPRINTF("GPIO_Out: pattern: DEC "); DPRINT(pattern); 100 | DPRINTF(" HEX "); DPRINT(pattern, HEX); 101 | DPRINTF(" Binary "); DPRINTLN(pattern, BIN); 102 | 103 | //#ifndef IO_MODULE 104 | // DPRINTLNF("GPIO_Out: IO_MODULE **NOT** enabled"); 105 | //return; 106 | //#endif 107 | 108 | // Enabled relay when any XVTR band active - test for now with 2 channel relay module 109 | #if defined ( RELAY2 ) 110 | if (pattern) { 111 | digitalWrite(pinR2, HIGH); 112 | DPRINTLNF("Relay+++++++++XVTR_ON"); 113 | } 114 | else { 115 | digitalWrite(pinR2, LOW); 116 | DPRINTLNF("Relay---------XVTR_OFF"); 117 | } 118 | #endif 119 | 120 | //pattern = !pattern; 121 | 122 | #ifdef IO_MODULE 123 | // mask each bit and apply the 1 or 0 to the assigned pin 124 | if (BAND_DECODE_OUTPUT_PIN_0 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_0, (pattern & 0x01) ? 1 : 0); // bit 0 125 | if (BAND_DECODE_OUTPUT_PIN_1 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_1, (pattern & 0x02) ? 1 : 0); // bit 1 126 | if (BAND_DECODE_OUTPUT_PIN_2 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_2, (pattern & 0x04) ? 1 : 0); // bit 2 127 | if (BAND_DECODE_OUTPUT_PIN_3 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_3, (pattern & 0x08) ? 1 : 0); // bit 3 128 | if (BAND_DECODE_OUTPUT_PIN_4 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_4, (pattern & 0x10) ? 1 : 0); // bit 4 129 | if (BAND_DECODE_OUTPUT_PIN_5 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_5, (pattern & 0x20) ? 1 : 0); // bit 5 130 | if (BAND_DECODE_OUTPUT_PIN_6 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_6, (pattern & 0x40) ? 1 : 0); // bit 6 131 | if (BAND_DECODE_OUTPUT_PIN_7 != GPIO_PIN_NOT_USED) module.setOutput(BAND_DECODE_OUTPUT_PIN_7, (pattern & 0x80) ? 1 : 0); // bit 7 132 | #endif 133 | } 134 | 135 | void PTT_Output(uint8_t band, bool PTT_state) 136 | { 137 | // Set your desired PTT pattern per band in RadioConfig.h 138 | // ToDo: Eventually create a local UI screen to edit and monitor pin states 139 | 140 | DPRINTF("Band_Decode_Output: Band: "); DPRINTLN(band); 141 | 142 | switch (band) 143 | { 144 | case BAND_AM : GPIO_PTT_Out(DECODE_BANDAM_PTT, PTT_state); break; //160M 145 | case BAND_160M : GPIO_PTT_Out(DECODE_BAND160M_PTT, PTT_state); break; //160M 146 | case BAND_80M : GPIO_PTT_Out(DECODE_BAND80M_PTT, PTT_state); break; //80M 147 | case BAND_60M : GPIO_PTT_Out(DECODE_BAND60M_PTT, PTT_state); break; //60M 148 | case BAND_40M : GPIO_PTT_Out(DECODE_BAND40M_PTT, PTT_state); break; //40M 149 | case BAND_30M : GPIO_PTT_Out(DECODE_BAND30M_PTT, PTT_state); break; //30M 150 | case BAND_20M : GPIO_PTT_Out(DECODE_BAND20M_PTT, PTT_state); break; //20M 151 | case BAND_17M : GPIO_PTT_Out(DECODE_BAND17M_PTT, PTT_state); break; //17M 152 | case BAND_15M : GPIO_PTT_Out(DECODE_BAND15M_PTT, PTT_state); break; //15M 153 | case BAND_12M : GPIO_PTT_Out(DECODE_BAND12M_PTT, PTT_state); break; //12M 154 | case BAND_10M : GPIO_PTT_Out(DECODE_BAND10M_PTT, PTT_state); break; //10M 155 | case BAND_6M : GPIO_PTT_Out(DECODE_BAND6M_PTT, PTT_state); break; //6M 156 | case BAND_FM : GPIO_PTT_Out(DECODE_BANDFM_PTT, PTT_state); break; //6M 157 | case BAND_AIR : GPIO_PTT_Out(DECODE_BANDAIR_PTT, PTT_state); break; //6M 158 | //case BAND70 : GPIO_PTT_Out(0x01_PTT, PTT_state); break; //6M 159 | case BAND_2M : GPIO_PTT_Out(DECODE_BAND144_PTT, PTT_state); break; //2M 160 | case BAND_1_25M: GPIO_PTT_Out(DECODE_BAND222_PTT, PTT_state); break; //222 161 | case BAND_70cm : GPIO_PTT_Out(DECODE_BAND432_PTT, PTT_state); break; //432 162 | case BAND_33cm : GPIO_PTT_Out(DECODE_BAND902_PTT, PTT_state); break; //902 163 | case BAND_23cm : GPIO_PTT_Out(DECODE_BAND1296_PTT, PTT_state); break; //1296 164 | case BAND_13cm : GPIO_PTT_Out(DECODE_BAND2400_PTT, PTT_state); break; //2400 165 | case BAND_9cm : GPIO_PTT_Out(DECODE_BAND3400_PTT, PTT_state); break; //3400 166 | case BAND_6cm : GPIO_PTT_Out(DECODE_BAND5760_PTT, PTT_state); break; //5760M 167 | case BAND_3cm : GPIO_PTT_Out(DECODE_BAND10G_PTT, PTT_state); break; //10.368.1G 168 | case BAND_24G : GPIO_PTT_Out(DECODE_BAND24G_PTT, PTT_state); break; //24.192G 169 | case BAND_47G : GPIO_PTT_Out(DECODE_BAND47G_PTT, PTT_state); break; //47.1G 170 | case BAND_76G : GPIO_PTT_Out(DECODE_BAND76G_PTT, PTT_state); break; //76.1G 171 | case BAND_122G : GPIO_PTT_Out(DECODE_BAND122G_PTT, PTT_state); break; //122G 172 | case B_GENERAL : GPIO_PTT_Out(DECODE_B_GENERAL_PTT,PTT_state); break; //Any other band not in the list 173 | } 174 | } 175 | 176 | void GPIO_PTT_Out(uint8_t pattern, bool _PTT_state) 177 | { 178 | uint8_t PTT_state = _PTT_state ? 0xFF : 0; 179 | 180 | DPRINTF(" PTT state "); DPRINT(_PTT_state, BIN); 181 | DPRINTF(" PTT Output Binary "); DPRINTLN(pattern, BIN); 182 | 183 | //#ifndef IO_MODULE 184 | // DPRINTLNF(" GPIO_PTT_Out: IO_MODULE **NOT** Enabled"); 185 | //return; 186 | //#endif 187 | 188 | // Operate a relay anytime PT is high. Probably not useful if have more than 1 PTT but is here for a test 189 | // This is a M5Stack 1 rleay Unit. The 1 and 2 relay units oeprate on a grove port (B or C) with simple digital IO. 190 | // On a Care, Port A is the same pins as the rest of the internal i2c, operating a relay on them would screw up I2C likely. 191 | // The 4 relay unit is i2c addressed and normally plugs into Port A on the Corexx itself. 192 | // I2C on Port B is a separate IC2 port for the Core2 and Core3 193 | 194 | #if defined ( RELAY2 ) 195 | if (PTT_state && pattern) { 196 | digitalWrite(pinR1, HIGH); 197 | DPRINTLNF("Relay+++++++++PTT"); 198 | } 199 | else { 200 | digitalWrite(pinR1, LOW); 201 | DPRINTLNF("Relay---------PTT"); 202 | } 203 | #endif 204 | 205 | //PTT_state = !PTT_state; // Invert PTT 1 = TX, IO needs 0 to gnd for TX. 206 | 207 | //Serial.println((pattern & 0x10 & PTT_state) ? 0 : 1); 208 | 209 | #ifdef IO_MODULE 210 | // mask each bit and apply the 1 or 0 to the assigned pin 211 | if (BAND_DECODE_PTT_OUTPUT_PIN_0 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_0, (pattern & 0x01 & PTT_state) ? 1 : 0);} // bit 0 212 | if (BAND_DECODE_PTT_OUTPUT_PIN_1 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_1, (pattern & 0x02 & PTT_state) ? 1 : 1);} // bit 1 213 | if (BAND_DECODE_PTT_OUTPUT_PIN_2 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_2, (pattern & 0x04 & PTT_state) ? 1 : 0);} // bit 2 214 | if (BAND_DECODE_PTT_OUTPUT_PIN_3 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_3, (pattern & 0x08 & PTT_state) ? 1 : 0);} // bit 3 215 | if (BAND_DECODE_PTT_OUTPUT_PIN_4 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_4, (pattern & 0x10 & PTT_state) ? 1 : 0);} // bit 4 216 | if (BAND_DECODE_PTT_OUTPUT_PIN_5 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_5, (pattern & 0x20 & PTT_state) ? 1 : 0);} // bit 5 217 | if (BAND_DECODE_PTT_OUTPUT_PIN_6 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_6, (pattern & 0x40 & PTT_state) ? 1 : 0);} // bit 6 218 | if (BAND_DECODE_PTT_OUTPUT_PIN_7 != GPIO_PIN_NOT_USED) {module.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_7, (pattern & 0x80 & PTT_state) ? 1 : 0);} // bit 7 219 | #endif 220 | } 221 | 222 | /* Not used for the 4-In/8-Out module, all are fixed direction 223 | void Decoder_GPIO_Pin_Setup(void) 224 | { 225 | // using 8 bits since the ouput pattern is 1 byte. Can use thenm any way you want. 226 | // The pins used here are defined in RadioConfig. The one GPIO_SWx_PIN were designated as hardware switches in the Teensy SDR 227 | // If using the Teensy SDR motherboard and you have physical switch hardware on any of these then you need to pick alernate pins. 228 | // Most pins are alrewady goiven a #define bname in RadioCOnfig, substitute the right ones in here. Make sure they are free. 229 | 230 | // set up our Decoder output pins if enabled 231 | if (BAND_DECODE_OUTPUT_PIN_0 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_0, OUTPUT); // bit 0 232 | if (BAND_DECODE_OUTPUT_PIN_1 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_1, OUTPUT); // bit 1 233 | if (BAND_DECODE_OUTPUT_PIN_2 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_2, OUTPUT); // bit 2 234 | if (BAND_DECODE_OUTPUT_PIN_3 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_3, OUTPUT); // bit 3 235 | if (BAND_DECODE_OUTPUT_PIN_4 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_4, OUTPUT); // bit 4 236 | if (BAND_DECODE_OUTPUT_PIN_5 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_5, OUTPUT); // bit 5 237 | if (BAND_DECODE_OUTPUT_PIN_6 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_6, OUTPUT); // bit 6 238 | if (BAND_DECODE_OUTPUT_PIN_7 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_OUTPUT_PIN_7, OUTPUT); // bit 7 239 | 240 | // set up our PTT breakout pins if enabled 241 | if (BAND_DECODE_PTT_OUTPUT_PIN_0 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_0, OUTPUT); // bit 0 242 | if (BAND_DECODE_PTT_OUTPUT_PIN_1 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_1, OUTPUT); // bit 1 243 | if (BAND_DECODE_PTT_OUTPUT_PIN_2 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_2, OUTPUT); // bit 2 244 | if (BAND_DECODE_PTT_OUTPUT_PIN_3 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_3, OUTPUT); // bit 3 245 | if (BAND_DECODE_PTT_OUTPUT_PIN_4 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_4, OUTPUT); // bit 4 246 | if (BAND_DECODE_PTT_OUTPUT_PIN_5 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_5, OUTPUT); // bit 5 247 | if (BAND_DECODE_PTT_OUTPUT_PIN_6 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_6, OUTPUT); // bit 6 248 | if (BAND_DECODE_PTT_OUTPUT_PIN_7 != GPIO_PIN_NOT_USED) pinMode(BAND_DECODE_PTT_OUTPUT_PIN_7, OUTPUT); // bit 7 249 | 250 | DPRINTLNF("Decoder_GPIO_Pin_Setup: Pin Mode Setup complete"); 251 | } 252 | */ 253 | 254 | //MODULE_4IN8OUT module; // done in main ino. Be sure toi run Wire(21,22); before this in setup(0) 255 | void Module_4in_8out_setup() 256 | { 257 | 258 | #if defined ( RELAY2 ) 259 | // For the 1 or 2-Relay modules if used. Plug into Port C. Port B only 1 pin 26 worked con the Core Basic. 260 | // Port A pins are internal i2c and would conflict with relay usage 261 | pinMode(pinR1, OUTPUT); // Set pin to output mode. 262 | pinMode(pinR2, OUTPUT); // Set pin to output mode. 263 | #endif 264 | 265 | #ifdef IO_MODULE 266 | uint8_t counter = 0; 267 | #ifdef CONFIG_IDF_TARGET_ESP32S3 268 | Serial.println("Decoder: CoreS3 i2c pins used"); 269 | while (!module.begin(&Wire1, 12, 11, MODULE_4IN8OUT_ADDR) && counter < 4) // for cores3 270 | #else 271 | while (!module.begin(&Wire, 21, 22, MODULE_4IN8OUT_ADDR) && counter < 4) //for core basic 272 | #endif 273 | { 274 | Serial.println("4IN8OUT INIT ERROR, Check Module is plugged in tight!"); 275 | //M5.Lcd.drawString("4IN8OUT INIT ERROR", 5, 20, 4); 276 | //M5.Lcd.drawString("Check IO module is plugged in!", 5, 40, 4); 277 | delay(10); 278 | counter++; 279 | } 280 | if (counter < 4) 281 | Serial.println("4IN8OUT INIT Success"); 282 | #endif 283 | } 284 | 285 | long interval = 0; 286 | bool level = false; 287 | 288 | 289 | //.setOutput(BAND_DECODE_PTT_OUTPUT_PIN_0, pattern & 0x01 & PTT_state); 290 | uint8_t Module_4in_8out_Input_scan(void) 291 | { 292 | #ifdef IO_MODULE 293 | uint8_t pattern = 0; 294 | pattern |= module.getInput(0) ; 295 | pattern |= module.getInput(1) << 1; 296 | pattern |= module.getInput(2) << 2; 297 | pattern |= module.getInput(3) << 3; 298 | return pattern & 0x0F; 299 | #else 300 | return 0; 301 | #endif 302 | } 303 | 304 | #endif // DECODER FILE -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/Decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef DECODER_H_ 2 | #define DECODER_H_ 3 | 4 | #include 5 | 6 | void Band_Decode_Output(uint8_t band); 7 | void GPIO_Out(uint8_t pattern); 8 | void PTT_Output(uint8_t band, bool PTT_state); 9 | void GPIO_PTT_Out(uint8_t pattern, bool PTT_state); 10 | void Module_4in_8out_Output_test(); 11 | uint8_t Module_4in_8out_Input_scan(void); 12 | void Module_4in_8out_setup(); 13 | 14 | enum band_idx { BAND_AM, 15 | BAND_160M, 16 | BAND_80M, 17 | BAND_60M, 18 | BAND_40M, 19 | BAND_30M, 20 | BAND_20M, 21 | BAND_17M, 22 | BAND_15M, 23 | BAND_12M, 24 | BAND_10M, 25 | BAND_6M, 26 | BAND_FM, 27 | BAND_AIR, 28 | BAND_2M, 29 | BAND_1_25M, 30 | BAND_70cm, 31 | BAND_33cm, 32 | BAND_23cm, 33 | BAND_13cm, 34 | BAND_9cm, 35 | BAND_6cm, 36 | BAND_3cm, 37 | BAND_24G, 38 | BAND_47G, 39 | BAND_76G, 40 | BAND_122G, 41 | B_GENERAL, 42 | NUM_OF_BANDS }; 43 | 44 | #define GPIO_PIN_NOT_USED 255 // use for any pin not in use below 45 | 46 | // Make IO Pin assignments here. 47 | // These are 8 MOSFET outputs on the 4-In/8-Out module 48 | #define GPIO_MOD_O_PIN_0 0 49 | #define GPIO_MOD_O_PIN_1 1 50 | #define GPIO_MOD_O_PIN_2 2 51 | #define GPIO_MOD_O_PIN_3 3 52 | #define GPIO_MOD_O_PIN_4 4 53 | #define GPIO_MOD_O_PIN_5 5 54 | #define GPIO_MOD_O_PIN_6 6 55 | #define GPIO_MOD_O_PIN_7 7 56 | 57 | // These are te 4 input pins on the IO module 58 | #define GPIO_MOD_I_PIN_0 0 59 | #define GPIO_MOD_I_PIN_1 1 60 | #define GPIO_MOD_I_PIN_2 2 61 | #define GPIO_MOD_I_PIN_3 3 62 | 63 | // BAND DECODE INPUT PINS 64 | // Assign your pins of choice. Use a number or one of the existing #define number names 65 | // Make sure they are not monitored by the code as a button or other use like an encoder. 66 | // If not used set to GPIO_PIN_NOT_USED since there is no pin 255. 67 | #define BAND_DECODE_INPUT_PIN_0 GPIO_MOD_I_PIN_0 // bit 0 68 | #define BAND_DECODE_INPUT_PIN_1 GPIO_MOD_I_PIN_1 // bit 1 69 | #define BAND_DECODE_INPUT_PIN_2 GPIO_MOD_I_PIN_2 // bit 2 70 | #define BAND_DECODE_INPUT_PIN_3 GPIO_MOD_I_PIN_3 // bit 3 71 | 72 | // BAND DECODE OUTPUT PINS 73 | // Assign your pins of choice. Use a number or one of the existing #define number names 74 | // Make sure they are not monitored by the code as a button or other use like an encoder. 75 | // If not used set to GPIO_PIN_NOT_USED since there is no pin 255. 76 | #define BAND_DECODE_OUTPUT_PIN_0 GPIO_MOD_O_PIN_0 // bit 0 77 | #define BAND_DECODE_OUTPUT_PIN_1 GPIO_MOD_O_PIN_1 // bit 1 78 | #define BAND_DECODE_OUTPUT_PIN_2 GPIO_MOD_O_PIN_2 // bit 2 79 | #define BAND_DECODE_OUTPUT_PIN_3 GPIO_MOD_O_PIN_3 // bit 3 80 | #define BAND_DECODE_OUTPUT_PIN_4 GPIO_PIN_NOT_USED // bit 4 81 | #define BAND_DECODE_OUTPUT_PIN_5 GPIO_PIN_NOT_USED // bit 5 82 | #define BAND_DECODE_OUTPUT_PIN_6 GPIO_PIN_NOT_USED // bit 6 83 | #define BAND_DECODE_OUTPUT_PIN_7 GPIO_PIN_NOT_USED // bit 7 84 | 85 | // BAND DECODE PTT OUTPUT PINS 86 | // Assign your pins of choice. Use a number or one of the existing #define number names 87 | // Make sure they are not monitored by the code as a button or other use like an encoder. 88 | // If not used set to GPIO_PIN_NOT_USED since there is no pin 255. 89 | #define BAND_DECODE_PTT_OUTPUT_PIN_0 GPIO_PIN_NOT_USED // bit 0 90 | #define BAND_DECODE_PTT_OUTPUT_PIN_1 GPIO_PIN_NOT_USED // bit 1 91 | #define BAND_DECODE_PTT_OUTPUT_PIN_2 GPIO_PIN_NOT_USED // bit 2 92 | #define BAND_DECODE_PTT_OUTPUT_PIN_3 GPIO_PIN_NOT_USED // bit 3 93 | #define BAND_DECODE_PTT_OUTPUT_PIN_4 GPIO_MOD_O_PIN_4 // bit 4 94 | #define BAND_DECODE_PTT_OUTPUT_PIN_5 GPIO_MOD_O_PIN_5 // bit 5 95 | #define BAND_DECODE_PTT_OUTPUT_PIN_6 GPIO_MOD_O_PIN_6 // bit 6 96 | #define BAND_DECODE_PTT_OUTPUT_PIN_7 GPIO_MOD_O_PIN_7 // bit 7 97 | 98 | // ************************************************************************************************************* 99 | // 100 | // Below are fixed assignments. User assignments are above 101 | // 102 | //************************************************************************************************************** 103 | // Band Decode Output patterns. 104 | // By default using BCD pattern following the Elecraft K3 HF-TRN table. 5 bits are used. Bit 4 =1 is VHF+ group 105 | #define DECODE_BANDAM (0x00) //160M 106 | #define DECODE_BAND160M (0x00) //160M 107 | #define DECODE_BAND80M (0x00) //80M 108 | #define DECODE_BAND60M (0x00) //60M 109 | #define DECODE_BAND40M (0x00) //40M 110 | #define DECODE_BAND30M (0x00) //30M 111 | #define DECODE_BAND20M (0x00) //20M 112 | #define DECODE_BAND17M (0x00) //17M 113 | #define DECODE_BAND15M (0x00) //15M 114 | #define DECODE_BAND12M (0x00) //12M 115 | #define DECODE_BAND10M (0x00) //10M 116 | #define DECODE_BAND6M (0x00) //6M 117 | #define DECODE_BANDFM (0x00) //6M 118 | #define DECODE_BANDAIR (0x00) //6M 119 | //#define DECODE_BAND70 (0x00) //70MHz 120 | #define DECODE_BAND144 (0x00) //2M 121 | #define DECODE_BAND222 (0x00) //222 122 | #define DECODE_BAND432 (0x00) //432 123 | #define DECODE_BAND902 (0x01) //902 124 | #define DECODE_BAND1296 (0x02) //1296 125 | #define DECODE_BAND2400 (0x04) //2400 126 | #define DECODE_BAND3400 (0x00) //3400 127 | #define DECODE_BAND5760 (0x00) //5760M 128 | #define DECODE_BAND10G (0x00) //10.368.1G 129 | #define DECODE_BAND24G (0x00) //24.192G 130 | #define DECODE_BAND47G (0x00) //47.1G 131 | #define DECODE_BAND76G (0x00) //76.1G 132 | #define DECODE_BAND122G (0x00) //122G 133 | #define DECODE_B_GENERAL (0x00) // Non-Ham Band 134 | 135 | // Band Decoder Output patterns for PTT routing. 136 | // BAn example would be the BCD pattern following the Elecraft K3 HF-TRN table. 5 bits are used. Bit 4 =1 is VHF+ group 137 | // here we have only 1 4-IN/8-Out module installed configured as 4x decode outputs and 4 PTT outputs for PTT routing to 4 amps/xvtrs 138 | // Here the PTT lines are on the upper half of the group of 8 module outputs so we set values on the upper nibble, the lower will be ignored. 139 | // if not used enter 0x00 140 | #define DECODE_BANDAM_PTT (0x00) //160M_PTT 141 | #define DECODE_BAND160M_PTT (0x00) //160M_PTT 142 | #define DECODE_BAND80M_PTT (0x00) //80M_PTT 143 | #define DECODE_BAND60M_PTT (0x00) //60M_PTT 144 | #define DECODE_BAND40M_PTT (0x00) //40M_PTT 145 | #define DECODE_BAND30M_PTT (0x00) //30M_PTT 146 | #define DECODE_BAND20M_PTT (0x00) //20M_PTT 147 | #define DECODE_BAND17M_PTT (0x00) //17M_PTT 148 | #define DECODE_BAND15M_PTT (0x00) //15M_PTT 149 | #define DECODE_BAND12M_PTT (0x00) //12M_PTT 150 | #define DECODE_BAND10M_PTT (0x00) //10M_PTT 151 | #define DECODE_BAND6M_PTT (0x00) //6M_PTT 152 | #define DECODE_BANDFM_PTT (0x00) //6M_PTT 153 | #define DECODE_BANDAIR_PTT (0x00) //6M_PTT 154 | //#define DECODE_BAND70_PTT (0x00) //70M_PTTHz 155 | #define DECODE_BAND144_PTT (0x00) //2M_PTT 156 | #define DECODE_BAND222_PTT (0x00) //222_PTT 157 | #define DECODE_BAND432_PTT (0x00) //432_PTT 158 | #define DECODE_BAND902_PTT (0x10) //902_PTT 159 | #define DECODE_BAND1296_PTT (0x20) //1296_PTT 160 | #define DECODE_BAND2400_PTT (0x40) //2400_PTT 161 | #define DECODE_BAND3400_PTT (0x00) //3400_PTT 162 | #define DECODE_BAND5760_PTT (0x00) //5760_PTT 163 | #define DECODE_BAND10G_PTT (0x00) //10.368.1G_PTT 164 | #define DECODE_BAND24G_PTT (0x00) //24.192G_PTT 165 | #define DECODE_BAND47G_PTT (0x00) //47.1G_PTT 166 | #define DECODE_BAND76G_PTT (0x00) //76.1G_PTT 167 | #define DECODE_BAND122G_PTT (0x00) //122G_PTT 168 | #define DECODE_B_GENERAL_PTT (0x00) // Non-Ham Band 169 | 170 | 171 | #endif -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/M5StampC3U_Decoder.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | ICOM CI-V Band Decoder and PTT breakout 3 | K7MDL 8/2024 4 | 5 | BT Classic Serial or USB connection for IC-705 6 | USB for other models 7 | Runs on M5Stack Core Basic, Core2. All have issues with USB Host compatibility as of Aug 2024. 8 | 9 | This is very basic and very small self-contained CI-V band decoder that can display transverter frequency with suitable offsets, 10 | change bands with touch or external input and output (switch, radio decoder outputs), 2, 4, 8, or more I/O outputs. 11 | Depending on the stacking module(s) chosen, can be relays, MOSFETs (1A @ 24VDC), or a proto board for DIY interfaces. 12 | They also have a 9 to 24VDC power supply input and batteries of various sized. 13 | With the small size you can stick it on the back of a radio or the back of a dish on a tropid. 14 | Generally no hardware packaging is required. Just plug together and wire up to the connectors. 15 | There are several code projects that are similar, some do not have the IO., this is a customization of one of them. 16 | My 905-CIV project is Teensy based and I have not added WFi or BT to it yet. This M5Stack approach is a quick no-build mini solution 17 | enhanced to do some multi-byte CI-V messages and monitor PTT status to echo it out to the seledcted band's amps and/or Xvtrs and antenna relays 18 | There is opportunity to do some fancy graphics, present some shortcut buttons for things like memories and a band select menu that knows about transverters. 19 | 20 | For this to work with the 705 Bluetooth, it must be run on a chipset and BT code library that supports BT Classic serial port profile. 21 | The newer M5Stack CoreS3 (ESPS3 based) and CoreS3SE apepar to only support BT , mesh and BLE, is not backward compatible with BT Classic SSP/ 22 | The profiles listed on the 705 BT Info page lists SPP and LE. I suspect the LE is for audio connections and not serial. 23 | Maybe that will chanbge in the future, no one seems to have in insight into this. I can discover the radio with BLE, but no connection yet, 24 | still working on it in my spare time. 25 | 26 | This will Pair BT with a Passkey, no action required on teeh decoder for passkey or for radio address 27 | 28 | To use this with BT on the IC-705 you first pair it on the 705. 29 | Once paired, this device will auto-(re)connect. 30 | This device operates in Master mode so power up order does not matter. 31 | On first connection after pairing the radio's CI-V address is discovered and used so there is no configuraton required 32 | 33 | For BT connection the IC-705 side settings required are 34 | 1. Bluetooth ON 35 | 2. AutoConnect ON 36 | 3. Data-Device-> Serialport Function -> CI-V (Echo Back ON) 37 | 4. Pair the radio to this device: 38 | On the 705 menu SET -> BLUETOOTH SET -> Pairing Reception 39 | Power on the BT Band Decoder. If it times out, power cycle the decoder to retry 40 | "IC-705 Decoder 1" device name will display when it is discovered by the radio 41 | The radio will prompt to confirm a passkey number, it should match the decoder display if any attached or on a serial terminal 42 | Press OK 43 | The Decoder will auto accept the passkey confirm from the radio and connect and start operating 44 | It is now paired and connected and will auto-reconnect as needed. 45 | 46 | 47 | Tested on the IC-705 (BT andf USB) and IC-905 (USB). Should work with other models like the 9700. 48 | 49 | This M5Stack decoder is a mini version of my large USB CI-V Band Decoder for the 905 and 705 which is built on a Teensy and passes both of radio's 2 50 | USB serial port data (CI-V and GPS) on to a optional PC. It has options for 7" or 4.3" touch display or encoders and can do radio control allowing 51 | for transverter control with each Xvtr band keeping its own parameters. 52 | https://github.com/K7MDL2/ICOM_IC-905_CIV 53 | 54 | I have a hardware/softaare big Band decoder at https://github.com/K7MDL2/RF-Power-Meter-V1 55 | 56 | The Teensy based 905 decoder uses the UI and control framewark from my Teensy SDR project at https://github.com/K7MDL2/KEITHSDR 57 | 58 | Derived from the following project, thanks! 59 | _________________________________________________ 60 | T1 Interface 61 | V2.0 (12.09.2023) 62 | Peter Jonas DL5DLA 63 | 64 | This code, running on an ESP32, requests the current frequency 65 | from the ICOM IC-705 via bluetooth connection, and sends the 66 | related band number to the Elecraft T1. Based on the band 67 | number, the T1 applies the stored tuning settings. A re-tuning 68 | is possible directly after changing the frequency. For the next 69 | few seconds the T1 waits for a carrier and will tune again. 70 | 71 | For first use, the ESP32 must be paired to the IC-705. Later on 72 | the ESP32 should be powered already, before the IC-705 is 73 | switched on. If someone knows how the bluetooth connection 74 | can be setup the other way around (switch on the IC-705, then 75 | the esp32), please let me know. 76 | 77 | The code is compiled on PlatformIO, but should also work using 78 | the Arduino IDE. 79 | 80 | This code is based on the code from 81 | Ondrej Kolonicny (ok1cdj) https://github.com/ok1cdj/IC705-BT-CIV 82 | and 83 | Matthew Robinson (VK6MR) https://zensunni.org/blog/2011/01/19/arduino-elecraft-t1-interface/ 84 | 85 | Many thanks to both for their example codes giving me the first insight on how 86 | to deal with the communication between the IC-705 and T1. 87 | 88 | In this version the ESP32 device is set as bluetooth master and the IC-705 as client. 89 | Due to this the bluetooth connection is more robust, and the IC-705 is reconnected 90 | no matter if the TRX or the ESP32 is switched off temporarly. 91 | 92 | If you are using BT Classic SPP then it is important to set the "bd_address" in the next lines below! 93 | *************************************************************************/ 94 | #ifndef _BT_USB_ 95 | #define _BT_USB_ 96 | 97 | #define M5STAMPC3U 98 | 99 | #include "M5Unified.h" 100 | #include 101 | #include "time.h" 102 | 103 | #define IC705 0xA4 104 | #define IC905 0xAC 105 | #define RADIO_ADDR IC705 106 | 107 | // NOTE: With a single USB virtual Serial port to the PC, ANY debug on Serial will interfere with a program like WSJT-X passing through to teh radio. 108 | 109 | #define CONTROLLER_ADDRESS 0xE0 //Controller address 110 | #define BROADCAST_ADDRESS 0x00 111 | 112 | #define START_BYTE 0xFE // Start byte 113 | #define STOP_BYTE 0xFD // Stop byte 114 | 115 | #define CMD_READ_FREQ 0x03 // Read operating frequency data 116 | 117 | #define POLL_PTT_DEFAULT 187 // poll the radio for PTT status odd numbers to stagger them a bit 118 | // USB on both the 705 and 905 respond to PTT requests slower on USB than BT on the 705. 119 | // Also polls the wired inputs Can go down to 25-45. When using wired PTT set this slow. 120 | #define POLL_PTT_USBHOST 162 // Dynamically changes value based on detected radio address. 121 | // By observation, on USB, the radio only responds once every few seconds when the radio \ 122 | // has not changed states. It will immediately reply to a poll if the Tx state changed. \ 123 | // Still have to poll fast for controlling external PTT, most requests will not be answered. \ 124 | // Unlike other modes. BT seems to answer every request. USB2 engine is likely the same in \ 125 | // all radios, where BT got a capacity upgrade. The 905 acts the same as the 905 (905 is USB only) \ 126 | // Have not compared to a LAN connection. 127 | #define POLL_RADIO_FREQ 308 // poll the radio for frequency 128 | #define POLL_RADIO_UTC 998 // poll radio for time and location 129 | #define POLL_RADIO_MODE 1101 // poll radio for extended mode, filter and datamode 130 | #define POLL_RADIO_AGC 1203 // poll radio for AGC 131 | #define POLL_RADIO_ATTN 1305 // poll radio for atten status 132 | #define POLL_RADIO_PRE 1404 // poll radio for preamp status 133 | 134 | // Chose the combination needed. Note that at least one service must be enabled. 135 | #define BLE // Core 3. Maybe works on Core 2, TBD 136 | //#define USBHOST // if no BLE or BTCLASSIC this must be enabled. 137 | //#define RELAY2 // enable 1 or 2 channel UNIT-RELAY module on Port A, B or C 138 | //#define RELAY4 // enable the i2c Relay-4 Unit, typically plugged into Port A (i2C). 139 | 140 | //#define PC_PASSTHROUGH // fwd through BT or USBHOST data to a PC if connected. All debug must be off! 141 | 142 | #ifndef PC_PASSTHROUGH // shut off by default when PASSTHRU MODE is on 143 | #define PRINT_VFO_TO_SERIAL // uncomment to visually see VFO updates from the radio on Serial 144 | #define PRINT_PTT_TO_SERIAL // uncomment to visually see PTT updates from the radio on Serial 145 | #endif 146 | 147 | //-------------------------------------- END OF USER CONFIG --------------------------------------------------------------- 148 | 149 | //************************************************************************************************************************************* 150 | //************************************* should not be any user config below this point ********************************************* 151 | //************************************************************************************************************************************* 152 | 153 | //#define SSP // use BT SSP - pair with a passkey 154 | 155 | // After #defines 156 | #include "DebugPrint.h" 157 | #include "CIV.h" 158 | 159 | // Function prototypes: 160 | void configRadioBaud(uint16_t); 161 | uint8_t readLine(void); 162 | bool searchRadio(); 163 | void sendCatRequest(const uint8_t cmd_num, const uint8_t Data[], const uint8_t Data_len); // first byte in Data is length 164 | void printFrequency(void); 165 | void processCatMessages(); 166 | void read_Frequency(uint8_t data_len); 167 | void draw_new_screen(void); 168 | //unsigned int hexToDec(String hexString); 169 | void display_Freq(uint64_t _freq, bool _force); 170 | void display_Time(uint8_t _UTC, bool _force); 171 | void display_Xvtr(bool _band, bool _force); 172 | void display_PTT(bool _PTT_state, bool _force); 173 | void display_Band(uint8_t _band, bool _force); 174 | void display_Grid(char _grid[], bool _force); 175 | void SetFreq(uint64_t Freq); 176 | 177 | const uint64_t decMulti[] = { 100000000000, 10000000000, 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; 178 | 179 | #define BAUD_RATES_SIZE 4 180 | const uint16_t baudRates[BAUD_RATES_SIZE] = { 19200, 9600, 4800, 1200 }; 181 | 182 | struct Bands { 183 | char band_name[6]; // Freindly name or label. Default here but can be changed by user. 184 | uint64_t edge_lower; // band edge limits for TX and for when to change to next band when tuning up or down. 185 | uint64_t edge_upper; 186 | uint64_t Xvtr_offset; // Offset to add to radio frequency. 187 | // When all is correct, it will be within the band limits and allow PTT and Band decoder outputs 188 | uint64_t VFO_last; // store the last used frequency on each band. 189 | // for XVTR bands subtract the LO offset and send the result to the radio 190 | uint8_t mode_idx; // current mode stored as indexc to the modelist table. 191 | uint8_t filt; // current fiult soreds in teh modelist table 192 | uint8_t datamode; 193 | uint8_t agc; // store last agc. Some radio/band/mode combos only have 1. 194 | uint8_t preamp; // some bands there is no preamp (2.4G+ on 905). Some radios/bands/modes combos have 1 preamp level, others have 2 levels. 195 | uint8_t atten; // some bands there is no atten (some on 905). Some radios/bands/mode combos have 1 atten level, others have more. 196 | }; 197 | 198 | extern uint8_t USBHost_ready; // 0 = not mounted. 1 = mounted, 2 = system not initialized 199 | extern bool USBH_connected; 200 | extern bool restart_USBH_flag; 201 | extern bool restart_BT_flag; 202 | extern uint16_t background_color; 203 | extern uint64_t frequency; 204 | extern bool update_radio_settings_flag; 205 | 206 | #endif -------------------------------------------------------------------------------- /Archive/M5StampC3U_Decoder/M5StampC3U_Decoder.ino: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | ICOM CI-V BLE Band Decoder and PTT breakout - M5Stamp-C3U version (headless) 3 | K7MDL 8/2024 4 | 5 | BT BLE Serial connection for IC-705. 6 | 7 | Runs on M5Stamp C3U 8 | 9 | Intended use scenario is to be a CI-V serial bus USB to Bluetooth BLE converter for non-BT enabled USB equipped ICOM radios 10 | 11 | For now this program does these main things: 12 | 1. Pass through in both direction Radio CI-V data if a PC is connect 13 | This enables an optional USB PC connection for things like logging and WSJT-X). 14 | 2. Monitor Radio Frequency (active VFO) and display it, adding any band offset the band decoder input or User Input selects 15 | This enables Transverter selection, enable a band specific amplifier, or change antenna relays, all per band. 16 | 3. Monitor PTT and pass it through to a selected GPIO pin which in turn controls a port on the 4In/8Out M5Stack module. 17 | This enables PTT breakout per band 18 | 4. Optionally connect to the radio by USB Host or by BT BLE (IC-705 only so far) 19 | 5. Radios tested so far - IC-705 and IC-905 20 | 6. i2c can be brought out on a connector to drive peripherals like relays 21 | 22 | Down the road, probably on BLE mesh, this could bridge a radio to a PC completely by BLE. 23 | 24 | 25 | *********************************************************************/ 26 | 27 | #include "M5StampC3U_Decoder.h" 28 | #include "DebugPrint.h" 29 | 30 | // Language ID: English 31 | #define LANGUAGE_ID 0x0409 32 | 33 | #ifdef _PC_PASSTHRU // This is unused code, saving for reference 34 | // forward Serial <-> SerialHost 35 | void forward_serial(void) { 36 | uint8_t buf[64]; 37 | //Serial.print("^"); 38 | // Serial -> SerialHost 39 | if (Serial.available()) { 40 | size_t count = Serial.read(buf, sizeof(buf)); 41 | if (SerialHost && SerialHost.connected()) { 42 | SerialHost.write(buf, count); 43 | SerialHost.flush(); 44 | } 45 | } 46 | 47 | // SerialHost -> Serial 48 | if (SerialHost.connected() && SerialHost.available()) { 49 | size_t count = SerialHost.read(buf, sizeof(buf)); 50 | Serial.write(buf, count); 51 | Serial.flush(); 52 | } 53 | } 54 | #endif 55 | 56 | extern void BLE_Setup(); 57 | extern void BLE_loop(); 58 | extern void app_loop(); 59 | extern void Scan_BLE_Servers(); 60 | extern void app_setup(); 61 | bool BtnA_pressed = false; 62 | bool BtnB_pressed = false; 63 | bool BtnC_pressed = false; 64 | uint64_t frequency = 0; 65 | bool USBH_connected = false; 66 | bool restart_BT_flag = false; 67 | // 68 | // Main Setup for ESP32 69 | // 70 | void setup() { 71 | 72 | Serial.begin(115200); 73 | while ( !Serial ) delay(10); // wait for native usb 74 | 75 | app_setup(); // setup app stuff 76 | 77 | #ifdef BLE 78 | //BLE_Setup(); 79 | //Scan_BLE_Servers(); 80 | #endif 81 | 82 | Serial.println("Setup Done"); 83 | } 84 | 85 | //***************************************************************************** 86 | // 87 | // Main Loop. Call app_setup() to run main application 88 | // 89 | //***************************************************************************** 90 | 91 | void loop() { 92 | 93 | static int32_t loop_time = 0; 94 | static int32_t loop_max_time = 0; 95 | int32_t loop_time_threshold = 30; 96 | static int32_t prev_loop_time = 0; 97 | 98 | loop_time = millis(); // watermark 99 | 100 | #ifdef _PC_PASSTHRU // Unused code, save for reference or test 101 | // allow a PC to talk o teh radio and opposite. Need debug shuto ff typically 102 | forward_serial(); 103 | #endif 104 | 105 | //Serial.print("."); // causes crashes on PC due to too high data rate 106 | 107 | #ifdef BLE 108 | BLE_loop(); 109 | #endif 110 | 111 | app_loop(); // call to application main loop - moved to FreeRTOS task 112 | 113 | // Measure our current and max loop times 114 | int32_t temp_time = millis() - loop_time; // current loop duration 115 | 116 | if ((temp_time > loop_max_time) || temp_time > loop_time_threshold) { 117 | if (temp_time > loop_max_time) 118 | loop_max_time = temp_time; 119 | //Serial.print("!"); // Turn on to see RTOS scheduling time allocated visually 120 | if (loop_max_time > loop_time_threshold) { 121 | Serial.printf("! loop time > %d current time = %d max time seen %d\n", loop_time_threshold, temp_time, loop_max_time); 122 | //Serial.println(" App loop time > 500!"); 123 | 124 | //if (loop_max_time > 3000 && SerialBT.isClosed() && SerialBT.isReady()) 125 | // restart_BT(); // try this as a USBHost lockup failover short of having the btn task 126 | } // delete and restart the app task, or even the USBHost task 127 | else { 128 | ; // nothing 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/BLE.cpp: -------------------------------------------------------------------------------- 1 | #include "HWCDC.h" 2 | /* 3 | * IC705_BLE_Decoder_Simple.ino 4 | * 5 | * Central Mode (client) BLE UART for ESP32 - Tested on CoreS3 SE 6 | * 7 | * Modifed by K7MDL Aug 2024 for BLE Serial port (uart) connection to the IC-705 via BLE serial on a M5Stack Core3 and Core 3 SE. Tested on a SE version 8 | * 9 | * This is a simplified example program showing a BLE connection to an IC-705 and getting CI-V frequency and PTT state. 10 | * The UI is simply a title, frequency, band number, and PTT status, with PTT (Rx/Tx) turning red during Tx. 11 | * Future example programs could show more info on the display, process button touches, and have configurable band decoder outputs 12 | * 13 | *********************************************** Usage ************************************************************************* 14 | * 15 | * To use: 16 | * 1. On the IC-705 press menu 17 | * 2. Navigate to to Set -> Bluetooth Set -> <> 18 | * 3. The device will pair silently with the radio and display the given name in the Pairing Connect page. 19 | * 20 | * Once paired it will auto-reconnect as long as it is paired with the radio. 21 | * The name shown in the Pairing/Connect menu is hard coded today. See below byte arrays to edit. 22 | * 23 | ******************************** Below is the original code header/credits ************************************************** 24 | * 25 | * This sketch is a central mode (client) Nordic UART Service (NUS) that connects automatically to a peripheral (server) 26 | * Nordic UART Service. NUS is what most typical "blueart" servers emulate. This sketch will connect to your BLE uart 27 | * device in the same manner the nRF Connect app does. 28 | * 29 | * Once connected this sketch will switch notification on using BLE2902 for the charUUID_TX characteristic which is the 30 | * characteristic that our server is making data available on via notification. The data received from the server 31 | * characteristic charUUID_TX will be printed to Serial on this device. Every five seconds this device will send the 32 | * string "Time since boot: #" to the server characteristic charUUID_RX, this will make that data available in the BLE 33 | * uart and trigger a notifyCallback or similar depending on your BLE uart server setup. 34 | * 35 | * 36 | * A brief explanation of BLE client/server actions and rolls: 37 | * 38 | * Central Mode (client) - Connects to a peripheral (server). 39 | * -Scans for devices and reads service UUID. 40 | * -Connects to a server's address with the desired service UUID. 41 | * -Checks for and makes a reference to one or more characteristic UUID in the current service. 42 | * -The client can send data to the server by writing to this RX Characteristic. 43 | * -If the client has enabled notifications for the TX characteristic, the server can send data to the client as 44 | * notifications to that characteristic. This will trigger the notifyCallback function. 45 | * 46 | * Peripheral (server) - Accepts connections from a central mode device (client). 47 | * -Advertises a service UUID. 48 | * -Creates one or more characteristic for the advertised service UUID 49 | * -Accepts connections from a client. 50 | * -The server can send data to the client by writing to this TX Characteristic. 51 | * -If the server has enabled notifications for the RX characteristic, the client can send data to the server as 52 | * notifications to that characteristic. This the default function on most "Nordic UART Service" BLE uart sketches. 53 | * 54 | * 55 | * Copyright <2018> 56 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 57 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 58 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 59 | * permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright 60 | * notice and this permission notice shall be included in all copies or substantial portions of the Software. THE 61 | * SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 62 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 63 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 64 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 65 | * 66 | * 67 | * Based on the "BLE_Client" example by Neil Kolban: 68 | * https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/BLE_client/BLE_client.ino 69 | * With help from an example by Andreas Spiess: 70 | * https://github.com/SensorsIot/Bluetooth-BLE-on-Arduino-IDE/blob/master/Polar_Receiver/Polar_Receiver.ino 71 | * Nordic UART Service info: 72 | * https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v14.0.0%2Fble_sdk_app_nus_eval.html 73 | * 74 | */ 75 | #define BLE_ 76 | #ifdef BLE_ 77 | 78 | //#include "M5Stack_CI-V_Band_Decoder.h" 79 | #include "DebugPrint.h" 80 | #include "BLEDevice.h" 81 | #include "esp_bt_main.h" 82 | #include "esp_bt_device.h" 83 | #include "BLEScan.h" 84 | //#include "CIV.h" 85 | #include "sdkconfig.h" 86 | #if defined(CONFIG_BLUEDROID_ENABLED) 87 | #include 88 | #include 89 | #include "BLEAdvertisedDevice.h" 90 | #include "BLEClient.h" 91 | #include "RTOS.h" 92 | #include "BLE.h" 93 | //#include "BLEAddress.h" 94 | 95 | //#define WATCH_BLE_SERIAL 96 | 97 | // The remote Nordic UART service service we wish to connect to. 98 | // This service exposes two characteristics: one for transmitting and one for receiving (as seen from the client). 99 | static BLEUUID serviceUUID("14cf8001-1ec2-d408-1b04-2eb270f14203"); 100 | 101 | // The characteristics of the above service we are interested in. 102 | // The client can send data to the server by writing to this characteristic. 103 | static BLEUUID charUUID_RX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // RX Characteristic 104 | 105 | // If the client has enabled notifications for this characteristic, 106 | // the server can send data to the client as notifications. 107 | static BLEUUID charUUID_TX("14cf8002-1ec2-d408-1b04-2eb270f14203"); // TX Characteristic 108 | 109 | // For testing I hard coded the pairing messages to the IC-705! 110 | 111 | // UUID, 41 bytes total. Any less and will not get a reply from the Name msg 0x42. It is too generated nunmber which iodeally should be unique on each device 112 | // The radio uses the combination of UUID and Name to identity each device paired. 113 | // Here is a generated UUID from https://www.uuidgenerator.net/version4 114 | // 56a56730- e8bc- 4930- 81b6- ef33e973842b 115 | uint8_t CIV_ID0[] = {0xFE,0xF1,0x00,0x61, 0x35,0x36,0x41,0x35,0x36,0x37,0x33,0x30,0x2D, 0x45,0x38,0x42,0x43,0x2D, 0x34,0x39,0x30,0x30,0x2D, 0x38,0x31,0x42,0x36,0x2D, 0x45,0x46,0x33,0x33,0x45,0x39,0x37,0x33,0x38,0x34,0x32,0x42,0xFD}; // Send our UUID 116 | 117 | // name is "IC705 Decoder 04" 21 bytes total - YOu can change this but teh name must be exactly 16 bytes. Can pad with spaces 118 | uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0x2D, 0x30, 0x34, 0xFD}; // Send Name 119 | // name is "IC705 BT Decoder" 120 | // uint8_t CIV_ID1[] = {0xFE, 0xF1, 0x00, 0x62, 0x49, 0x43, 0x37, 0x30, 0x35, 0x2D, 0x42, 0x54, 0x2D, 0x44, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x72, 0xFD}; // Send Name 121 | 122 | // ToDo: Make configurable the target radio's service and characteristic UUIDs. Only needed if future radios use differenmt UUIDs. 123 | // The RX and Tx UUIDs are the same number. Unlike most devices, the CI-V bus is not full duplex, 124 | // they share the same wire for Rx and TX and so it goes for the digital wire here. 125 | 126 | #ifdef CORE3 127 | extern HWCDC Serial; 128 | #else 129 | #include "M5Stack_CI-V_Band_Decoder.h" 130 | #endif 131 | 132 | int scanTime = 5; //In seconds 133 | static BLEScan *pBLEScan = NULL; 134 | static BLEClient *pClient = NULL; 135 | static BLEAddress *pServerAddress = NULL; 136 | //static boolean doConnect = false; 137 | static bool connected = false; 138 | static BLERemoteCharacteristic* pTXCharacteristic; 139 | static BLERemoteCharacteristic* pRXCharacteristic; 140 | //const uint64_t decMulti[] = {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1}; 141 | static bool BT_ADDR_confirm = false; 142 | static bool Name_confirm = false; 143 | static bool Token_confirm = false; 144 | static bool Pairing_Accepted = false; 145 | static bool CIV_granted = false; 146 | extern bool BLE_connected; 147 | const uint8_t notificationOff[] = {0x0, 0x0}; 148 | const uint8_t notificationOn[] = {0x1, 0x0}; 149 | bool onoff = true; 150 | extern uint8_t band; 151 | extern uint8_t PTT; 152 | extern uint8_t radio_address; 153 | extern bool XVTR_enabled; 154 | extern uint8_t XVTR_Band; 155 | extern uint64_t frequency; 156 | extern uint8_t read_buffer[]; //Read buffer 157 | extern bool BLE_buff_flag; 158 | 159 | static void notifyCallback( 160 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 161 | uint8_t* pData, 162 | size_t length, 163 | bool isNotify); 164 | 165 | //void printFrequency(void); 166 | 167 | // The onDisconnect() callback function worked but am using pClient->isConnected() instead. 168 | // It also arrives asynchronously which has to be handled as such. Not using this now. 169 | // To use these, uncomment the 170 | class MyClientCallback : public BLEClientCallbacks 171 | { 172 | void onConnect(BLEClient* pclient) { 173 | //doConnect = true; 174 | //BLE_connected = true; // tracks state of BLE level connection 175 | DPRINTLNF("Now Connected to BLE server"); 176 | } 177 | 178 | void onDisconnect(BLEClient* pclient) { 179 | connected = false; // tacks state of CIV connection 180 | doConnect = false; // gateway to connect and pair processes. 181 | BLE_connected = false; // tracks state of BLE level connection 182 | Name_confirm = Token_confirm = CIV_granted = false; // reset 183 | DPRINTLNF("Lost BLE server connection event flag set on Disconnect "); 184 | //Scan_BLE_Servers(); 185 | } 186 | }; 187 | 188 | // ---------------------------------------- 189 | // Print the received frequency 190 | // ---------------------------------------- 191 | /* 192 | void printFrequency(const uint8_t freq[]) 193 | { 194 | if (BLE_connected) { 195 | frequency = 0; 196 | uint64_t mul = 1; 197 | //FE FE E0 42 03 <00 00 58 45 01 10> FD ic-905 6byes on 10G+ bands 198 | //FE FE E0 42 03 <00 00 58 45 01> FD ic-820 and IC-705 5 bytes 199 | //FE FE 00 40 00 <00 60 06 14> FD ic-732 4 bytes 200 | for (uint8_t i = 0; i < 5; i++) { 201 | if (freq[9 - i] == 0xFD) continue; //spike 202 | frequency += (freq[9 - i] >> 4) * decMulti[i * 2]; 203 | frequency += (freq[9 - i] & 0x0F) * decMulti[i * 2 + 1]; 204 | } 205 | DPRINTF("VFO:"); DPRINTLN(frequency); 206 | } 207 | } 208 | */ 209 | uint8_t *r = read_buffer; 210 | 211 | // This can pop up inthe middle of a read_buffer processing fucntion so use a semaphore and only copy the buffer if the process is done with the old one. 212 | static void notifyCallback( 213 | BLERemoteCharacteristic* pBLERemoteCharacteristic, 214 | uint8_t* pData, 215 | size_t length, 216 | bool isNotify) 217 | { 218 | uint8_t buf[64] = {}; 219 | 220 | //Serial.printf("Callback Notify value = \n",isNotify); 221 | #ifdef WATCH_BLE_SERIAL 222 | DPRINTF("Callback length: "); DPRINTLN(length); 223 | DPRINTF("Notify callback - Data: "); 224 | #endif 225 | 226 | int i = 0; 227 | // it is possble for several messages to be stacked up making length larger than the buffer. 228 | // Process the first and ignore the rest. 229 | // Ideally we would parse several and put then into a queue 230 | // Another option is to load up the read_buffer but that is not a circular buffer today 231 | 232 | if (length >= sizeof(buf)) // if length > buffer size will get a stack crash 233 | length = sizeof(buf) - 1; 234 | 235 | #ifdef WATCH_BLE_SERIAL 236 | for (i; i < length; i++) { // Look at the whole buffer which seems to often have multiple responses 237 | DPRINT(pData[i], HEX); 238 | } 239 | DPRINTLNF(""); 240 | #endif 241 | 242 | i = 0; 243 | for (i; i < length; i++) 244 | { 245 | // DPRINT((char)pData[i]); // Print character to uart 246 | #ifdef WATCH_BLE_SERIAL 247 | DPRINT(pData[i], HEX); // print raw data to uart 248 | DPRINTF(","); 249 | #endif 250 | 251 | //if (pData[0] != 0xFE) { 252 | // break; 253 | //} 254 | 255 | if (pData[0] == 0xFE && pData[1] == 0xFE) 256 | buf[i] = pData[i]; // copy into main read buffer 257 | 258 | if (pData[i] == 0xFD) 259 | { 260 | if (pData[1] == 0xF1 && pData[2] == 0x00) 261 | { 262 | switch (pData[3]) 263 | { 264 | case 0x61: 265 | DPRINTLNF("Got BT_ADDR message confirmation, proceed"); 266 | BT_ADDR_confirm = true; 267 | break; 268 | case 0x62: 269 | DPRINTLNF("Got NAME message confirmation, proceed"); 270 | Name_confirm = true; 271 | break; 272 | case 0x63: 273 | DPRINTLNF("Got TOKEN message confirmation, proceed"); 274 | Token_confirm = true; 275 | if (pData[4] == 0x01) 276 | Pairing_Accepted = true; // Pairing action worked. Once pair this wil return 0 277 | break; 278 | case 0x64: 279 | DPRINTLNF("CI-V bus ACCESS granted, proceed"); 280 | CIV_granted = true; 281 | connected = true; 282 | break; 283 | } 284 | BLE_buff_flag = false; // consuming functions will reset this once it is read and won't waste time reading stale data 285 | break; 286 | } 287 | 288 | buf[i+1] = 0; 289 | 290 | if (!BLE_buff_flag) { 291 | memcpy(r, buf, i+1); // only move data into read_buffer if it has already been read by the main program. 292 | BLE_buff_flag = true; // buffer reaady - consuming functions will reset this once it is read and won't waste time reading stale data 293 | #ifdef WATCH_BLE_SERIAL 294 | DPRINTLNF("End of Msg\n"); 295 | #endif 296 | processCatMessages(); 297 | } 298 | 299 | #ifdef WATCH_BLE_SERIAL 300 | DPRINTLNF(""); 301 | #endif 302 | } 303 | } 304 | } 305 | 306 | //************************************************************************************** 307 | // 308 | // Connect to Server 309 | // 310 | //************************************************************************************** 311 | 312 | bool connectToServer(BLEAddress pAddress) { 313 | DPRINTF("Establishing a connection to device address: "); 314 | DPRINTLN(pAddress.toString().c_str()); 315 | 316 | pClient = BLEDevice::createClient(); 317 | //BLEClient* pClient = BLEDevice::createClient(); 318 | DPRINTLNF(" - Created client"); 319 | 320 | // Connect to the remove BLE Server. 321 | pClient->connect(pAddress); 322 | DPRINTLNF(" - Connected to server"); 323 | pClient->setMTU(517); //set client to request maximum MTU from 324 | //server (default is 23 otherwise) 325 | 326 | // Obtain a reference to the Nordic UART service on the remote BLE server. 327 | BLERemoteService* pRemoteService = pClient->getService(serviceUUID); 328 | if (pRemoteService == nullptr) { 329 | DPRINTF("Failed to find Nordic UART service UUID: "); 330 | DPRINTLN(serviceUUID.toString().c_str()); 331 | pClient->disconnect(); 332 | return false; 333 | } 334 | DPRINTF(" - Found our service "); 335 | //DPRINTLN(pClient->getPeerAddress()); 336 | 337 | // Obtain a reference to the TX characteristic of the Nordic UART service on the remote BLE server. 338 | pTXCharacteristic = pRemoteService->getCharacteristic(charUUID_TX); 339 | if (pTXCharacteristic == nullptr) { 340 | DPRINTF("Failed to find TX characteristic UUID: "); 341 | DPRINTLN(charUUID_TX.toString().c_str()); 342 | pClient->disconnect(); 343 | return false; 344 | } 345 | DPRINTLNF(" - Remote BLE TX characteristic reference established"); 346 | 347 | // Read the value of the TX characteristic. 348 | //if(pTXCharacteristic->canRead()) { 349 | std::string value = pTXCharacteristic->readValue(); 350 | DPRINTF("The characteristic value is currently: "); 351 | DPRINTLN(value.c_str()); 352 | //} 353 | 354 | // Obtain a reference to the RX characteristic of the Nordic UART service on the remote BLE server. 355 | pRXCharacteristic = pRemoteService->getCharacteristic(charUUID_RX); 356 | if (pRXCharacteristic == nullptr) { 357 | DPRINTF("Failed to find our characteristic UUID: "); 358 | DPRINTLN(charUUID_RX.toString().c_str()); 359 | return false; 360 | } 361 | DPRINTLNF(" - Remote BLE RX characteristic reference established"); 362 | 363 | // Read the value of the characteristic. 364 | if(pRXCharacteristic->canRead()) { 365 | value = pRXCharacteristic->readValue(); 366 | DPRINTF("The characteristic value was: "); 367 | DPRINTLN(value.c_str()); 368 | } 369 | 370 | if(pTXCharacteristic->canNotify()) 371 | pTXCharacteristic->registerForNotify(notifyCallback); 372 | 373 | // UUID is 32 bytes, msg is 41 total. Any less and the reply for the Name msg will be suppressed. Weird, probably a radio bug. 374 | pRXCharacteristic->writeValue(CIV_ID0, sizeof(CIV_ID0)); 375 | pRXCharacteristic->canNotify(); 376 | vTaskDelay(20); 377 | 378 | // Device name must be 16 bytes exactly, msg total 21 bytes. 379 | pRXCharacteristic->writeValue(CIV_ID1, sizeof(CIV_ID1)); 380 | pRXCharacteristic->canNotify(); 381 | vTaskDelay(20); // a small delay was required or this message would be missed (collision likely). 382 | 383 | // Send Token - A fixed value 9 bytes long total. 384 | uint8_t CIV_ID2[] = {0xFE, 0xF1, 0x00, 0x63, 0xEE, 0x39, 0x09, 0x10, 0xFD}; // Send Token 385 | pRXCharacteristic->writeValue(CIV_ID2, 9); 386 | pRXCharacteristic->canNotify(); 387 | vTaskDelay(20); 388 | 389 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x62, 0xFD // no reply when reconnecting 390 | // if pairing, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x01, 0xFD // pair confirmed 391 | // if already paired, get reply with 0xFE, 0xF1, 0x00, 0x63, 0x00, 0xFD // already paired 392 | // if all good, will get reply with 0xFE, 0xF1, 0x00, 0x64, 0xFD // CI-V bus access granted 393 | 394 | //String helloValue = "Hello Remote Server"; 395 | //pRXCharacteristic->writeValue(helloValue.c_str(), helloValue.length()); 396 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); 397 | //connected = true; 398 | return true; 399 | } 400 | 401 | void printDeviceAddress() { 402 | const uint8_t* point = esp_bt_dev_get_address(); 403 | 404 | for (int i = 0; i < 6; i++) { 405 | char str[3]; 406 | 407 | sprintf(str, "%02X", (int)point[i]); 408 | DPRINT(str); 409 | 410 | if (i < 5){ 411 | DPRINTF(":"); 412 | } 413 | } 414 | DPRINTLNF(""); 415 | } 416 | 417 | /************************************************************************************** 418 | Scan for BLE servers and find the first one that advertises the Nordic UART service. 419 | ***************************************************************************************/ 420 | class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { 421 | /** 422 | Called for each advertising BLE server. 423 | */ 424 | void onResult(BLEAdvertisedDevice advertisedDevice) { 425 | DPRINTF("BLE Advertised Device found - "); 426 | DPRINTLN(advertisedDevice.toString().c_str()); 427 | 428 | // We have found a device, check to see if it contains the Nordic UART service. 429 | if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { 430 | 431 | DPRINTLNF("Found a device with the desired ServiceUUID!"); 432 | advertisedDevice.getScan()->stop(); 433 | 434 | pServerAddress = new BLEAddress(advertisedDevice.getAddress()); 435 | doConnect = true; // Trigger to process server connection 436 | 437 | } // Found our server 438 | } // onResult 439 | }; // MyAdvertisedDeviceCallbacks 440 | 441 | void Scan_BLE_Servers(void) 442 | { 443 | // Retrieve a Scanner and set the callback we want to use to be informed when we 444 | // have detected a new device. Specify that we want active scanning and start the 445 | // scan to run for 30 seconds 446 | BLEScan* pBLEScan = BLEDevice::getScan(); 447 | pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); 448 | pBLEScan->setInterval(1349); 449 | pBLEScan->setWindow(449); // less or equal setInterval value 450 | pBLEScan->setActiveScan(true); 451 | BLEScanResults foundDevices = pBLEScan->start(scanTime, false); 452 | ////pBLEScan->start(scanTime, false); 453 | DPRINTF("Devices found: "); DPRINTLN(foundDevices.getCount()); 454 | DPRINTLNF("Scan done!"); 455 | pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory 456 | } 457 | 458 | //-------------------------------------------- // 459 | // BLE 460 | // SendMessage by BLE Slow in packets of 20 chars 461 | // or fast in one long string. 462 | // Fast can be used in IOS app BLESerial Pro 463 | //------------------------------ 464 | void SendMessageBLE(uint8_t Message[], uint8_t len) 465 | { 466 | if(connected) 467 | { 468 | //if (Mem.UseBLELongString) // If Fast transmission is possible 469 | pRXCharacteristic->writeValue(Message, len, false); //.c_str()); 470 | pRXCharacteristic->canNotify(); 471 | //delay(10); // Bluetooth stack will go into congestion, if too many packets are sent 472 | 473 | /*} 474 | else // Packets of max 20 bytes 475 | { 476 | int parts = (Message.length()/20) + 1; 477 | for(int n=0;nwriteValue(Message.substr(n*20, 20).c_str()); 480 | pRXCharacteristic->canNotify(); 481 | //delay(40); // Bluetooth stack will go into congestion, if too many packets are sent 482 | } 483 | }*/ 484 | } 485 | } 486 | 487 | void BLE_Setup(void) 488 | { 489 | BLEDevice::init(""); 490 | doConnect = false; 491 | } 492 | 493 | // If the flag "doConnect" is true then we have scanned for and found the desired 494 | // BLE Server with which we wish to connect. Now we connect to it. Once we are 495 | // connected we set the connected flag to be true. 496 | void BLE_loop(void) 497 | { 498 | static uint32_t time_freq = 0; 499 | static uint32_t time_tx = 0; 500 | 501 | if (doConnect == true) 502 | { 503 | if (connectToServer(*pServerAddress)) 504 | { 505 | //DPRINTLNF("We are now connected to the BLE Server."); 506 | // should have CIV results by now, see if we have access to the CI-V bus or not 507 | Serial.printf("doConnect1 - post CIV_Connect - connected = %d Token = %d CIV_Granted = %d BLE_connected = %d\n", connected, Token_confirm, CIV_granted, BLE_connected); 508 | 509 | if (Token_confirm) 510 | ; 511 | 512 | if (Pairing_Accepted && Token_confirm) 513 | DPRINTLNF("Pairing_Accepted"); // only get this whe a pairing is request. false on regular sign in 514 | 515 | if (!Pairing_Accepted && Token_confirm) // continue on 516 | DPRINTLNF("Paired already, continue to sign in"); 517 | 518 | if (!BLE_connected && CIV_granted) 519 | { 520 | connected = true; // tracks CIV layer state can be connected to BLE but not CIV (not paired for example) 521 | BLE_connected = true; // tracks CIV layer more glabal than the connected var, almost redundant 522 | DPRINTLNF("BLE Connected"); 523 | } 524 | onoff = true; // want to read from the radio 525 | // Can toggle notifications for the TX Characteristic on and off. 526 | // Update the RX characteristic with the current time since boot string. 527 | if (onoff) { 528 | //DPRINTLNF("Notifications turned on"); 529 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); 530 | } else { 531 | //DPRINTLNF("Notifications turned off"); 532 | pTXCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOff, 2, true); 533 | } 534 | } 535 | else 536 | { 537 | DPRINTLNF("We have failed to connect to the server; there is nothin more we will do."); 538 | //draw_initial_screen(); 539 | //M5.Lcd.setTextColor(text_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 540 | //M5.Lcd.setCursor(5, 80); //Set the location of the cursor to the coordinates X and Y 541 | //M5.Lcd.printf("Failed Connection to Radio"); 542 | connected = false; 543 | } 544 | doConnect = false; 545 | } 546 | 547 | if (pClient != nullptr && !pClient->isConnected()) 548 | { 549 | if (BLE_connected) 550 | DPRINTLNF("BLE not connected to radio"); // detect if we are not connected 551 | //delay(100); 552 | connected = false; 553 | BLE_connected = false; 554 | } 555 | 556 | if(connected) 557 | { 558 | /* 559 | if (millis() >= time_freq + POLL_RADIO_FREQ) // poll every X ms 560 | { 561 | //DPRINTLNF("Poll radio"); 562 | uint8_t CIV_frequency[] = {0xFE, 0xFE, radio_address, 0xE0, 0x03, 0xFD}; 563 | pRXCharacteristic->writeValue(CIV_frequency, sizeof(CIV_frequency), false); 564 | //pRXCharacteristic->writeValue(&cmds[CIV_C_F_READ].cmdData[1], cmds[CIV_C_F_READ].cmdData[0], true); 565 | pRXCharacteristic->canNotify(); 566 | //delay(10); 567 | time_freq = millis(); 568 | } 569 | 570 | if (millis() >= time_tx + POLL_PTT_DEFAULT) // poll every X ms 571 | { 572 | //DPRINTLNF("Poll radio for TX/RX state"); 573 | uint8_t CIV_TX[] = {0xFE, 0xFE, radio_address, 0xE0, 0x1C, 0x00, 0xFD}; 574 | pRXCharacteristic->writeValue(CIV_TX, sizeof(CIV_TX), false); 575 | //pRXCharacteristic->writeValue(CIV_C_TX, cmds[CIV_C_TX].cmdData[0], true); 576 | pRXCharacteristic->canNotify(); 577 | //delay(10); 578 | time_tx = millis(); 579 | } 580 | */ 581 | }// if connected 582 | else 583 | { 584 | Scan_BLE_Servers(); 585 | } 586 | } // End of loop 587 | 588 | #endif 589 | #endif 590 | 591 | -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/BLE.h: -------------------------------------------------------------------------------- 1 | #ifndef BLE_H_ 2 | #define BLE_H_ 3 | 4 | void Scan_BLE_Servers(void); 5 | static bool doConnect = false; 6 | void BLE_loop(void); 7 | void BLE_Setup(void); 8 | 9 | #endif -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/BLEScan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BLEScan.h 3 | * 4 | * Created on: Jul 1, 2017 5 | * Author: kolban 6 | */ 7 | 8 | #ifndef COMPONENTS_CPP_UTILS_BLESCAN_H_ 9 | #define COMPONENTS_CPP_UTILS_BLESCAN_H_ 10 | #include "sdkconfig.h" 11 | #if defined(CONFIG_BLUEDROID_ENABLED) 12 | #include 13 | 14 | // #include 15 | #include 16 | #include "BLEAdvertisedDevice.h" 17 | #include "BLEClient.h" 18 | #include "RTOS.h" 19 | 20 | class BLEAdvertisedDevice; 21 | class BLEAdvertisedDeviceCallbacks; 22 | class BLEExtAdvertisingCallbacks; 23 | class BLEClient; 24 | class BLEScan; 25 | class BLEPeriodicScanCallbacks; 26 | 27 | 28 | struct esp_ble_periodic_adv_sync_estab_param_t { 29 | uint8_t status; /*!< periodic advertising sync status */ 30 | uint16_t sync_handle; /*!< periodic advertising sync handle */ 31 | uint8_t sid; /*!< periodic advertising sid */ 32 | esp_ble_addr_type_t adv_addr_type; /*!< periodic advertising address type */ 33 | esp_bd_addr_t adv_addr; /*!< periodic advertising address */ 34 | esp_ble_gap_phy_t adv_phy; /*!< periodic advertising phy type */ 35 | uint16_t period_adv_interval; /*!< periodic advertising interval */ 36 | uint8_t adv_clk_accuracy; /*!< periodic advertising clock accuracy */ 37 | }; 38 | 39 | /** 40 | * @brief The result of having performed a scan. 41 | * When a scan completes, we have a set of found devices. Each device is described 42 | * by a BLEAdvertisedDevice object. The number of items in the set is given by 43 | * getCount(). We can retrieve a device by calling getDevice() passing in the 44 | * index (starting at 0) of the desired device. 45 | */ 46 | class BLEScanResults { 47 | public: 48 | void dump(); 49 | int getCount(); 50 | BLEAdvertisedDevice getDevice(uint32_t i); 51 | 52 | private: 53 | friend BLEScan; 54 | std::map m_vectorAdvertisedDevices; 55 | }; 56 | 57 | /** 58 | * @brief Perform and manage %BLE scans. 59 | * 60 | * Scanning is associated with a %BLE client that is attempting to locate BLE servers. 61 | */ 62 | class BLEScan { 63 | public: 64 | void setActiveScan(bool active); 65 | void setAdvertisedDeviceCallbacks( 66 | BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, 67 | bool wantDuplicates = false, 68 | bool shouldParse = true); 69 | void setInterval(uint16_t intervalMSecs); 70 | void setWindow(uint16_t windowMSecs); 71 | bool start(uint32_t duration, void (*scanCompleteCB)(BLEScanResults), bool is_continue = false); 72 | BLEScanResults start(uint32_t duration, bool is_continue = false); 73 | void stop(); 74 | void erase(BLEAddress address); 75 | BLEScanResults getResults(); 76 | void clearResults(); 77 | 78 | #ifdef CONFIG_BT_BLE_50_FEATURES_SUPPORTED 79 | void setExtendedScanCallback(BLEExtAdvertisingCallbacks* cb); 80 | void setPeriodicScanCallback(BLEPeriodicScanCallbacks* cb); 81 | 82 | esp_err_t stopExtScan(); 83 | esp_err_t setExtScanParams(); 84 | esp_err_t setExtScanParams(esp_ble_ext_scan_params_t* ext_scan_params); 85 | esp_err_t startExtScan(uint32_t duration, uint16_t period); 86 | private: 87 | BLEExtAdvertisingCallbacks* m_pExtendedScanCb = nullptr; 88 | BLEPeriodicScanCallbacks* m_pPeriodicScanCb = nullptr; 89 | #endif // CONFIG_BT_BLE_50_FEATURES_SUPPORTED 90 | 91 | private: 92 | BLEScan(); // One doesn't create a new instance instead one asks the BLEDevice for the singleton. 93 | friend class BLEDevice; 94 | void handleGAPEvent( 95 | esp_gap_ble_cb_event_t event, 96 | esp_ble_gap_cb_param_t* param); 97 | 98 | 99 | esp_ble_scan_params_t m_scan_params; 100 | BLEAdvertisedDeviceCallbacks* m_pAdvertisedDeviceCallbacks = nullptr; 101 | bool m_stopped = true; 102 | bool m_shouldParse = true; 103 | FreeRTOS::Semaphore m_semaphoreScanEnd = FreeRTOS::Semaphore("ScanEnd"); 104 | BLEScanResults m_scanResults; 105 | bool m_wantDuplicates; 106 | void (*m_scanCompleteCB)(BLEScanResults scanResults); 107 | }; // BLEScan 108 | 109 | class BLEPeriodicScanCallbacks { 110 | public: 111 | virtual ~BLEPeriodicScanCallbacks() {} 112 | 113 | virtual void onCreateSync(esp_bt_status_t status) {} 114 | virtual void onCancelSync(esp_bt_status_t status) {} 115 | virtual void onTerminateSync(esp_bt_status_t status) {} 116 | virtual void onLostSync(uint16_t sync_handle) {} 117 | virtual void onSync(esp_ble_periodic_adv_sync_estab_param_t) {} 118 | virtual void onReport(esp_ble_gap_periodic_adv_report_t params) {} 119 | virtual void onStop(esp_bt_status_t status) {} 120 | }; 121 | 122 | #endif /* CONFIG_BLUEDROID_ENABLED */ 123 | #endif /* COMPONENTS_CPP_UTILS_BLESCAN_H_ */ 124 | -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/CIV.h: -------------------------------------------------------------------------------- 1 | // CIV.h 2 | 3 | #ifndef CIV_h 4 | #define CIV_h 5 | 6 | #include 7 | #include "M5Stack_CI-V_Band_Decoder.h" 8 | 9 | //inline uint8_t bcdByte(const uint8_t x) const { return (((x & 0xf0) >> 4) * 10) + (x & 0x0f); } 10 | inline uint8_t bcdByte(const uint8_t x) { return (((x & 0xf0) >> 4) * 10) + (x & 0x0f); } 11 | // input is between 0 and 99 decimal. output 0 to 0x99 12 | //inline uint8_t bcdByteEncode(const uint8_t x) const { return ((x / 10) << 4) + (x % 10); } 13 | inline uint8_t bcdByteEncode(const uint8_t x) { return ((x / 10) << 4) + (x % 10); } 14 | 15 | /* ======================================== 16 | * geo.c 17 | * 18 | * Converts Lat and Long to extended maidenhead grid squares 19 | * 20 | * ======================================== 21 | */ 22 | 23 | /* geo.c Ham Radio functions for orientation on earth – Copyright 2010 This program is free software; you can redistribute it 24 | * and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either 25 | * version 3, or (at your option) any later version. 26 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 27 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 28 | * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software 29 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 30 | */ 31 | /* 32 | * 33 | * Next the function that converts the position to the Maidenhead locator. It could easily have been written just to 34 | * accept two arguments for the position, but in this case the structure is passed by address to the function for evaluation. 35 | * 36 | * The return value of the function is best provided by the calling routine, so the second argument is the address of a string 37 | * (i.e. an array of type char) where the function will return the result. This is quite a bit more complicated that most 38 | * languages which use dynamic memory allocation and garbage collection to allow functions to return strings. 39 | * 40 | * I use the return value here to indicate success or failure, but have no failure conditions. I suppose a latitude of less than -90 or more than +90 would suffice. For longitude I thing wrapping (e.g. 181E = 179W) is sufficient, which is what the function does. 41 | * 42 | */ 43 | 44 | /* Global variables for handling GPS conversion to Maindernhead grid square */ 45 | #define NMEA_MAX_LENGTH (120) 46 | #define GRIDSQUARE_LEN (9u) 47 | 48 | struct position { 49 | double latitude; 50 | double longitude; 51 | }; 52 | 53 | static char Latitude[14]; /* size to hold longest values supplied by GPS, assuming 10 plus null for now */ 54 | static char Longitude[14]; 55 | void CIV_Action(const uint8_t cmd_num, const uint8_t data_start_idx, const uint8_t data_len, const uint8_t msg_len, const uint8_t read_buffer[]); 56 | void reverse(char *str, int len); 57 | void ftoa(float n, char *res, int afterpoint); 58 | int positionToMaidenhead(char m[]); 59 | int Convert_to_MH(void); 60 | void ConvertToMinutes(char _gps_msg[]); 61 | void SetMode(uint8_t _band); 62 | void SetAGC(uint8_t _band); 63 | void SetPre(uint8_t _band); 64 | void SetAttn(uint8_t _band); 65 | void SetSplit(uint8_t _band, bool force_off); 66 | void SetRFPwr(uint8_t _band); 67 | 68 | // command "body" of the CIV commands currently in use 69 | // Add new command to this list. Then add array values to the structure below. The row is the same as the enum value here. 70 | enum cmds { 71 | CIV_C_F_SEND, 72 | CIV_C_F1_SEND, 73 | CIV_C_F_READ, 74 | CIV_C_F26, 75 | CIV_C_F26A, 76 | CIV_C_F26B, 77 | CIV_C_F25A_SEND, 78 | CIV_C_F25B_SEND, 79 | CIV_C_MOD_READ, 80 | CIV_C_MOD_SET, 81 | CIV_C_MOD_SEND, 82 | CIV_C_MOD1_SEND, 83 | CIV_C_MOD_USB_F1_SEND, 84 | CIV_C_MOD_USB_SEND, 85 | CIV_C_USB_D0_F2_SEND, 86 | CIV_C_USB_D1_F2_SEND, 87 | CIV_C_LSB_D0_F2_SEND, 88 | CIV_C_LSB_D1_F2_SEND, 89 | CIV_C_FM_D1_F1_SEND, 90 | CIV_C_ATTN_READ, 91 | CIV_C_ATTN_OFF, 92 | CIV_C_ATTN_ON, 93 | CIV_C_SPLIT_READ, 94 | CIV_C_SPLIT_OFF_SEND, 95 | CIV_C_SPLIT_ON_SEND, 96 | CIV_C_RFGAIN, 97 | CIV_C_AFGAIN, 98 | CIV_C_RFPOWER, 99 | CIV_C_S_MTR_LVL, 100 | CIV_C_PREAMP_READ, 101 | CIV_C_PREAMP_OFF, 102 | CIV_C_PREAMP_ON, 103 | CIV_C_PREAMP_ON2, 104 | CIV_C_AGC_READ, 105 | CIV_C_AGC_FAST, 106 | CIV_C_AGC_MID, 107 | CIV_C_AGC_SLOW, 108 | CIV_C_CW_MSGS, 109 | CIV_C_BSTACK, 110 | CIV_C_MY_POSIT_READ, 111 | CIV_C_MY_POSIT_DATA, 112 | CIV_C_TRX_ON_OFF, 113 | CIV_C_TRX_ID, 114 | CIV_C_TX, 115 | CIV_C_DATE, 116 | CIV_C_TIME, 117 | CIV_C_UTC_READ_905, 118 | CIV_C_UTC_READ_705, 119 | CIV_C_DUPLEX_READ, 120 | CIV_C_DUPLEX_SEND, 121 | CIV_C_RIT_XIT, 122 | CIV_C_RIT_ON_OFF, 123 | CIV_C_XIT_ON_OFF, 124 | CIV_C_RADIO_OFF, 125 | CIV_C_RADIO_ON, 126 | CIV_C_SCOPE_ON, 127 | CIV_C_SCOPE_OFF, 128 | CIV_C_SCOPE_ALL, 129 | CIV_R_NO_GOOD, 130 | CIV_R_GOOD, 131 | CIV_R_SEL_VFO, 132 | End_of_Cmd_List 133 | }; 134 | 135 | // For CIV commands 136 | 137 | #define MODES_NUM 16 138 | #define CW 3 139 | #define CW_R 7 140 | #define USB 1 141 | #define LSB 0 142 | #define RTTY 4 143 | #define RTTY_R 8 144 | #define AM 2 145 | #define FM 5 146 | #define DV 23 147 | #define DD 34 148 | #define ATV 35 149 | 150 | #define AGC_SET_NUM 4 151 | #define AGC_OFF 0 // Index to AGC Settings table 152 | #define AGC_SLOW 3 153 | #define AGC_MID 2 154 | #define AGC_FAST 1 155 | 156 | #define FILTER 4 157 | #define FILT1 1 158 | #define FILT2 2 159 | #define FILT3 3 160 | #define VFO_A 1 161 | #define VFO_B 0 162 | 163 | #define ATTN_OFF 0 // Bypass 164 | #define ATTN_ON 1 // Turn relay on 165 | #define PREAMP_OFF 0 // Bypass 166 | #define PREAMP_ON 1 // Switch relay on 167 | 168 | struct cmdList { 169 | cmds cmd; 170 | uint8_t cmdData[6]; // first byte is number of bytes in the command (sub commands) 171 | }; 172 | 173 | struct Modes_List { 174 | uint8_t mode_num; 175 | char mode_label[8]; 176 | uint8_t filtx; // bandwidth in HZ - look up matching width in Filter table when changing modes 177 | uint8_t data; 178 | }; 179 | 180 | // translation of the radio's general mode 181 | const char ModeStr[3][11] = { 182 | "MODE_VOICE", 183 | "MODE_DATA", 184 | "MODE_NDEF" 185 | }; 186 | 187 | const char AgcStr[4][6] = { 188 | {"AGC- "}, // 0 reserved for AGC OFF 189 | {"AGC-F"}, // 1 190 | {"AGC-M"}, // 2 191 | {"AGC-S"} // 3 192 | }; 193 | 194 | // clear text translation of the Filter setting 195 | const char FilStr[4][5] = { 196 | "NDEF", 197 | "FIL1", // 1 (1 .. 3 is according to ICOM's documentation) 198 | "FIL2", 199 | "FIL3" 200 | }; 201 | 202 | // states of radio's DC-Power (on/Off State) 203 | const char radioOnOffStr[6][13] = { 204 | "RADIO_OFF", 205 | "RADIO_ON", 206 | "RADIO_OFF_TR", // transit from OFF to ON 207 | "RADIO_ON_TR", // transit from ON to OFF 208 | "RADIO_NDEF", // don't know 209 | "RADIO_TOGGLE" 210 | }; 211 | 212 | #endif // CIV.h header file 213 | -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/DebugPrint.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUGPRINT_H_ 2 | #define DEBUGPRINT_H_ 3 | 4 | //#define DEBUG //set for debug output 5 | 6 | #ifdef DEBUG 7 | #define DEBUG_ERROR true 8 | #define DEBUG_ERROR_SERIAL if(DEBUG_ERROR)Serial 9 | 10 | #define DEBUG_WARNING true 11 | #define DEBUG_WARNING_SERIAL if(DEBUG_WARNING)Serial 12 | 13 | #define DEBUG_INFORMATION true 14 | #define DEBUG_INFORMATION_SERIAL if(DEBUG_INFORMATION)Serial 15 | 16 | #define DSERIALBEGIN(...) Serial.begin(__VA_ARGS__) 17 | #define DPRINTLN(...) Serial.println(__VA_ARGS__) 18 | #define DPRINT(...) Serial.print(__VA_ARGS__) 19 | #define DPRINTF(...) Serial.print(F(__VA_ARGS__)) 20 | #define DPRINTLNF(...) Serial.println(F(__VA_ARGS__)) //printing text using the F macro 21 | #define DELAY(...) delay(__VA_ARGS__) 22 | #define PINMODE(...) pinMode(__VA_ARGS__) 23 | #define DEBUG_PRINT(...) Serial.print(F(#__VA_ARGS__" = ")); Serial.print(__VA_ARGS__); Serial.print(F(" ")) 24 | #define DEBUG_PRINTLN(...) DEBUG_PRINT(__VA_ARGS__); Serial.println() 25 | #define DEBUG_PRINTF(...) Serial.printf(__VA_ARGS__) 26 | #else 27 | #define DSERIALBEGIN(...) 28 | #define DPRINTLN(...) 29 | #define DPRINT(...) 30 | #define DPRINTF(...) 31 | #define DPRINTLNF(...) 32 | #define DELAY(...) 33 | #define PINMODE(...) 34 | #define DEBUG_PRINT(...) 35 | #define DEBUG_PRINTLN(...) 36 | #define DEBUG_PRINTF(...) 37 | #endif 38 | 39 | #endif //DEBUGPRINT_H_ -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/M5Stack_CI-V_Band_Decoder.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | ICOM CI-V Band Decoder and PTT breakout 3 | Michael Lewis K7MDL May 2025 4 | https://github.com/K7MDL2/IC-705-BLE-Serial-Example/tree/main/M5Stack_CI-V_Band_Decoder 5 | 6 | BT/BLE Classic Serial or USB connection for IC-705 7 | USB for other models 8 | Runs on M5Stack Core Basic(BT Classic only), Core2(BT&BLE) and Core3-SE(BLE only). All have issues with M5 USB Host stacking module compatibility as of Aug 2024. 9 | Use BLE or BT methods. 10 | The USB port may be used to connect to a PC for logging and digi-mode progam usage to get the actual XVTR frequency 11 | No USB audio is passed through. Use the 705's USB port for that. 12 | 13 | This a small self-contained CI-V band decoder that can display transverter frequency with suitable offsets, 14 | change bands with touch or external input and output (switch, radio decoder outputs), 2, 4, 8, or more I/O outputs. 15 | Depending on the stacking module(s) chosen, can be relays, MOSFETs (1A @ 24VDC), or a proto board for DIY interfaces. 16 | They also have a 9 to 24VDC power supply input and batteries of various sized. 17 | With the small size you can stick it on the back of a radio or the back of a dish on a tropid. 18 | Generally no hardware packaging is required. Just plug together and wire up to the connectors. 19 | There are several code projects that are similar, some do not have the IO., this is a customization of one of them. 20 | 21 | For this to work with the 705 Bluetooth, it must be run on a chipset and BT code library that supports BT Classic serial port profile. 22 | The newer M5Stack CoreS3 (ESPS3 based) and CoreS3SE only support BT5, mesh and BLE, is not backward compatible with BT Classic serial profile 23 | The profiles listed on the 705's BT Info page lists SPP and LE. 24 | 25 | This will Pair BT with a Passkey, no action required on the decoder for passkey or for radio address 26 | 27 | To use this with BT on the IC-705 you first pair it on the 705. YOu need to configure teh Radio BT address (6 bytes) eitehr in 28 | the code or in a config.ini file on the SD card. See project Wiki for details. 29 | Once paired, this device will auto-(re)connect. BT Classic reconects very fast. 30 | This device operates in Master mode so power up order does not matter. 31 | On first connection after pairing the radio's CI-V address is discovered and used so there is no configuraton required 32 | 33 | For BT connection the IC-705 side settings required are 34 | 1. Bluetooth ON 35 | 2. AutoConnect ON 36 | 3. Data-Device-> Serialport Function -> CI-V (Echo Back ON) 37 | 4. Pair the radio to this device: 38 | On the 705 menu SET -> BLUETOOTH SET -> Pairing Reception 39 | Power on the BT Band Decoder. If it times out, power cycle the decoder to retry 40 | "IC-705 Decoder 1" device name will display when it is discovered by the radio 41 | The radio will prompt to confirm a passkey number, it should match the decoder display if any attached or on a serial terminal 42 | Press OK 43 | The Decoder will auto accept the passkey confirm from the radio and connect and start operating 44 | It is now paired and connected and will auto-reconnect as needed. 45 | 46 | Tested on the IC-705 (BT andf USB) and IC-905 (USB). Should work with other models like the 9700. 47 | 48 | This M5Stack decoder is a mini version of my large USB CI-V Band Decoder for the 905 and 705 which is built on a Teensy and passes both of radio's 2 49 | USB serial port data (CI-V and GPS) on to a optional PC. It has options for 7" or 4.3" touch display or encoders and can do radio control allowing 50 | for transverter control with each Xvtr band keeping its own parameters. 51 | https://github.com/K7MDL2/ICOM_IC-905_CIV. There are multiple band decoder solutions, some for the 905, most will support 905/705 and 9700, and more. 52 | 53 | I have a hardware/software big Band decoder at https://github.com/K7MDL2/RF-Power-Meter-V1 . It also measures power with an external bi-directional 54 | coupler up to 10GHz. 55 | 56 | The Teensy based 905 decoder uses the UI and control framework from my Teensy SDR project at https://github.com/K7MDL2/KEITHSDR 57 | 58 | Some BT parts are derived from the following project, thanks! 59 | _________________________________________________ 60 | T1 Interface 61 | V2.0 (12.09.2023) 62 | Peter Jonas DL5DLA 63 | 64 | This code, running on an ESP32, requests the current frequency 65 | from the ICOM IC-705 via bluetooth connection, and sends the 66 | related band number to the Elecraft T1. Based on the band 67 | number, the T1 applies the stored tuning settings. A re-tuning 68 | is possible directly after changing the frequency. For the next 69 | few seconds the T1 waits for a carrier and will tune again. 70 | 71 | For first use, the ESP32 must be paired to the IC-705. Later on 72 | the ESP32 should be powered already, before the IC-705 is 73 | switched on. If someone knows how the bluetooth connection 74 | can be setup the other way around (switch on the IC-705, then 75 | the esp32), please let me know. 76 | 77 | The code is compiled on PlatformIO, but should also work using 78 | the Arduino IDE. 79 | 80 | This code is based on the code from 81 | Ondrej Kolonicny (ok1cdj) https://github.com/ok1cdj/IC705-BT-CIV 82 | and 83 | Matthew Robinson (VK6MR) https://zensunni.org/blog/2011/01/19/arduino-elecraft-t1-interface/ 84 | 85 | Many thanks to both for their example codes giving me the first insight on how 86 | to deal with the communication between the IC-705 and T1. 87 | 88 | In this version the ESP32 device is set as bluetooth master and the IC-705 as client. 89 | Due to this the bluetooth connection is more robust, and the IC-705 is reconnected 90 | no matter if the TRX or the ESP32 is switched off temporarly. 91 | 92 | If you are using BT Classic SPP then it is important to set the "bd_address" in the next lines below! 93 | *************************************************************************/ 94 | #ifndef _M5_BT_USB_ 95 | #define _M5_BT_USB_ 96 | 97 | //#define CLEAN_SD_DB_FILE // used when the data structure has changed, force an overwrite with default data 98 | 99 | //#define CORE2LIB // applies only to Core2 - forces M5Core2 lib vs M5Unified - Touch works better with M5Unified 100 | 101 | //#define M5STAMPC3U // Set for M5 StampC3U used in the K7MDL IC-705 Transverter Box controller 102 | // Comment out and the CPU architecture is automatically selected for all others (AtomS3, Core, Core2, CoreS3/SE) 103 | 104 | #ifndef M5STAMPC3U // for radio side controller can choose XVBox BCD output operation and/or PC Passthrough 105 | 106 | #define XVBOX // for radio side controller set config specific to usage with the 705 transverter box using hte 4In/*out module and 3 BCD + 1 PTT and 1 PTT in 107 | 108 | #ifdef XVBOX // option for IO for BCD + PTT on LCD controller 109 | #define XVBOX_PLCC // use PLCC module with ULN2803A instead of otehr IO device such as 4-In/8-Out module for 3 BCD + 1 PTT and 1 PTT in 110 | #endif 111 | 112 | #define PC_PASSTHROUGH // fwd through BT or USBHOST data to a PC if connected. Turn off Debug in DebugPrint.h 113 | 114 | //#define DBG_TO_LCD // used to print frequency and CI-V commands to the LCD to debug PC Passthrough 115 | 116 | #endif 117 | 118 | #ifdef M5STAMPC3U 119 | //#include // kills off USB Host 120 | #define MCP23017 121 | #define I2C_SDA 1 122 | #define I2C_SCL 0 123 | #include 124 | //#define BUTTON_PIN 3 125 | #define PIXEL_PIN 2 // GPIO2 is Sk6812 RGB LED 126 | #define NUM_PIXELS 1 // Just 1 LED 127 | 128 | #elif defined ( CONFIG_IDF_TARGET_ESP32S3 ) 129 | #ifdef __M5GFX_M5ATOMDISPLAY__ 130 | #include 131 | #define ATOMS3 132 | #else 133 | //#include // Mov 2024 latest M5Unified now supports M5CoreS3 134 | #include // kills off USB Host 135 | #endif 136 | static m5::touch_state_t prev_state; 137 | #define SD_SPI_SCK_PIN 36 138 | #define SD_SPI_MISO_PIN 35 139 | #define SD_SPI_MOSI_PIN 37 140 | #define SD_SPI_CS_PIN 4 141 | #define CORE3 142 | 143 | #elif defined ( ARDUINO_M5STACK_CORE2 ) || defined ( ARDUINO_M5STACK_Core2 ) 144 | #ifdef CORE2LIB 145 | #include // USB Host sort to works 146 | #else 147 | #include // kills off USB Host 148 | #endif 149 | #define SD_SPI_SCK_PIN 18 150 | #define SD_SPI_MISO_PIN 38 151 | #define SD_SPI_MOSI_PIN 23 152 | #define SD_SPI_CS_PIN 4 153 | #define CORE2 154 | 155 | #else 156 | #include 157 | #define SD_SPI_SCK_PIN 18 158 | #define SD_SPI_MISO_PIN 19 159 | #define SD_SPI_MOSI_PIN 23 160 | #define SD_SPI_CS_PIN 4 161 | #define CORE 162 | #endif 163 | 164 | #include 165 | #include 166 | #include "Wire.h" 167 | #include "time.h" 168 | #include "FS.h" 169 | #include 170 | #include 171 | 172 | #define IC705 0xA4 173 | #define IC905 0xAC 174 | #define IC9700 0xA2 175 | #define RADIO_ADDR IC705 176 | 177 | // NOTE: With a single USB virtual Serial port to the PC, ANY debug on Serial will interfere with a program like WSJT-X passing through to teh radio. 178 | 179 | #define CONTROLLER_ADDRESS 0xE5 //Controller address 180 | #define BROADCAST_ADDRESS 0x00 181 | 182 | #define START_BYTE 0xFE // Start byte 183 | #define STOP_BYTE 0xFD // Stop byte 184 | 185 | #define CMD_READ_FREQ 0x03 // Read operating frequency data 186 | 187 | #ifdef M5STAMPC3U // for embedded 705 Transverter solution 188 | #define WIRED_PTT 1 // 1 = use the wired input for fastest PTT response time 189 | // 0 = poll radio for TX status. Polling delay can be adjusted with parameters below. 190 | 191 | #else // choose for M5 Core or Atom CPUs 192 | #define WIRED_PTT 1 // 1 = use the wired input for fastest PTT 193 | // 0 = poll radio for TX status. Polling delay can be adjusted with parameters below. 194 | #endif 195 | 196 | #define PTT_DELAY 50 // PTT sequencing delay. At start of PTT -> TX event, turns OFF IF switch to prevent 197 | // RF flowing while downstream relays are switching. 198 | 199 | #define POLL_PTT_DEFAULT 247 // poll the radio for PTT status odd numbers to stagger them a bit 200 | // USB on both the 705 and 905 respond to PTT requests slower on USB than BT on the 705. 201 | // Also polls the wired inputs Can go down to 25-45. When using wired PTT set this slow. 202 | #define POLL_PTT_USBHOST 262 // Dynamically changes value based on detected radio address. 203 | // By observation, on USB, the radio only responds once every few seconds when the radio \ 204 | // has not changed states. It will immediately reply to a poll if the Tx state changed. \ 205 | // Still have to poll fast for controlling external PTT, most requests will not be answered. \ 206 | // Unlike other modes. BT seems to answer every request. USB2 engine is likely the same in \ 207 | // all radios, where BT got a capacity upgrade. The 905 acts the same as the 905 (905 is USB only) \ 208 | // Have not compared to a LAN connection. 209 | #define POLL_RADIO_FREQ 708 // poll the radio for frequency 210 | #define POLL_RADIO_UTC 998 // poll radio for time and location 211 | #define POLL_RADIO_MODE 6101 // poll radio for extended mode, filter and datamode 212 | #define POLL_RADIO_AGC 3403 // poll radio for AGC 213 | #define POLL_RADIO_ATTN 3305 // poll radio for atten status 214 | #define POLL_RADIO_PRE 3204 // poll radio for preamp status 215 | #define POLL_RADIO_SPLIT 3102 // poll radio for split status 216 | #define POLL_RADIO_RFPWR 1713 // poll radio for RF power for active band 217 | 218 | #ifndef M5STAMPC3U // None of these apply to the M5StampC3U as used in the 705 Transverter project 219 | // Chose the combination needed. Note that at least one comm service must be enabled. 220 | #define BTCLASSIC // Can define BTCLASSIC *** OR *** BLE, not both. No BT version is OK if USB Host is enabled 221 | // BT Classic does not work on Core3. It might on Core2 (untested) 222 | //#define BLE // Core 3 (BT5). Works on Core 2, (BT4.2) not on Core 223 | //#define USBHOST // if no BLE or BTCLASSIC this must be enabled. *** USB Host is not stable so far **** 224 | //#define IO_MODULE // enable the 4-In/8-Out module OR EXT_IO2_UNIT - BOTH are default at addr = 0x45 225 | //#define EXT_IO2_UNIT // EXT.IO2 UNIT GIO extender - plugs into Port A i2c Grove port on CPU module, adds 8 GPIO ports at 3.3V max. 226 | #define SD_CARD // enable sd card features 227 | //#define RELAY2_UNIT // enable 1 or 2 channel UNIT-RELAY module on Port A, B or C - Units are most useful on the AtomS3 or M5StampS3/C3U 228 | //#define RELAY4_UNIT // enable the i2c Relay-4 unit, typically plugged into Port A (i2C). 229 | //#define MODULE_4RELAY_13_2 // enable the stacking 4 channel relay module - be sure to set the jumpers for each port relay contacts addr = 0x26 230 | #else 231 | #define INA226_I2C // Current and voltage monitor module via i2c bus. Info is displayed on the SSD1306_OLED so that must be enabled. 232 | #define SSD1306_OLED // 128x32 OLED display, SSD1306 compatible. Shows band, TX, Xvtr, voltage and current. Band. Xvtr, Tx can be displayed without a INA226 installed 233 | #endif 234 | 235 | #ifndef PC_PASSTHROUGH // shut off by default when PASSTHRU MODE is on 236 | #define PRINT_VFO_TO_SERIAL // uncomment to visually see VFO updates from the radio on Serial 237 | #define PRINT_PTT_TO_SERIAL // uncomment to visually see PTT updates from the radio on Serial 238 | #define NO_SEND // block changes to radio from controller - used for PC pass thru 239 | #else 240 | //#define SKIP_XVTR_FREQ_XLATE // Skip frquency translation when in PC Pass-through mode. Useful when extrnal apps handle Xvtr band offsets 241 | #undef NO_SEND // block changes to radio from controller - used for PC pass thru 242 | #endif 243 | 244 | //-------------------------------------- END OF USER CONFIG --------------------------------------------------------------- 245 | 246 | //************************************************************************************************************************************* 247 | //************************************* should not be any user config below this point ********************************************* 248 | //************************************************************************************************************************************* 249 | 250 | #define SPI_FREQ (25000000u) // SPI bus speed - impacts reliability of SD card and mostly the USB v1.2 module 251 | // which is desgned for 26Mhz but we get lockups at higher speeds. 252 | 253 | #if defined ( CONFIG_IDF_TARGET_ESP32S3 ) 254 | #undef BTCLASSIC // Only BLE on S3 255 | //#define USBHOST // use this for now until BLE code added 256 | //#define WATCH_BLE_SERIAL 257 | #elif defined ( ARDUINO_M5STACK_CORE2 ) || defined ( ARDUINO_M5STACK_Core2 ) // For Core2 both BLE and BT Classic OK 258 | #if defined ( BTCLASSIC ) && defined ( BLE) 259 | #undef BLE // BTCLASSIC is more reliable and faster connect so far. 260 | #endif 261 | //#define USBHOST // use this for now until BLE code added 262 | //#define WATCH_BLE_SERIAL 263 | #else 264 | #undef BLE // BLE does not work on Core Basic so BTCLAsssic only 265 | #endif 266 | 267 | //#define SSP // use BT SSP - pair with a passkey 268 | 269 | #ifdef INA226_I2C // Current and Voltage monitor module 270 | #include "INA226.h" // https://github.com/RobTillaart/INA226 271 | #endif 272 | 273 | #ifdef SSD1306_OLED 274 | #include 275 | #include 276 | #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 277 | #define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 278 | #define SCREEN_WIDTH 128 // OLED display width, in pixels 279 | #define SCREEN_HEIGHT 32 // OLED display height, in pixels 280 | #endif 281 | 282 | // After #defines 283 | #include "DebugPrint.h" 284 | #include "CIV.h" 285 | 286 | // Function prototypes: 287 | void configRadioBaud(uint16_t); 288 | uint8_t readLine(void); 289 | bool searchRadio(); 290 | void sendCatRequest(const uint8_t cmd_num, const uint8_t Data[], const uint8_t Data_len); // first byte in Data is length 291 | void printFrequency(void); 292 | void processCatMessages(); 293 | void sendBit(int); 294 | void sendBand(byte); 295 | void printDirectory(File dir, int numTabs); 296 | void UpdateFromFS(fs::FS &fs); 297 | void read_Frequency(uint64_t freq, uint8_t data_len); 298 | void draw_new_screen(void); 299 | unsigned int hexToDec(String hexString); 300 | void display_Freq(uint64_t _freq, bool _force); 301 | void display_Time(uint8_t _UTC, bool _force); 302 | void display_Xvtr(bool _band, bool _force); 303 | void display_PTT(bool _PTT_state, bool _force); 304 | void display_Band(uint8_t _band, bool _force); 305 | void display_Grid(char _grid[], bool _force); 306 | void SetFreq(uint64_t Freq, uint8_t cmd); 307 | uint8_t pass_PC_to_radio(void); 308 | 309 | //const uint64_t decMulti[] = { 100000000000, 10000000000, 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 }; 310 | 311 | #define BAUD_RATES_SIZE 4 312 | const uint16_t baudRates[BAUD_RATES_SIZE] = { 19200, 9600, 4800, 1200 }; 313 | 314 | struct Bands { 315 | char band_name[6]; // Freindly name or label. Default here but can be changed by user. 316 | uint64_t edge_lower; // band edge limits for TX and for when to change to next band when tuning up or down. 317 | uint64_t edge_upper; 318 | uint64_t Xvtr_offset; // Offset to add to radio frequency. 319 | // When all is correct, it will be within the band limits and allow PTT and Band decoder outputs 320 | uint64_t VFO_last; // store the last used frequency on each band. 321 | // for XVTR bands subtract the LO offset and send the result to the radio 322 | uint8_t mode_idx; // current mode stored as indexc to the modelist table. 323 | uint8_t filt; // current fiult soreds in teh modelist table 324 | uint8_t datamode; 325 | uint8_t agc; // store last agc. Some radio/band/mode combos only have 1. 326 | uint8_t preamp; // some bands there is no preamp (2.4G+ on 905). Some radios/bands/modes combos have 1 preamp level, others have 2 levels. 327 | uint8_t atten; // some bands there is no atten (some on 905). Some radios/bands/mode combos have 1 atten level, others have more. 328 | uint8_t split; // Split mode on or off 329 | uint8_t rfpwr; // RF Power set 0-255 range = 0-100% 330 | uint8_t InputMap; // If input pattern matches this value, then select this band. First match wins. 331 | }; 332 | 333 | extern uint8_t USBHost_ready; // 0 = not mounted. 1 = mounted, 2 = system not initialized 334 | extern bool USBH_connected; 335 | extern bool restart_USBH_flag; 336 | extern bool restart_BT_flag; 337 | extern uint16_t background_color; 338 | extern uint64_t frequency; 339 | extern bool update_radio_settings_flag; 340 | #define M5ATOMS3 11 341 | extern uint8_t board_type; 342 | 343 | #endif -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/M5Stack_CI-V_Band_Decoder.ino: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | ICOM CI-V Band Decoder and PTT breakout 3 | K7MDL 8/2024 4 | 5 | BT Classic Serial or USB Host connection for IC-705 6 | USB for other models 7 | Runs on M5Stack Core Basic, possible Core2. Core3 has issues with USB Host compatibility as of Aug 2024. 8 | 9 | For USB Host uses the M5Stack USB V1.2 module. 10 | The DIP switches for SPI INT and SS need to be set to 5 and 35 for the Core Basic. 11 | Core3 pins are different and set in usbh_helper.h 12 | 13 | This is based on a mege between 2 other works, the serial_host_bridge.inbo in Arduino examples, and 14 | T1 Interface V2.0 (12.09.2023) by Peter Jonas DL5DLA 15 | 16 | This is the main setup focused on USB Host setup then launches the app setup and loop 17 | which in turn starts up BT if enabled. The eventual goal is to have both services 18 | standing by and able to use one, the other , or both. Possible flipping both BT and USB around. 19 | 20 | For now this program does these main things: 21 | 1. Pass through in both direction Radio CI-V data if a PC is connect - Not finished 22 | This enables an optional USB PC connection for things like logging and WSJT-X). 23 | 2. Monitor Radio Frequency (active VFO) and display it, adding any band offset the band decoder input or User Input selects 24 | This enables Transverter selection, enable a band specific amplifier, or change antenna relays, all per band. 25 | 3. Monitor PTT and pass it through to a selected GPIO pin which in turn controls a port on the 4In/8Out M5Stack module. 26 | This enables PTT breakout per band 27 | 4. Optionally connect to the radio by USB Host or by BLE or BT Classic SPP (IC-705 only so far) 28 | 5. Radios tested so far - IC-705 and IC-905 29 | 6. Tested on M5Stack Core Basic, Core2 and CoreS3. 30 | 7. Can run with minor changes on M5StampC3U, M5StampS3, and M5AtomS3. 31 | 32 | Down the road, probably on BLE mesh, this could bridge a radio to a PC completely by BLE. 33 | 34 | The code on ths page is almost complete the serial_host_bridge.ino example file. 35 | 36 | I placed a hook into setup and loop for each architecture. I am only testing this on the M5Stack ESP32 models today 37 | though it may be possble to run on other CPUs like the pico some day, so I left all that in place 38 | and put all the app code in other files. There be need to ever edit this file. Same for usbh_helper.h 39 | except you may need to edit the SPI pins for different model CPU such as the Core3 or a Core 2 maybe. 40 | 41 | ********************************************************************* 42 | 43 | // INA226 library Info 44 | // AUTHOR: Rob Tillaart 45 | // URL: https://github.com/RobTillaart/INA226 46 | 47 | ********************************************************************* 48 | 49 | Adafruit invests time and resources providing this open source code, 50 | please support Adafruit and open-source hardware by purchasing 51 | products from Adafruit! 52 | 53 | MIT license, check LICENSE for more information 54 | Copyright (c) 2019 Ha Thach for Adafruit Industries 55 | All text above, and the splash screen below must be included in 56 | any redistribution 57 | *********************************************************************/ 58 | 59 | /* This example demonstrates use of both device and host, where 60 | * - Device run on native usb controller (roothub port0) 61 | * - Host depending on MCUs run on either: 62 | * - rp2040: bit-banging 2 GPIOs with the help of Pico-PIO-USB library (roothub port1) 63 | * - samd21/51, nrf52840, esp32: using MAX3421e controller (host shield) 64 | * 65 | * Requirements: 66 | * - For rp2040: 67 | * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library 68 | * - 2 consecutive GPIOs: D+ is defined by PIN_USB_HOST_DP, D- = D+ +1 69 | * - Provide VBus (5v) and GND for peripheral 70 | * - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed" 71 | * - For samd21/51, nrf52840, esp32: 72 | * - Additional MAX2341e USB Host shield or featherwing is required 73 | * - SPI instance, CS pin, INT pin are correctly configured in usbh_helper.h 74 | */ 75 | 76 | /* This example demonstrates use of Host Serial (CDC). SerialHost (declared below) is 77 | * an object to manage an CDC peripheral connected to our USB Host connector. This example 78 | * will forward all characters from Serial to SerialHost and vice versa. 79 | */ 80 | 81 | // nRF52 and ESP32 use freeRTOS, we may need to run USBhost.task() in its own rtos's thread. 82 | // Since USBHost.task() will put loop() into dormant state and prevent followed code from running 83 | // until there is USB host event. 84 | 85 | #include "M5Stack_CI-V_Band_Decoder.h" 86 | #include "Wire.h" 87 | #include "Decoder.h" 88 | #include "DebugPrint.h" 89 | #ifndef M5STAMPC3U 90 | #ifdef USBHOST 91 | //#include "M5_Max3421E_Usb.h" 92 | #endif 93 | #endif 94 | 95 | #if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_ESP32) 96 | #define USE_FREERTOS 97 | #endif 98 | 99 | #ifndef M5STAMPC3U 100 | #ifdef USBHOST 101 | // USBHost is defined in usbh_helper.h 102 | #include "usbh_helper.h" 103 | // CDC Host object 104 | Adafruit_USBH_CDC SerialHost; 105 | 106 | // Language ID: English 107 | #define LANGUAGE_ID 0x0409 108 | 109 | typedef struct { 110 | tusb_desc_device_t desc_device; 111 | uint16_t manufacturer[32]; 112 | uint16_t product[48]; 113 | uint16_t serial[16]; 114 | bool mounted; 115 | } dev_info_t; 116 | 117 | // CFG_TUH_DEVICE_MAX is defined by tusb_config header 118 | dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 }; 119 | #endif 120 | #else // for M5STAMP{C3U which has a SK6812 RGB LED button. 121 | Adafruit_NeoPixel pixel(NUM_PIXELS, PIXEL_PIN, NEO_GRBW + NEO_KHZ400); 122 | bool currentButtonPressed = false; 123 | #endif 124 | 125 | #ifdef PC_PASSTHRU_USBHOST // This is unused code, saving for reference 126 | // forward Serial <-> SerialHost 127 | void forward_serial(void) { 128 | uint8_t buf[64]; 129 | //Serial.print("^"); 130 | // Serial -> SerialHost 131 | if (Serial.available()) { 132 | size_t count = Serial.read(buf, sizeof(buf)); 133 | if (SerialHost && SerialHost.connected()) { 134 | SerialHost.write(buf, count); 135 | SerialHost.flush(); 136 | } 137 | } 138 | 139 | // SerialHost -> Serial 140 | if (SerialHost.connected() && SerialHost.available()) { 141 | size_t count = SerialHost.read(buf, sizeof(buf)); 142 | Serial.write(buf, count); 143 | Serial.flush(); 144 | } 145 | } 146 | #endif 147 | 148 | #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 149 | //--------------------------------------------------------------------+ 150 | // Using Host shield MAX3421E controller 151 | //--------------------------------------------------------------------+ 152 | //#define CFG_TUD_COUNT 2 153 | #endif 154 | 155 | #ifdef USE_FREERTOS 156 | 157 | #ifdef ARDUINO_ARCH_ESP32 158 | #define USBH_STACK_SZ 8000 159 | #else 160 | #define USBH_STACK_SZ 200 161 | #endif 162 | 163 | #ifndef M5STAMPC3U 164 | #ifdef USBHOST 165 | TaskHandle_t xHandle = NULL; 166 | 167 | void usbhost_rtos_task(void *param) { 168 | (void) param; 169 | while (1) { 170 | //Serial.print("+"); 171 | USBHost.task(10, false); 172 | //vTaskDelay(10); 173 | // test for stack size 174 | uint32_t stack_sz; 175 | stack_sz = uxTaskGetStackHighWaterMark( NULL ); 176 | if (stack_sz < 1000) 177 | Serial.printf("\n ####### USB Host Loop: Stack Size Low Space Warning < 1000 words left free: %lu\n",stack_sz); 178 | } 179 | vTaskDelete(NULL); 180 | } 181 | #endif 182 | #endif 183 | 184 | extern void app_loop(); 185 | 186 | void app_loop_rtos_task(void *param) { 187 | (void) param; 188 | while (1) { 189 | app_loop(); 190 | //Serial.print("\nA"); 191 | //vTaskDelay(12); 192 | // test for stack size 193 | uint32_t stack_sz; 194 | stack_sz = uxTaskGetStackHighWaterMark( NULL ); 195 | if (stack_sz < 1000) 196 | Serial.printf("\n ^^^^^^^^^^^ app_loop: Stack Size Low Space Warning < 1000 words left free: %lu\n",stack_sz); 197 | } 198 | vTaskDelete(NULL); 199 | } 200 | 201 | #ifdef BLE 202 | extern void BLE_loop(); 203 | 204 | void BLE_loop_rtos_task(void *param) { 205 | (void) param; 206 | while (1) { 207 | BLE_loop(); 208 | //Serial.print("\nT"); 209 | //vTaskDelay(12); 210 | // test for stack size 211 | uint32_t stack_sz; 212 | stack_sz = uxTaskGetStackHighWaterMark( NULL ); 213 | if (stack_sz < 1000) 214 | Serial.printf("\n ^^^^^^^^^^^ BLE_loop: Stack Size Low Space Warning < 1000 words left free: %lu\n",stack_sz); 215 | } 216 | vTaskDelete(NULL); 217 | } 218 | #endif // BLE 219 | 220 | #ifndef M5STAMPC3U 221 | void btn_loop_rtos_task(void *param) { 222 | (void) param; 223 | while (1) { 224 | chk_btns(); 225 | //Serial.print("\nT"); 226 | //vTaskDelay(12); 227 | // test for stack size 228 | uint32_t stack_sz; 229 | stack_sz = uxTaskGetStackHighWaterMark( NULL ); 230 | if (stack_sz < 1000) 231 | Serial.printf("\n ^^^^^^^^^^^ chk_btns: Stack Size Low Space Warning < 1000 words left free: %lu\n",stack_sz); 232 | } 233 | vTaskDelete(NULL); 234 | } 235 | #endif 236 | 237 | #endif // FREERTOS 238 | 239 | extern void BLE_Setup(); 240 | extern void Scan_BLE_Servers(); 241 | extern void app_setup(); 242 | uint8_t USBHost_ready = 2; // 0 = not mounted. 1 = mounted, 2 = system not initialized 243 | bool USBH_connected = false; 244 | bool restart_USBH_flag = false; 245 | bool restart_BT_flag = false; 246 | bool BtnA_pressed = false; 247 | bool BtnB_pressed = false; 248 | bool BtnC_pressed = false; 249 | uint64_t frequency = 0; 250 | uint8_t board_type = 0; 251 | 252 | #ifndef M5STAMPC3U 253 | void chk_btns(void) { 254 | #if defined ( CONFIG_IDF_TARGET_ESP32S3 ) && !defined ( __M5GFX_M5ATOMDISPLAY__ ) 255 | auto touchPoint = M5.Touch.getDetail(); 256 | if (prev_state != touchPoint.state) { 257 | prev_state = touchPoint.state; 258 | } 259 | if ((M5.Display.height() > touchPoint.y && 260 | touchPoint.y > M5.Display.height() - 40) && 261 | touchPoint.state == m5::touch_state_t::touch_begin) { 262 | if (M5.Display.width() / 3 > touchPoint.x && touchPoint.x > 0){ 263 | BtnA_pressed = true; 264 | DPRINTLNF("3A"); 265 | } 266 | if ((M5.Display.width() / 3) * 2 > touchPoint.x && 267 | touchPoint.x > M5.Display.width() / 3) { 268 | BtnB_pressed = true; 269 | DPRINTLNF("3B"); 270 | } 271 | if (M5.Display.width() > touchPoint.x && 272 | touchPoint.x > (M5.Display.width() / 3) * 2) { 273 | BtnC_pressed = true; 274 | DPRINTLNF("3C"); 275 | } 276 | } 277 | 278 | #elif !defined ( CORE2LIB ) && ( defined ( ARDUINO_M5STACK_CORE2 ) || defined ( ARDUINO_M5STACK_Core2 ) ) 279 | int state = M5.BtnA.wasHold() ? 1 280 | : M5.BtnA.wasClicked() ? 2 281 | : M5.BtnA.wasPressed() ? 3 282 | : M5.BtnA.wasReleased() ? 4 283 | : M5.BtnA.wasDecideClickCount() ? 5 284 | : 0; 285 | if (state == 3 && !BtnA_pressed) { // Only process once the main loop is done 286 | BtnA_pressed = true; 287 | DPRINTF("2A, state = "); DPRINTLN(state); 288 | } 289 | 290 | state = M5.BtnB.wasHold() ? 1 291 | : M5.BtnB.wasClicked() ? 2 292 | : M5.BtnB.wasPressed() ? 3 293 | : M5.BtnB.wasReleased() ? 4 294 | : M5.BtnB.wasDecideClickCount() ? 5 295 | : 0; 296 | if (state == 3 && !BtnB_pressed) { 297 | BtnB_pressed = true; 298 | DPRINTF("2B, state = "); DPRINTLN(state); 299 | } 300 | 301 | state = M5.BtnC.wasHold() ? 1 302 | : M5.BtnC.wasClicked() ? 2 303 | : M5.BtnC.wasPressed() ? 3 304 | : M5.BtnC.wasReleased() ? 4 305 | : M5.BtnC.wasDecideClickCount() ? 5 306 | : 0; 307 | if (state == 3 & !BtnC_pressed) { 308 | BtnC_pressed = true; 309 | DPRINTF("2C, state = "); DPRINTLN(state); 310 | } 311 | 312 | #elif !defined (M5STAMPC3U) 313 | if (//M5.BtnA.wasReleased() || 314 | M5.BtnA.pressedFor(100, 3000)) { 315 | BtnA_pressed = true; 316 | DPRINTLNF("A"); 317 | } else if (//M5.BtnB.wasReleased() || 318 | M5.BtnB.pressedFor(100, 3000)) { 319 | BtnB_pressed = true; 320 | DPRINTLNF("B"); 321 | } else if (//M5.BtnC.wasReleased() || 322 | M5.BtnC.pressedFor(100, 3000)) { 323 | BtnC_pressed = true; 324 | DPRINTLNF("C"); 325 | } 326 | #endif 327 | } 328 | #endif //M5STAMPC3U 329 | 330 | // 331 | // Main Setup for ESP32 332 | // 333 | void setup() { 334 | Serial.begin(115200); 335 | while ( !Serial ) delay(10); // wait for native usb 336 | 337 | #ifdef M5STAMPC3U 338 | //auto cfg = M5.config(); 339 | //M5.begin(cfg); 340 | //M5.Power.begin(); 341 | Wire.begin(I2C_SDA, I2C_SCL); // M5StampC3U i2c 342 | // set up neopixel 343 | pixel.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) 344 | pixel.clear(); // Set pixel colors to 'off' 345 | pixel.show(); 346 | // set up GPIO 347 | Serial.println("Turning LED blue"); 348 | pixel.setPixelColor(0, pixel.Color(0, 0, 128)); 349 | pixel.show(); 350 | //Serial.println("turning LED red"); 351 | //pixel.setPixelColor(0, pixel.Color(128, 0, 0)); 352 | //pixel.show(); 353 | 354 | #elif CONFIG_IDF_TARGET_ESP32S3 355 | auto cfg = M5.config(); 356 | M5.begin(cfg); 357 | M5.Power.begin(); 358 | #ifdef ATOMS3 359 | DPRINTLNF("ATOMS3 defined") 360 | #endif 361 | board_type = M5.getBoard(); 362 | if (board_type == M5ATOMS3) { 363 | DPRINTLNF("AtomS3 ext i2c pins defined"); 364 | Wire.begin(2,1); // M5AtomS3 external i2c 365 | M5.Lcd.setRotation(3); // 0 to 3 rotate, 4 to 7 reverse and rotate. 366 | M5.Lcd.setBrightness(30); // 0- 255 367 | } else { 368 | DPRINTLNF("CoreS3 or CoreS3SE ext i2C pins defined"); 369 | Wire.begin(12,11); // CoreS3 and ?StampC3U? 370 | } 371 | //M5.Touch.begin(); 372 | auto ms = millis(); 373 | if (M5.Touch.isEnabled()) 374 | M5.Touch.update(ms); 375 | //M5.Power.setExtOutput(true); // .powerModeSet(POWER_MODE_USB_IN_BUS_OUT); 376 | //SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN); 377 | 378 | #elif defined ( ARDUINO_M5STACK_CORE2 ) || defined ( ARDUINO_M5STACK_Core2 ) 379 | DPRINTLNF("Core2 defined"); 380 | #if defined (IO_MODULE) || defined (EXT_IO2_UNIT) 381 | Wire.begin(21,22); 382 | #endif 383 | //SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN); 384 | 385 | #ifdef CORE2LIB 386 | // M5Core2.h stuff USB Host sort of works, Touch Buttons not so much. 387 | M5.begin(); 388 | M5.Axp.begin(); 389 | DPRINTF("Power Status 0=external, 1=internal 2=max "); DPRINTLN(M5.Axp.isACIN() ? 0 : 1); 390 | M5.Touch.begin(); 391 | //if (M5.Touch.isEnabled()) 392 | M5.Touch.update(); 393 | #else 394 | //// M5Unified.h stuff = kills USB Host though, makes the touch buttons work. 395 | auto cfg = M5.config(); 396 | M5.begin(cfg); 397 | M5.Power.begin(); 398 | auto ms = millis(); 399 | if (M5.Touch.isEnabled()) { 400 | M5.Touch.update(ms); 401 | } 402 | #endif 403 | 404 | #else 405 | DPRINTLNF("Core Basic defined"); 406 | M5.begin(); //(true, false, true, true); // 2nd arg is enable SD card, off now. 407 | #if defined (IO_MODULE) || defined (EXT_IO2_UNIT) 408 | Wire.begin(21,22); 409 | #endif 410 | //SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN); 411 | #endif 412 | 413 | #ifndef M5STAMPC3U 414 | SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN); 415 | //SPI.setFrequency(SPI_FREQ); 416 | #endif 417 | 418 | #ifdef USBHOST 419 | // init host stack on controller (rhport) 1 420 | USBHost.begin(1); 421 | // Initialize SerialHost 422 | SerialHost.begin(115200); 423 | #endif 424 | 425 | #ifdef USE_FREERTOS 426 | #ifdef USBHOST 427 | // Create a task to run USBHost.task() in background 428 | //xTaskCreatePinnedToCore(usbhost_rtos_task, "usbh", USBH_STACK_SZ, NULL, 4, NULL, 0); 429 | xTaskCreate(usbhost_rtos_task, "usbh", 8000, NULL, 3, NULL); 430 | 431 | Serial.printf("USB pre-start status = %d\n", USBHost_ready); 432 | Serial.printf(" USBH_connected = %d\n",USBH_connected); 433 | int count = 0; 434 | while (USBHost_ready == 2 && count < 200) // 0 of nothing, 1 for device connected. value started at 2 so we know init is done. 435 | { 436 | delay(40); 437 | Serial.print(count); 438 | count++; 439 | } 440 | Serial.printf("USB post-start status = %d\n", USBHost_ready); 441 | Serial.printf(" USBH_connected = %d\n", USBH_connected); 442 | 443 | app_setup(); // setup app stuff 444 | //xTaskCreatePinnedToCore(app_loop_rtos_task, "app", 8000, NULL, 3, &xHandle, 1); 445 | //xTaskCreate(app_loop_rtos_task, "app", 8000, NULL, 3, &xHandle); 446 | //xTaskCreate(BLE_loop_rtos_task, "BLE", 8000, NULL, 2, &xHandle); // callback on server ID not working inside a task 447 | //xTaskCreate(btn_loop_rtos_task, "btns", 8000, NULL, 2, &xHandle); // callback on server ID not working inside a task 448 | #endif // USBHOST 449 | #endif // FREERTOS 450 | 451 | #ifndef USBHOST 452 | app_setup(); // setup app stuff 453 | #endif 454 | 455 | #ifdef BLE 456 | BLE_Setup(); 457 | Scan_BLE_Servers(); 458 | #endif // BLE 459 | 460 | DPRINTLNF("Setup Done"); 461 | } 462 | 463 | //***************************************************************************** 464 | // 465 | // Main Loop. Call app_setup() to run main application 466 | // 467 | //***************************************************************************** 468 | 469 | void loop() { 470 | 471 | static int32_t loop_time = 0; 472 | static int32_t loop_max_time = 0; 473 | int32_t loop_time_threshold = 10; 474 | static int32_t prev_loop_time = 0; 475 | 476 | loop_time = millis(); // watermark 477 | 478 | #ifndef USE_FREERTOS 479 | //USBHost.task(10,false); 480 | //USBHost.task(); 481 | #endif 482 | 483 | #ifndef M5STAMPC3U 484 | M5.update(); 485 | chk_btns(); 486 | #endif 487 | 488 | #ifdef _PC_PASSTHRU // Unused code, save for reference or test 489 | // allow a PC to talk to the radio and opposite. Need debug shutoff typically 490 | forward_serial(); 491 | #endif // _PC_PASSTHRU 492 | 493 | pass_PC_to_radio(); 494 | 495 | //Serial.print("."); //causes crashes on PC due to too high data rate 496 | 497 | #ifdef BLE 498 | BLE_loop(); 499 | #endif // BLE 500 | 501 | //#ifdef USBHOST 502 | app_loop(); // call to application main loop - moved to FreeRTOS task 503 | // #endif 504 | 505 | #ifndef M5STAMPC3U 506 | // Measure our current and max loop times 507 | int32_t temp_time = millis() - loop_time; // current loop duration 508 | 509 | if ((temp_time > loop_max_time) || temp_time > loop_time_threshold) { 510 | if (temp_time > loop_max_time) 511 | loop_max_time = temp_time; 512 | //Serial.print("!"); // Turn on to see RTOS scheduling time allocated visually 513 | if (loop_max_time > loop_time_threshold) { 514 | //Serial.printf("! loop time > %d current time = %d max time seen %d\n", loop_time_threshold, temp_time, loop_max_time); 515 | //Serial.println(" App loop time > 500!"); 516 | M5.Lcd.setTextDatum(ML_DATUM); 517 | M5.Lcd.setTextColor(WHITE, background_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 518 | M5.Lcd.drawString("!", 0, 0, 2); 519 | //if (loop_max_time > 3000 && SerialBT.isClosed() && SerialBT.isReady()) 520 | // restart_BT(); // try this as a USBHost lockup failover short of having the btn task 521 | } // delete and restart the app task, or even the USBHost task 522 | else { 523 | M5.Lcd.setTextDatum(ML_DATUM); // erase the marker 524 | M5.Lcd.setTextColor(background_color, background_color); //Set the color of the text from 0 to 65535, and the background color behind it 0 to 65535 525 | M5.Lcd.drawString("!", 0, 0, 2); 526 | } 527 | } 528 | #endif // M5STAMPC3U 529 | 530 | //uint32_t stack_sz; 531 | //stack_sz = uxTaskGetStackHighWaterMark( NULL ); 532 | //if (stack_sz < 1000) 533 | //Serial.printf("\n ####### App Loop: Stack Size Low Space Warning < 1000 words left free: %lu\n",stack_sz); 534 | } 535 | 536 | #ifndef M5STAMPC3U 537 | void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, 538 | uint8_t const* report, uint16_t len) { 539 | } 540 | 541 | //--------------------------------------------------------------------+ 542 | // TinyUSB Host callbacks 543 | //--------------------------------------------------------------------+ 544 | 545 | // Invoked when a device with CDC interface is mounted 546 | // idx is index of cdc interface in the internal pool. 547 | void tuh_cdc_mount_cb(uint8_t idx) { 548 | // bind SerialHost object to this interface 549 | #ifdef USBHOST 550 | SerialHost.mount(idx); 551 | #endif 552 | Serial.println("\n****** SerialHost is connected to a new CDC device"); 553 | USBH_connected = true; 554 | frequency = 0; 555 | //BT_enabled= false; 556 | delay(1200); // Delay first Tx or get a hang. 557 | //SerialHost.flush(); 558 | } 559 | 560 | // Invoked when a device with CDC interface is unmounted 561 | void tuh_cdc_umount_cb(uint8_t idx) { 562 | #ifdef USBHOST 563 | SerialHost.umount(idx); 564 | #endif 565 | Serial.println("\n****** SerialHost is disconnected"); 566 | USBH_connected = false; 567 | frequency = 0; // force the screen to update if reconnecting to same frequency 568 | //btConnected = false; 569 | //BT_enabled = true; 570 | ESP.restart(); 571 | } 572 | 573 | #ifdef USBHOST 574 | //--------------------------------------------------------------------+ 575 | // TinyUSB Host callbacks 576 | //--------------------------------------------------------------------+ 577 | 578 | void print_device_descriptor(tuh_xfer_t *xfer); 579 | 580 | void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len); 581 | 582 | void print_lsusb(void) { 583 | bool no_device = true; 584 | for (uint8_t daddr = 1; daddr < CFG_TUH_DEVICE_MAX + 1; daddr++) { 585 | // TODO can use tuh_mounted(daddr), but tinyusb has an bug 586 | // use local connected flag instead 587 | dev_info_t *dev = &dev_info[daddr - 1]; 588 | if (dev->mounted) { 589 | Serial.printf("Device %u: ID %04x:%04x %s %s\r\n", daddr, 590 | dev->desc_device.idVendor, dev->desc_device.idProduct, 591 | (char *) dev->manufacturer, (char *) dev->product); 592 | 593 | no_device = false; 594 | } 595 | } 596 | 597 | if (no_device) { 598 | Serial.println("No device connected (except hub)"); 599 | } 600 | USBHost_ready = (uint8_t) no_device; // flag for setup to wait for USB Host to be ready. 601 | } 602 | 603 | //void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, 604 | // uint8_t const* report, uint16_t len) { 605 | //} 606 | 607 | // Invoked when device is mounted (configured) 608 | void tuh_mount_cb(uint8_t daddr) { 609 | Serial.printf("Device attached, address = %d\r\n", daddr); 610 | 611 | dev_info_t *dev = &dev_info[daddr - 1]; 612 | dev->mounted = true; 613 | USBHost_ready = 1; // flag for setup to wait for USB Host to be ready. 614 | 615 | // Get Device Descriptor 616 | tuh_descriptor_get_device(daddr, &dev->desc_device, 18, print_device_descriptor, 0); 617 | } 618 | 619 | /// Invoked when device is unmounted (bus reset/unplugged) 620 | void tuh_umount_cb(uint8_t daddr) { 621 | Serial.printf("Device removed, address = %d\r\n", daddr); 622 | dev_info_t *dev = &dev_info[daddr - 1]; 623 | dev->mounted = false; 624 | 625 | // print device summary 626 | print_lsusb(); 627 | } 628 | 629 | void print_device_descriptor(tuh_xfer_t *xfer) { 630 | if (XFER_RESULT_SUCCESS != xfer->result) { 631 | Serial.printf("Failed to get device descriptor\r\n"); 632 | return; 633 | } 634 | 635 | uint8_t const daddr = xfer->daddr; 636 | dev_info_t *dev = &dev_info[daddr - 1]; 637 | tusb_desc_device_t *desc = &dev->desc_device; 638 | 639 | Serial.printf("Device %u: ID %04x:%04x\r\n", daddr, desc->idVendor, desc->idProduct); 640 | Serial.printf("Device Descriptor:\r\n"); 641 | Serial.printf(" bLength %u\r\n" , desc->bLength); 642 | Serial.printf(" bDescriptorType %u\r\n" , desc->bDescriptorType); 643 | Serial.printf(" bcdUSB %04x\r\n" , desc->bcdUSB); 644 | Serial.printf(" bDeviceClass %u\r\n" , desc->bDeviceClass); 645 | Serial.printf(" bDeviceSubClass %u\r\n" , desc->bDeviceSubClass); 646 | Serial.printf(" bDeviceProtocol %u\r\n" , desc->bDeviceProtocol); 647 | Serial.printf(" bMaxPacketSize0 %u\r\n" , desc->bMaxPacketSize0); 648 | Serial.printf(" idVendor 0x%04x\r\n" , desc->idVendor); 649 | Serial.printf(" idProduct 0x%04x\r\n" , desc->idProduct); 650 | Serial.printf(" bcdDevice %04x\r\n" , desc->bcdDevice); 651 | 652 | // Get String descriptor using Sync API 653 | Serial.printf(" iManufacturer %u ", desc->iManufacturer); 654 | if (XFER_RESULT_SUCCESS == 655 | tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, dev->manufacturer, sizeof(dev->manufacturer))) { 656 | utf16_to_utf8(dev->manufacturer, sizeof(dev->manufacturer)); 657 | Serial.printf((char *) dev->manufacturer); 658 | } 659 | Serial.printf("\r\n"); 660 | 661 | Serial.printf(" iProduct %u ", desc->iProduct); 662 | if (XFER_RESULT_SUCCESS == 663 | tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, dev->product, sizeof(dev->product))) { 664 | utf16_to_utf8(dev->product, sizeof(dev->product)); 665 | Serial.printf((char *) dev->product); 666 | } 667 | Serial.printf("\r\n"); 668 | 669 | Serial.printf(" iSerialNumber %u ", desc->iSerialNumber); 670 | if (XFER_RESULT_SUCCESS == 671 | tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, dev->serial, sizeof(dev->serial))) { 672 | utf16_to_utf8(dev->serial, sizeof(dev->serial)); 673 | Serial.printf((char *) dev->serial); 674 | } 675 | Serial.printf("\r\n"); 676 | 677 | Serial.printf(" bNumConfigurations %u\r\n", desc->bNumConfigurations); 678 | 679 | // print device summary 680 | print_lsusb(); 681 | } 682 | 683 | //--------------------------------------------------------------------+ 684 | // String Descriptor Helper 685 | //--------------------------------------------------------------------+ 686 | 687 | static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) { 688 | // TODO: Check for runover. 689 | (void) utf8_len; 690 | // Get the UTF-16 length out of the data itself. 691 | 692 | for (size_t i = 0; i < utf16_len; i++) { 693 | uint16_t chr = utf16[i]; 694 | if (chr < 0x80) { 695 | *utf8++ = chr & 0xff; 696 | } else if (chr < 0x800) { 697 | *utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F)); 698 | *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F)); 699 | } else { 700 | // TODO: Verify surrogate. 701 | *utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F)); 702 | *utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F)); 703 | *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F)); 704 | } 705 | // TODO: Handle UTF-16 code points that take two entries. 706 | } 707 | } 708 | 709 | // Count how many bytes a utf-16-le encoded string will take in utf-8. 710 | static int _count_utf8_bytes(const uint16_t *buf, size_t len) { 711 | size_t total_bytes = 0; 712 | for (size_t i = 0; i < len; i++) { 713 | uint16_t chr = buf[i]; 714 | if (chr < 0x80) { 715 | total_bytes += 1; 716 | } else if (chr < 0x800) { 717 | total_bytes += 2; 718 | } else { 719 | total_bytes += 3; 720 | } 721 | // TODO: Handle UTF-16 code points that take two entries. 722 | } 723 | return total_bytes; 724 | } 725 | 726 | void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) { 727 | size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); 728 | size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len); 729 | 730 | _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, buf_len); 731 | ((uint8_t *) temp_buf)[utf8_len] = '\0'; 732 | } 733 | #endif // USBHOST 734 | #endif // M5STAMPC3U 735 | -------------------------------------------------------------------------------- /M5Stack_CI-V_Band_Decoder/usbh_helper.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | Adafruit invests time and resources providing this open source code, 3 | please support Adafruit and open-source hardware by purchasing 4 | products from Adafruit! 5 | 6 | MIT license, check LICENSE for more information 7 | Copyright (c) 2019 Ha Thach for Adafruit Industries 8 | All text above, and the splash screen below must be included in 9 | any redistribution 10 | *********************************************************************/ 11 | 12 | #ifndef USBH_HELPER_H 13 | #define USBH_HELPER_H 14 | 15 | #include 16 | 17 | #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 18 | // USB Host using MAX3421E: SPI, CS, INT 19 | #include "SPI.h" 20 | 21 | // Default CS and INT are pin 5, 35, these are with G34 INT switch set on USB host board 22 | #ifdef CONFIG_IDF_TARGET_ESP32S3 23 | M5_USBH_Host USBHost(&SPI, 36, 37, 35, 1, 10); // Core3 default INT switch G35 position 24 | //M5_USBH_Host USBHost(&SPI, 36, 37, 35, 1, 14); // Core3 Alt INT G34 position 25 | #elif defined ( ARDUINO_M5STACK_CORE2 ) || defined ( ARDUINO_M5STACK_Core2 ) // maybe library confusing CS pins with display in places. 26 | M5_USBH_Host USBHost(&SPI, 18, 23, 38, 33, 35); // Core2 default, INT G35 position SD card uses INT=4, display INT=5 TOUCh=39 27 | //M5_USBH_Host USBHost(&SPI, 18, 23, 38, 33, 34); // Corealt , INT G34 position 28 | #else 29 | //default pins 30 | M5_USBH_Host USBHost(&SPI, 18, 23, 19, 5, 35); // Core basic default, INT G35 position 31 | //M5_USBH_Host USBHost(&SPI, 18, 23, 19, 5, 34); // Core basic match to your DIP USB module switches 34 is used for Mic data 32 | #endif 33 | #endif // CFG_TUH_MAX3421 34 | #endif // USBH_HELPER_H 35 | -------------------------------------------------------------------------------- /Pictures/50W 28VDC 903MHz RF Amp pallet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/50W 28VDC 903MHz RF Amp pallet.jpg -------------------------------------------------------------------------------- /Pictures/50W 28VDC 903MHz RF Amp pallet internal .jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/50W 28VDC 903MHz RF Amp pallet internal .jpg -------------------------------------------------------------------------------- /Pictures/900Mhz 50W RF amp installed and working.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/900Mhz 50W RF amp installed and working.jpg -------------------------------------------------------------------------------- /Pictures/900Mhz 50W amp mounted on heat sinking end panel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/900Mhz 50W amp mounted on heat sinking end panel.jpg -------------------------------------------------------------------------------- /Pictures/Aug-10-2024_UI_Xvtr_grid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/Aug-10-2024_UI_Xvtr_grid.jpg -------------------------------------------------------------------------------- /Pictures/Aug-9-2024_UI_makeover-small-aug9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/Aug-9-2024_UI_makeover-small-aug9.jpg -------------------------------------------------------------------------------- /Pictures/Chassis end panels have heat sink fins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/Chassis end panels have heat sink fins.jpg -------------------------------------------------------------------------------- /Pictures/Core Basic and Core3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/Core Basic and Core3.jpg -------------------------------------------------------------------------------- /Pictures/Core Basic in early dev.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/Core Basic in early dev.jpg -------------------------------------------------------------------------------- /Pictures/Core3 Se connected by BLE to IC-705.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/Core3 Se connected by BLE to IC-705.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL BT CI-V decoders.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL BT CI-V decoders.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Xvtr icons ON.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Xvtr icons ON.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Band.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Band.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - current.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - current.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - voltage -TX icon on.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - voltage -TX icon on.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - voltage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - voltage.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 -TX and Xvtr icons ON.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 -TX and Xvtr icons ON.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - 12V power distribution.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - 12V power distribution.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Back View.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Back View.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Control Board with M5StampC3U.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Control Board with M5StampC3U.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View Front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View Front.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View Side 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View Side 2.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top View.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top view 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Top view 1.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Wiring it up.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 - Wiring it up.jpg -------------------------------------------------------------------------------- /Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 M5Core2 Radio side - BT connected.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/K7MDL IC-705 3-Band Transverter Box - Dec 2024 M5Core2 Radio side - BT connected.jpg -------------------------------------------------------------------------------- /Pictures/M5AtomS3 rotated.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/M5AtomS3 rotated.jpg -------------------------------------------------------------------------------- /Pictures/XvtrBox OLED Voltage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K7MDL2/IC-705-BLE-Serial-Example/34bc5879eaf33b564ccd36efa852a2909bf9df87/Pictures/XvtrBox OLED Voltage.jpg --------------------------------------------------------------------------------