[Radio] Baudot

Deze code in C++ laat je radiosignalen uitzenden in baudot (rtty), ik heb dit gebruikt voor mijn ballon-project met een arduino controller.
De gewoonlijke ASCII code is in 8 bit; dat betekent 8 ‘beeps’ en 2^8=256 mogelijke karakters. Baudot is 5 bit, en heeft dus maar 2^5=32 mogelijke karakters, máar is dus wel bijna twee maal zo efficient. In feite heeft baudot eigenlijk 62 mogelijkheden in plaats van 32, maar dan moet je je er even in verdiepen (niet essentieel voor het gebruik van deze code). Hij kan nemlijk switchen tussen ‘nummermodus’ en ‘alfabetmodus’ waardooor hij alle nodige leestekens, nummers en het alfabet alsnog kan uitzenden.

Lees meer over Baudothier.

Onderdelen lijst

  • Radiozender
  • Radioontvanger aangesloten op Computer
  • FLDIGI.exe
  • Arduino of equivalent

C++/Arduino Code:

  1. // --- editted for Project Hollands Hoogte ---
  2. // RTTY code
  3. // Transmit a string in baudot
  4.  
  5.  
  6. #include <stdint.h>
  7.  
  8. #define ARRAY_LEN 32
  9. #define LETTERS_SHIFT 31
  10. #define FIGURES_SHIFT 27
  11. #define LINEFEED 2
  12. #define CARRRTN  8
  13.  
  14. #define is_lowercase(ch)    ((ch) >= 'a' && (ch) <= 'z')
  15. #define is_uppercase(ch)    ((ch) >= 'A' && (ch) <= 'Z')
  16.  
  17. unsigned long time;
  18.  
  19. char letters_arr[33] = "00EnA SIUrDRJNFCKTZLWHYPQOBG00MXV00";
  20. char figures_arr[33] = "003n- a87r$4',!:(5")2#6019?&00./;00";
  21.  
  22. void setup(){
  23.   Serial.begin(9600);
  24.   pinMode(2, OUTPUT);
  25.   pinMode(3, OUTPUT);
  26. }
  27.  
  28. void loop(){
  29.  
  30.  time=millis();
  31.  //Now follow the info that starts with $$ and ends with rn
  32.  rtty_txstring("$$TBL,167,12:13:14,52.7933,5.1163,14378#3Arn");
  33.  time=millis()-time;
  34.  Serial.println(time);
  35.  delay(200);
  36. }
  37.  
  38.  
  39.  
  40.  
  41. uint8_t char_to_baudot(char c, char *array)
  42. {
  43.   int i;
  44.   for (i = 0; i < ARRAY_LEN; i++)
  45.   {
  46.     if (array[i] == c)
  47.       return i;
  48.   }
  49.  
  50.   return 0;
  51. }
  52.  
  53. void rtty_txbyte(uint8_t b)
  54. {
  55.   int8_t i;
  56.  
  57.   rtty_txbit(0);
  58.  
  59.   /* TODO: I don't know if baudot is MSB first or LSB first */
  60.   /* for (i = 4; i >= 0; i--) */
  61.   for (i = 0; i < 5; i++)
  62.   {
  63.     if (b & (1 << i))
  64.       rtty_txbit(1);
  65.     else
  66.       rtty_txbit(0);
  67.   }
  68.  
  69.   rtty_txbit(1);
  70. }
  71.  
  72. enum baudot_mode
  73. {
  74.   NONE,
  75.   LETTERS,
  76.   FIGURES
  77. };
  78.  
  79. void rtty_txstring(char *str)
  80. {
  81.   enum baudot_mode current_mode = NONE;
  82.   char c;
  83.   uint8_t b;
  84.  
  85.   while (*str != '')
  86.   {
  87.     c = *str;
  88.     /* some characters are available in both sets */
  89.     if (c == 'n')
  90.     {
  91.       rtty_txbyte(LINEFEED);
  92.     }
  93.     else if (c == 'r')
  94.     {
  95.       rtty_txbyte(CARRRTN);
  96.     }
  97.     else if (is_lowercase(*str) || is_uppercase(*str))
  98.     {
  99.       if (is_lowercase(*str))
  100.       {
  101.         c -= 32;
  102.       }
  103.  
  104.       if (current_mode != LETTERS)
  105.       {
  106.         rtty_txbyte(LETTERS_SHIFT);
  107.         current_mode = LETTERS;
  108.       }
  109.  
  110.       rtty_txbyte(char_to_baudot(c, letters_arr));
  111.     }
  112.     else
  113.     {
  114.       b = char_to_baudot(c, figures_arr);
  115.  
  116.       if (b != 0 && current_mode != FIGURES)
  117.       {
  118.         rtty_txbyte(FIGURES_SHIFT);
  119.         current_mode = FIGURES;
  120.       }
  121.  
  122.       rtty_txbyte(b);
  123.     }
  124.  
  125.     str++;
  126.   }
  127. }
  128.  
  129.  
  130.  
  131. // Transmit a bit as a mark or space
  132. void rtty_txbit (int bit) {
  133.   if (bit) {
  134.     // High - mark
  135.     digitalWrite(2, HIGH);
  136.     digitalWrite(3, LOW);
  137.   }
  138.   else {
  139.     // Low - space
  140.     digitalWrite(3, HIGH);
  141.     digitalWrite(2, LOW);
  142.   }
  143.   // Delay appropriately - tuned to 50 baud.
  144.   delay(20);
  145.   //delayMicroseconds(250);
  146. }

This code in C++ lets you emit radio signals in baudot, i have used this for my Arduino balloon-project.
The common ASCII code is in 8 bits, which means 8 beeps and 2^8 possible characters. Baudot though is in 5bit, and has only 2^5=32 possible combinations. 5 bits per byte is very little, which is great for radio performance. Though 32 is too little to fit in the alphabet and all the numbers (which we primarilly need), so it uses a bitcombination within that 32 that switches between numbers and the alphabet.

Read more about Baudot here.

Parts list

  • Radiotransmitter
  • Radioreceiver
  • FLDIGI.exe
  • Arduino or equivalent

C++/Arduino Code:

  1. // --- editted for Project Hollands Hoogte ---
  2. // RTTY code
  3. // Transmit a string in baudot
  4.  
  5.  
  6. #include <stdint.h>
  7.  
  8. #define ARRAY_LEN 32
  9. #define LETTERS_SHIFT 31
  10. #define FIGURES_SHIFT 27
  11. #define LINEFEED 2
  12. #define CARRRTN  8
  13.  
  14. #define is_lowercase(ch)    ((ch) >= 'a' && (ch) <= 'z')
  15. #define is_uppercase(ch)    ((ch) >= 'A' && (ch) <= 'Z')
  16.  
  17. unsigned long time;
  18.  
  19. char letters_arr[33] = "00EnA SIUrDRJNFCKTZLWHYPQOBG00MXV00";
  20. char figures_arr[33] = "003n- a87r$4',!:(5")2#6019?&00./;00";
  21.  
  22. void setup(){
  23.   Serial.begin(9600);
  24.   pinMode(2, OUTPUT);
  25.   pinMode(3, OUTPUT);
  26. }
  27.  
  28. void loop(){
  29.  
  30.  time=millis();
  31.  //Now follow the info that starts with $$ and ends with rn
  32.  rtty_txstring("$$TBL,167,12:13:14,52.7933,5.1163,14378#3Arn");
  33.  time=millis()-time;
  34.  Serial.println(time);
  35.  delay(200);
  36. }
  37.  
  38.  
  39.  
  40.  
  41. uint8_t char_to_baudot(char c, char *array)
  42. {
  43.   int i;
  44.   for (i = 0; i < ARRAY_LEN; i++)
  45.   {
  46.     if (array[i] == c)
  47.       return i;
  48.   }
  49.  
  50.   return 0;
  51. }
  52.  
  53. void rtty_txbyte(uint8_t b)
  54. {
  55.   int8_t i;
  56.  
  57.   rtty_txbit(0);
  58.  
  59.   /* TODO: I don't know if baudot is MSB first or LSB first */
  60.   /* for (i = 4; i >= 0; i--) */
  61.   for (i = 0; i < 5; i++)
  62.   {
  63.     if (b & (1 << i))
  64.       rtty_txbit(1);
  65.     else
  66.       rtty_txbit(0);
  67.   }
  68.  
  69.   rtty_txbit(1);
  70. }
  71.  
  72. enum baudot_mode
  73. {
  74.   NONE,
  75.   LETTERS,
  76.   FIGURES
  77. };
  78.  
  79. void rtty_txstring(char *str)
  80. {
  81.   enum baudot_mode current_mode = NONE;
  82.   char c;
  83.   uint8_t b;
  84.  
  85.   while (*str != '')
  86.   {
  87.     c = *str;
  88.     /* some characters are available in both sets */
  89.     if (c == 'n')
  90.     {
  91.       rtty_txbyte(LINEFEED);
  92.     }
  93.     else if (c == 'r')
  94.     {
  95.       rtty_txbyte(CARRRTN);
  96.     }
  97.     else if (is_lowercase(*str) || is_uppercase(*str))
  98.     {
  99.       if (is_lowercase(*str))
  100.       {
  101.         c -= 32;
  102.       }
  103.  
  104.       if (current_mode != LETTERS)
  105.       {
  106.         rtty_txbyte(LETTERS_SHIFT);
  107.         current_mode = LETTERS;
  108.       }
  109.  
  110.       rtty_txbyte(char_to_baudot(c, letters_arr));
  111.     }
  112.     else
  113.     {
  114.       b = char_to_baudot(c, figures_arr);
  115.  
  116.       if (b != 0 && current_mode != FIGURES)
  117.       {
  118.         rtty_txbyte(FIGURES_SHIFT);
  119.         current_mode = FIGURES;
  120.       }
  121.  
  122.       rtty_txbyte(b);
  123.     }
  124.  
  125.     str++;
  126.   }
  127. }
  128.  
  129.  
  130.  
  131. // Transmit a bit as a mark or space
  132. void rtty_txbit (int bit) {
  133.   if (bit) {
  134.     // High - mark
  135.     digitalWrite(2, HIGH);
  136.     digitalWrite(3, LOW);
  137.   }
  138.   else {
  139.     // Low - space
  140.     digitalWrite(3, HIGH);
  141.     digitalWrite(2, LOW);
  142.   }
  143.   // Delay appropriately - tuned to 50 baud.
  144.   delay(20);
  145.   //delayMicroseconds(250);
  146. }

Tim Zaman

MSc Biorobotics. Specialization in computer vision and deep learning. Works at NVIDIA.

You may also like...

2 Responses

  1. Ale says:

    Looks like there’s a problem with the strings, backslashes for escapes are missing. Trying to get them correct here:

    char letters_arr[33] = “\0E\nA SIU\rDRJNFCKTZLWHYPQOBG\0MXV\0”;
    char figures_arr[33] = “\03\n- \a87\r$4′,!:(5\”)2#6019?&\0./;\0″;

  1. April 13, 2011

    […] The code below is tuned to 50baud (transfer speed of 50 bit/s). You undertand: this is a very slow communication, about 7 characters per second. Also, it uses 7bit ascii, you can also set it to 8 bit asci (bit slower but more characters). Also i have the code for baudot (5bit) which is really fast, but with some restrictions. You can find that code here. […]