From 2b7e2ae533886724ba4348857e0896a050e1e6e9 Mon Sep 17 00:00:00 2001 From: dewdude Date: Sat, 8 Feb 2020 11:58:42 -0500 Subject: [PATCH] Initial Commit. Hello. --- CHANGELOG | 5 ++ LICENSE | 18 +++++++ README.md | 112 +++++++++++++++++++++++++++++++++++++++++++ alpha/civtesting.ino | 82 +++++++++++++++++++++++++++++++ images/civdecode.png | Bin 0 -> 16713 bytes 5 files changed, 217 insertions(+) create mode 100644 CHANGELOG create mode 100644 LICENSE create mode 100644 README.md create mode 100644 alpha/civtesting.ino create mode 100644 images/civdecode.png diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..8c5331a --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,5 @@ +CHANGELOG: + +There have been no revisions to any code as of the initial commit. + +Stay tuned for development updates. \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..320caca --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +Copyright 2020 Jay Moore + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions +and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0a68a0f --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +ArFO - Arduino Frequency Oscillator + +A (mobile) remote head for your ham transceiver. + +# History + +``` +8-Feb-2020: Repository Creation, Intitial Commit, Alpha Versions + +```` + + +# About + +ArFO is an Arduino-based program that interfaces with an external display, external controls, and your ham rig; +to allow you the convenience of a remote head for rigs that do not feature one. It is written in Arduino and +commands your rig using it's CAT/CI-V connection. ArFO is a continuation/reboot of PiFO; a previous project +that sought to do the same thing. + +In addition to being able to control your operating mode, VFO, and a few other select options; ArFO also provides +"advanced logic" for an otherwise older rig. When possible, it uses it's own programming rather than rely on the +rig's internal functions. Planned features include a memory function, similar to what the proof-of-concept PiFO +was; that will allow you to expand on the memory preset functions of older rigs as well as the ability to carry +your memory presets with you between rigs. ArFO stores the frequency information and sends it to the radio as +a frequency for the VFO. + +ArFO will use it's own internal logic when necessary, meaning older rigs will get some new features. This means +some limitations (like CI-V WARC band data) are irrelevant to ArFO as we can calculate and process things +ourselves. + +# Why The Change To Arduino + +When I originally came up with the idea for PiFO; the Raspberry Pi seemed like the easest development solution. With +existing software in it's repositories the original idea was just a basic python script to interface with these. +However as I began developing it I found a lot of limitations in the existing solutions that did not perform the way +I thought they should, or wanted it to. + +The other problem with the RPi is the amount of time it takes to boot. Even with a basic installation of Rasbian; +20 seconds was how long it took to become active without getting in to the OS and really stripping things down. +When I created [HiFiLOGIX](https://gitlab.com/dewdude/hifilogix) I decided to go with the Arduino platform due to +almost negligable boot-up time; the goal was to have it booted and ready to go within the 4.5 seconds it took for +the stereo to activate it's speaker output relay. + +The (relative) success of getting HiFoLOGIX to work and armed with new knowledge of Arduino; I decided it should be +possible to build PiFO in a way that works entirely on a microcontroller. We don't need a full OS; and this means +no long boot times. + +# Hardware + +Though I have not gotten to the full design of a "reference" remote head; I am shooting for the following: + +* easy-to-read seven-segment LED displays with a minimal amount of information +* one (or more) rotary encoders for spinning the VFO/channels +* dedicated buttons for functions that don't require you to navigate a menu +* onboard level converters for your rig's communication protocol +* two cables to the head; power and communications + +Currently development is occuring on an Arduino Mega2560 and a simple 7404 based level converter for CI-V. This is +actually the same converter used in the RPi version. If the code allows; the final product may contain an ATMega328. +All hardware is planned to be integrated in to the head, meaning you should only need a power and communication +cable going to your radio. + +I will post full pictures and a schematic as I get further along in the development. + +Usage of onboard USB controllers in newer rigs will depend on how difficult it is to implement. Unlike the RPi; +the AVR based ATMegas do not feature native USB support and only offer serial communications. So plugging a rig's +USB in to the thing won't work. The chip that handles serial-to-USB on the board would have to be reprogrammed to +act as a USB host and understand all the various serial-to-USB adapters on the market. While USB controllers are +available as an external module; the goal of this project is to keep costs to a minimum. No one wants to spend +$300 on a remote head accessory! + +Additional display types may be supported depending on demand or user-submitted code. The project is open-source; you +are welcome to contribute code. + + + +# Current DEV Status + +Development offically started on 5-FEB-2020 with working out the physical interface betweent he rig and the radio. +This has been fully tested and I'm able to send and receieve bytes. + +The current phase of development is largely focusing on the communication library for CI-V. In it's current state, +the software is able to detect, receive, and filter CI-V data packets and able to process iCom's BCD data in to a +decimal format that can be worked with by the rest of the software. Currently this just displays the frequency to +the serial port on the Mega2560 connected to the USB adapter. The radio is currently using one of the remaining +hardware serial ports. + +![Current Development Version](/images/civdecode.png "CIV Decoding")*Current Development Version* + + +# License + +Copyright 2020 Jay Moore + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions +and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + + diff --git a/alpha/civtesting.ino b/alpha/civtesting.ino new file mode 100644 index 0000000..f73a6d4 --- /dev/null +++ b/alpha/civtesting.ino @@ -0,0 +1,82 @@ +/* ArFO Development Version + * + * This software doesn't control the radio yet. It is just to test working with the + * iCom CI-V data stream coming from the radio. + * + * de NQ4T - 08-FEB-2020 + */ + +const byte numBytes = 32; +byte receivedBytes[numBytes]; +byte numReceived = 0; +long vfoa; + +boolean newData = false; + +void setup() { + Serial.begin(9600); + Serial2.begin(9600); + Serial.println("CI-V Monitor Ready"); + Serial.println(); + +} + +void loop() { + recvBytesWithStartEndMarkers(); + showNewData(); + newData = false; +} + +void recvBytesWithStartEndMarkers() { + static boolean recvInProgress = false; + static byte ndx = 0; + byte startMarker = 0xFE; + byte endMarker = 0xFD; + byte rb; + + + while (Serial2.available() > 0 && newData == false) { + rb = Serial2.read(); + + if (recvInProgress == true) { + if (rb != endMarker) { + receivedBytes[ndx] = rb; + ndx++; + if (ndx >= numBytes) { + ndx = numBytes - 1; + } + } + else { + receivedBytes[ndx] = '\0'; // terminate the string + recvInProgress = false; + numReceived = ndx; // save the number for use when printing + ndx = 0; + newData = true; + } + } + + else if (rb == startMarker) { + recvInProgress = true; + } + } +} +void processciv() { + int i = 0; + long bcd[4]; + for (int x = numReceived; x > 2; x--) { + bcd[i] = (((receivedBytes[x] >> 4) *10) + (receivedBytes[x]&0xF)); + i++; + } + vfoa = ((bcd[0]*1000000)+(bcd[1]*10000)+(bcd[2]*100)+(bcd[3])); + } +void showNewData() { + if (newData == true) { + numReceived--; + processciv(); + Serial.println(); + Serial.print("VFO A: "); + Serial.print(vfoa, DEC); + Serial.print("kHz"); + } + newData = false; + } diff --git a/images/civdecode.png b/images/civdecode.png new file mode 100644 index 0000000000000000000000000000000000000000..bd442cfbc4d871db9f92546bfb9b6d0576756322 GIT binary patch literal 16713 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