One of the interesting things to do when operating narrow band is to use the QRSS frequencies which normally transmit slow morse or DFCW (dual frequency CW), to instead transmit ASCII characters on a set of 8 bit mapped frequencies, this sends a bit mapped font character.
This results in a display at QRSS3 speeds as shown in Argo software:
I am using an SDR receiver (this one is the Elektor SDR) tuned to 7050kHz centre frequency, with the IQ outputs going to a Startech A/D and on to my iMac computer. I am running the HDSDR software (under Wine) tuned to 7038.7kHz USB, so giving an audio tone of 1500kHz displayed in Argo
The transmitter is an Arduino UNO programming an Si5351 synthesiser module. This includes an RTC and TX is made every 5 mins
And here's couple more photos using the SDR_40M "Concept" SDR and Mac native DSP Radio software, audio is sent from the Radio to Argo using Soundflower software (recently updated for MacOS 10 and much improved)
Updated message after I got my Full Licence...
The code below is for transmission of an embedded line "CQ M0IFA IO92HF" (replace this with your text, max 16 characters if you want it to display on the LCD screen). The font here is a normal right-way-up font.
Code - updated 5-2-17
// HELL_S/MT_5x7 Sequential MultiTone Hellschreiber // 5x7 font, normal // Si5351 correction for ARDUINO COURSE BB, may need adustment // Si5351 I2C bus // SDA = A4 // SCL = A5 // LCD I2C bus (16x2) // SDA = A4 // SCL = A5 // rotary encoder pins // DT = 2 // CLK = 3 // SW = 4 // Si5351, LCDI2C libraries #include "si5351.h" #include "LiquidCrystal_I2C.h" // LCD 0x27 or 0x3F //#define LCDADDR 0x3F #define LCDADDR 0x27 #define LCDCOLS 16 #define LCDROWS 2 // frequencies, base and shift (cHz) #define BASEFREQ 707000000 // 40m, freqs 7077, 10132, 14070kHz #define SHIFT 200 // 2Hz shift, 14Hz total BW //each pixel 300ms, chargap 5pix = 1500ms #define PIXTIME 300 #define CHARGAP 1500 // table of glyphs 0-9 & A-Z, cols b0-b7 byte glyphs[][6] = { {' ', 0x00, 0x00, 0x00, 0x00, 0x00, }, {'/', 0x04, 0x08, 0x10, 0x20, 0x40, }, {'0', 0x7C, 0x8A, 0x92, 0xA2, 0x7C, }, {'1', 0x00, 0x42, 0xFE, 0x02, 0x00, }, {'2', 0x42, 0x86, 0x8A, 0x92, 0x62, }, {'3', 0x84, 0x82, 0xA2, 0xD2, 0x8C, }, {'4', 0x18, 0x28, 0x48, 0xFE, 0x08, }, {'5', 0xE4, 0xA2, 0xA2, 0xA2, 0x9C, }, {'6', 0x3C, 0x52, 0x92, 0x92, 0x0C, }, {'7', 0x80, 0x8E, 0x90, 0xA0, 0xC0, }, {'8', 0x6C, 0x92, 0x92, 0x92, 0x6C, }, {'9', 0x60, 0x92, 0x92, 0x94, 0x78, }, {'A', 0x7E, 0x88, 0x88, 0x88, 0x7E, }, {'B', 0xFE, 0x92, 0x92, 0x92, 0x6C, }, {'C', 0x7C, 0x82, 0x82, 0x82, 0x44, }, {'D', 0xFE, 0x82, 0x82, 0x44, 0x38, }, {'E', 0xFE, 0x92, 0x92, 0x92, 0x82, }, {'F', 0xFE, 0x90, 0x90, 0x90, 0x80, }, {'G', 0x7C, 0x82, 0x92, 0x92, 0x5E, }, {'H', 0xFE, 0x10, 0x10, 0x10, 0xFE, }, {'I', 0x00, 0x82, 0xFE, 0x82, 0x00, }, {'J', 0x04, 0x02, 0x82, 0xFC, 0x80, }, {'K', 0xFE, 0x10, 0x28, 0x44, 0x82, }, {'L', 0xFE, 0x02, 0x02, 0x02, 0x02, }, {'M', 0xFE, 0x40, 0x30, 0x40, 0xFE, }, {'N', 0xFE, 0x20, 0x10, 0x08, 0xFE, }, {'O', 0x7C, 0x82, 0x82, 0x82, 0x7C, }, {'P', 0xFE, 0x90, 0x90, 0x90, 0x60, }, {'Q', 0x7C, 0x82, 0x8A, 0x84, 0x7A, }, {'R', 0xFE, 0x90, 0x98, 0x94, 0x62, }, {'S', 0x62, 0x92, 0x92, 0x92, 0x8C, }, {'T', 0x80, 0x80, 0xFE, 0x80, 0x80, }, {'U', 0xFC, 0x02, 0x02, 0x02, 0xFC, }, {'V', 0xF8, 0x04, 0x02, 0x04, 0xF8, }, {'W', 0xFC, 0x02, 0x1C, 0x02, 0xFC, }, {'X', 0xC6, 0x28, 0x10, 0x28, 0xC6, }, {'Y', 0xE0, 0x10, 0x0E, 0x10, 0xE0, }, {'Z', 0x86, 0x8A, 0x92, 0xA2, 0xC2, }, }; // calc number of glyphs in glyphs table #define NGLYPHS ((sizeof glyphs) / (sizeof glyphs[0])) // freq variable uint64_t freq = BASEFREQ; // base or bottom freq of pixels // message to send char msg[] = "TESTING M0IFA"; // max 16 char for LCD display, can transmit longer // dds object Si5351 dds; // LCD object LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS); void setup() { // init lcd & I2C lcd.begin(); // init dds dds.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0); // set drive output 8mA (about 4dBm into 50R) dds.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // disable all outputs dds.output_enable(SI5351_CLK0, 0); dds.output_enable(SI5351_CLK1, 0); dds.output_enable(SI5351_CLK2, 0); // initial display dispMsg(0, 0, " HELLSCHREIBER "); // title & clear line Serial.println("START 1 sec"); delay(1000); } void loop() { dispMsg(0, 0, " "); // clear title dispMsg(0, 0, msg); // disp msg dispFreq(1, 1, freq, 1); // display freq dispMsg(11, 1, " USB "); sendMsg(msg); dispMsg(11, 1, " "); dispMsg(0, 0, " HELLSCHREIBER "); // title & clear line dispMsg(0, 1, " "); delay(30000); // next 30sec delay } // take glyphs of message and send void sendMsg(char *m) { int c, i, j; // c scans msg, i & j scan the glyphs & rows int pix; // pix scans pixel cols in glyph c = 0; while (m[c] != '\0') { // scan until end of msg for (i = 0; i < NGLYPHS; i++) { // scan glyphs, always scan all rows to preserve timing if (m[c] == glyphs[i][0]) { // if m[c] found at [i][0] for (j = 1; j <= 5; j++) { // read glyphs[j][1] to [j][5] for (pix = 1; pix <= 7; pix++) { // font cols b1-b7 for USB if (bitRead(glyphs[i][j], pix) == 1) { // send pix outFreq(freq + (pix * SHIFT), PIXTIME); // calc output freq } else { delay(PIXTIME); } } } delay(CHARGAP); } } c++; } } // output f for t ms void outFreq(uint64_t f, uint16_t t) { dds.set_freq(f, SI5351_CLK0); // output freq dds.output_enable(SI5351_CLK0, 1); delay(t); dds.output_enable(SI5351_CLK0, 0); } // display freq in kHz,col c, row r, d decimal places void dispFreq(uint8_t c, uint8_t r, uint64_t f, uint8_t d) { lcd.setCursor(c, r); // clear last freq display lcd.print((float)f / 100000, d); // convert to float for print function lcd.print("kHz "); // + trailing spaces to clear previous display } // display a number at col c, row r void dispNum(uint8_t c, uint8_t r, uint16_t n) { lcd.setCursor(c, r); lcd.print(n); } // display char msg at col c, row r void dispMsg(uint8_t c, uint8_t r, char *m) { lcd.setCursor(c, r); lcd.print(m); }
No comments:
Post a Comment