Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: CC1200 SerialStream
Revision 0:9e9ede3ac523, committed 2020-08-29
- Comitter:
- Jamie Smith
- Date:
- Sat Aug 29 03:06:11 2020 -0700
- Commit message:
- Initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Aug 29 03:06:11 2020 -0700 @@ -0,0 +1,5 @@ +^BUILD$ +^.mbed$ +^mbed-os$ +^CC1200$ +^SerialStream$
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CC1200.lib Sat Aug 29 03:06:11 2020 -0700 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MultipleMonomials/code/CC1200/#c609cc7c9ea7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CC1200Morse.cpp Sat Aug 29 03:06:11 2020 -0700
@@ -0,0 +1,177 @@
+//
+// Created by jamie on 8/24/2020.
+//
+
+#include "CC1200Morse.h"
+
+#include <cinttypes>
+
+// Morse code tables.
+// Covers ASCII ranges 0x41-0x5A and 0x61-0x7A
+char const * const alphaMorse[] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---",
+ "-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-",
+ "...-",".--","-..-","-.--","--.."};
+
+// Covers ASCII range 0x30-0x39
+char const * const numMorse[] = {"-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
+
+// covers ASCII range 0x21-0x2F
+char const * const punctuation1Morse[] = {"-.-.--", ".-..-.", nullptr, "...-..-", nullptr, ".-...", ".----.", "-.--.",
+ "-.--.-", nullptr, ".-.-.", "--..--", nullptr, ".-.-.-", "-..-."};
+
+// covers ASCII range 0x3A-0x40
+char const * const punctuation2Morse[] = {"---...", "-.-.-.", nullptr, "-...-", nullptr, "..--..", ".--.-."};
+
+void CC1200Morse::configure(CC1200::Band band, float radioFrequency, float morseTimePeriod, float transmitPower)
+{
+ radio.setPacketMode(CC1200::PacketMode::FIXED_LENGTH);
+ radio.setCRCEnabled(false);
+
+ // set frequency
+ radio.setSymbolRate(1/morseTimePeriod);
+ radio.setRadioFrequency(band, radioFrequency);
+
+ // disable anything getting sent before the data
+ radio.configureSyncWord(0x0, CC1200::SyncMode::SYNC_NONE, 8);
+ radio.configurePreamble(0, 0);
+
+ // configure OOK modulation
+ radio.setModulationFormat(CC1200::ModFormat::ASK);
+ radio.disablePARamping();
+ radio.setASKPowers(transmitPower, CC1200::ASK_MIN_POWER_OFF);
+}
+
+// helper function for convertToMorse
+static bool appendBits(uint8_t *outputBuffer, size_t bufferLen, uint8_t & nextBit, size_t & currByte, uint8_t toAppend, size_t count)
+{
+ //printf("appendBits(%" PRIu8 ", %zu)\n", toAppend, count);
+ for(size_t counter = 0; counter < count; ++counter)
+ {
+ outputBuffer[currByte] |= toAppend << nextBit;
+
+ if(nextBit == 0)
+ {
+ nextBit = 7;
+ currByte += 1;
+ if(currByte >= bufferLen)
+ {
+ // out of space
+ return false;
+ }
+ }
+ else
+ {
+ nextBit--;
+ }
+ }
+
+ return true;
+}
+
+
+CC1200Morse::EncodedMorse CC1200Morse::convertToMorse(const char *string, uint8_t *outputBuffer, size_t bufferLen)
+{
+ memset(outputBuffer, 0, bufferLen);
+
+ // place in the output buffer where next items will be written
+ uint8_t nextBit = 7;
+ size_t currByte = 0;
+
+ EncodedMorse encoded;
+ encoded.buffer = outputBuffer;
+ encoded.valid = false;
+
+ if(!appendBits(outputBuffer, bufferLen, nextBit, currByte, 0, spaceBefore))
+ {
+ return encoded;
+ }
+
+ size_t stringLength = strlen(string);
+ for(size_t charIndex = 0; charIndex < stringLength; ++charIndex)
+ {
+ char currChar = string[charIndex];
+ char const * morseToAppend = nullptr;
+ if((currChar >= 'A' && currChar <= 'Z'))
+ {
+ morseToAppend = alphaMorse[currChar - 'A'];
+ }
+ else if(currChar >= 'a' && currChar <= 'z')
+ {
+ morseToAppend = alphaMorse[currChar - 'a'];
+ }
+ else if(currChar >= '0' && currChar <= '9')
+ {
+ morseToAppend = numMorse[currChar - '0'];
+ }
+ else if(currChar >= '!' && currChar <= '/')
+ {
+ morseToAppend = punctuation1Morse[currChar - '!'];
+ }
+ else if(currChar >= ':' && currChar <= '@')
+ {
+ morseToAppend = punctuation2Morse[currChar - ':'];
+ }
+ else if(currChar == '_') // underscore is off by itself in the ASCII chart
+ {
+ morseToAppend = "..--.-";
+ }
+
+ // append bit timings
+ //printf("currChar = '%c'\n", currChar);
+ if(currChar == ' ')
+ {
+ // space between words is 7 time units
+ if(!appendBits(outputBuffer, bufferLen, nextBit, currByte, 0, 7))
+ {
+ return encoded;
+ }
+ }
+ else if(morseToAppend != nullptr)
+ {
+ size_t morseLength = strlen(morseToAppend);
+ for(size_t morseIndex = 0; morseIndex < morseLength; ++morseIndex)
+ {
+ // dot is 1 time unit, dash is 3 time units
+ if(!appendBits(outputBuffer, bufferLen, nextBit, currByte, 1, morseToAppend[morseIndex] == '-' ? 3 : 1))
+ {
+ return encoded;
+ }
+
+ // space between symbols is 1 time unit
+ if(!appendBits(outputBuffer, bufferLen, nextBit, currByte, 0, 1))
+ {
+ return encoded;
+ }
+ }
+
+ // extra space between letters is 2 time units
+ if(!appendBits(outputBuffer, bufferLen, nextBit, currByte, 0, 2))
+ {
+ return encoded;
+ }
+ }
+ }
+
+ if(!appendBits(outputBuffer, bufferLen, nextBit, currByte, 0, spaceAfter))
+ {
+ return encoded;
+ }
+
+ encoded.valid = true;
+ encoded.byteLen = currByte;
+ encoded.bitLen = 7 - nextBit;
+ encoded.totalLength = currByte + (encoded.bitLen > 0 ? 1 : 0);
+
+ return encoded;
+}
+
+void CC1200Morse::transmit(const CC1200Morse::EncodedMorse &morse)
+{
+ if(morse.totalLength > 128)
+ {
+ // too large to send in one packet
+ return;
+ }
+ radio.setPacketLength(morse.byteLen, morse.bitLen);
+ radio.enqueuePacket(reinterpret_cast<const char *>(morse.buffer), morse.totalLength);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CC1200Morse.h Sat Aug 29 03:06:11 2020 -0700
@@ -0,0 +1,75 @@
+//
+// Class allowing you to transmit Morse code using the CC1200 radio
+//
+
+#ifndef LIGHTSPEEDRANGEFINDER_CC1200MORSE_H
+#define LIGHTSPEEDRANGEFINDER_CC1200MORSE_H
+
+#include <CC1200.h>
+
+class CC1200Morse
+{
+ CC1200 & radio;
+
+ // time units at the start and end of the morse message.
+ const size_t spaceBefore = 3;
+ const size_t spaceAfter = 3;
+
+public:
+
+ CC1200Morse(CC1200 & _radio):
+ radio(_radio){}
+
+ /**
+ * Configure the CC1200 to transmit morse code.
+ *
+ * @param band Radio band containing the frequency.
+ * @param radioFrequency Frequency to transmit on.
+ * @param morseTimePeriod Time unit in seconds to use when transmitting.
+ * @param transmitPower Power in dBm to transmit at. Must be in the CC1200 allowed range.
+ * Dots are one time unit, dashes are three.
+ * 50ms is about the fastest a human can understand, while 125ms is a more reasonable speed.
+ * Specifics are here: http://www.codebug.org.uk/learn/step/541/morse-code-timing-rules/#:~:text=The%20space%20between%20symbols%20(dots,words%20is%207%20time%20units.
+ */
+ void configure(CC1200::Band band, float radioFrequency, float morseTimePeriod, float transmitPower);
+
+ struct EncodedMorse
+ {
+ /// Whether this morse data is valid.. If false, it couldn't be encoded due to an error.
+ bool valid;
+
+ /// Buffer storing morse data. Uses memory passed to configure()
+ uint8_t const * buffer;
+
+ /// Number of complete bytes and bits used in the data
+ size_t byteLen;
+ uint8_t bitLen;
+
+ // Number of bytes in the buffer that are at least partially filled.
+ size_t totalLength;
+ };
+
+ /**
+ * Convert ASCII text into characters suitable to be sent over the radio.
+ * Some ASCII characters do not have a morse equivalent, these will be removed.
+ *
+ * @param string ASCII string to convert.
+ * @param outputBuffer Buffer to write morse into. Will be zeroed.
+ * @return Encoded morse data, if there was insufficient space valid will be false.
+ */
+ EncodedMorse convertToMorse(const char* string, uint8_t * outputBuffer, size_t bufferLen);
+
+ /**
+ * Queue this morse code to be transmitted over the radio.
+ * Packets with a total length larger than 128 bytes cannot be transmitted (though this limit
+ * could be worked around).
+ *
+ * The packet will be transmitted as soon as the radio is switched to TX state.
+ * If it's already in TX then it will be transmitted immediately.
+ * @param morse
+ */
+ void transmit(EncodedMorse const & morse);
+};
+
+
+#endif //LIGHTSPEEDRANGEFINDER_CC1200MORSE_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialStream.lib Sat Aug 29 03:06:11 2020 -0700 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MultipleMonomials/code/SerialStream/#9437ea7d0799b269bfaa18d584dec7e17287a623 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Sat Aug 29 03:06:11 2020 -0700
@@ -0,0 +1,160 @@
+//
+// Test program for the CC1200 morse code example
+//
+
+#include <mbed.h>
+#include <SerialStream.h>
+
+#include <CC1200.h>
+#include <cinttypes>
+
+#include "CC1200Morse.h"
+
+#define PIN_SPI_MOSI P0_9
+#define PIN_SPI_MISO P0_8
+#define PIN_SPI_SCLK P0_7
+
+#define PIN_CC1200_CS P0_6
+#define PIN_CC1200_RST P0_29
+
+BufferedSerial serial(USBTX, USBRX, 115200);
+SerialStream<BufferedSerial> pc(serial);
+
+CC1200 radio(PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCLK, PIN_CC1200_CS, PIN_CC1200_RST, &pc);
+
+void testMorseCodeConversion()
+{
+ radio.begin();
+ CC1200Morse morseConverter(radio);
+
+ const size_t bufferLen = 64;
+ uint8_t outputBuffer[bufferLen];
+
+ char const * testString = "eternal silence@54!";
+
+ CC1200Morse::EncodedMorse morse = morseConverter.convertToMorse(testString, outputBuffer, bufferLen);
+
+ if(!morse.valid)
+ {
+ pc.printf("Morse is invalid\n");
+ }
+ else
+ {
+ pc.printf("Output %zu bytes:", morse.totalLength);
+ for(size_t index = 0; index < morse.totalLength; ++index)
+ {
+ pc.printf(" %" PRIx8, outputBuffer[index]);
+ }
+ pc.printf("\n");
+ }
+}
+
+/**
+ * Test sending some arbitrary bytes as OOK modulated data.
+ */
+void testMorseByteTransmission()
+{
+ const float timeUnit = 0.1f;
+
+ radio.begin();
+ CC1200Morse morseConverter(radio);
+ morseConverter.configure(CC1200::Band::BAND_820_960MHz, 915e6f, timeUnit, 14.5);
+
+ const char testString[] = "\xFF\x0E\xFF";
+ const size_t testStringLength = 3;
+
+ // manually create morse code data
+ CC1200Morse::EncodedMorse morse;
+ morse.valid = true;
+ morse.buffer = reinterpret_cast<uint8_t const *>(testString);
+ morse.byteLen = testStringLength;
+ morse.bitLen = 0;
+ morse.totalLength = testStringLength;
+
+ morseConverter.transmit(morse);
+
+ Timer messageTimer;
+ messageTimer.start();
+
+ radio.setOnTransmitState(CC1200::State::IDLE);
+ radio.startTX();
+
+ // wait until all bytes have been transmitted.
+ // Note: the FIFO length is 0 when the last byte is being sent, so we can't just check the FIFO length
+ while(radio.getTXFIFOLen() > 0 || radio.getState() != CC1200::State::IDLE)
+ {
+ pc.printf("TX FIFO size: %zu\n", radio.getTXFIFOLen());
+ ThisThread::sleep_for(std::chrono::milliseconds(static_cast<uint32_t>(timeUnit * 1000)));
+ //ThisThread::sleep_for(1ms);
+ }
+
+ float timeSeconds = std::chrono::duration_cast<std::chrono::duration<float>>(messageTimer.elapsed_time()).count();
+ size_t numBits = ((morse.byteLen * 8) + morse.bitLen);
+ float effectiveBitrate = numBits / timeSeconds;
+
+ pc.printf("Sent %zu bits in %.03f s, effective bitrate = %.03f sps\n", numBits, timeSeconds, effectiveBitrate);
+
+}
+
+void testMorseCodeTransmission()
+{
+ const float timeUnit = 0.1f;
+
+ radio.begin();
+ CC1200Morse morseConverter(radio);
+ morseConverter.configure(CC1200::Band::BAND_820_960MHz, 915e6f, timeUnit, 0);
+
+ const size_t bufferLen = 64;
+ uint8_t outputBuffer[bufferLen];
+
+ char const * testString = "eternal silence@54!";
+
+ CC1200Morse::EncodedMorse morse = morseConverter.convertToMorse(testString, outputBuffer, bufferLen);
+
+ if(!morse.valid)
+ {
+ pc.printf("Morse is invalid\n");
+ }
+
+ morseConverter.transmit(morse);
+
+ radio.setOnTransmitState(CC1200::State::IDLE);
+ radio.startTX();
+
+ // wait until all bytes have been transmitted.
+ // Note: the FIFO length is 0 when the last byte is being sent, so we can't just check the FIFO length
+ while(radio.getTXFIFOLen() > 0 || radio.getState() != CC1200::State::IDLE)
+ {
+ pc.printf("TX FIFO size: %zu\n", radio.getTXFIFOLen());
+ ThisThread::sleep_for(std::chrono::milliseconds(static_cast<uint32_t>(timeUnit * 1000)));
+ //ThisThread::sleep_for(1ms);
+ }
+}
+
+int main()
+{
+ pc.printf("\nCC1200 Morse Test Suite:\n");
+
+ while(1){
+ int test=-1;
+ //MENU. ADD AN OPTION FOR EACH TEST.
+ pc.printf("Select a test: \n");
+ pc.printf("1. Test converting to Morse code\n");
+ pc.printf("2. Test transmitting bytes as Morse\n");
+ pc.printf("3. Test transmitting string of Morse\n");
+
+ pc.scanf("%d", &test);
+ printf("Running test %d:\n\n", test);
+ //SWITCH. ADD A CASE FOR EACH TEST.
+ switch(test) {
+ case 1: testMorseCodeConversion(); break;
+ case 2: testMorseByteTransmission(); break;
+ case 3: testMorseCodeTransmission(); break;
+ default: pc.printf("Invalid test number. Please run again.\n"); continue;
+ }
+ pc.printf("done.\r\n");
+ }
+
+ return 0;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Sat Aug 29 03:06:11 2020 -0700 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os.git#a2ada74770f043aff3e61e29d164a8e78274fcd4 \ No newline at end of file