This is a really simple question but I haven't been able to find the answer. What is the best way to initialize an array such as in the example below? I'm pretty sure doing it one element at a time (as I did) isn't it. Thanks very much!
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4();
typedef struct
{
char alpha;
String morse;
} record_type;
record_type record[47];
String searchKey;
void setup()
{
Serial.begin(9600);
alpha4.begin(0x70); // pass in the address
record[0].alpha = 'A';
record[1].alpha = 'B';
record[2].alpha = 'C';
record[3].alpha = 'D';
record[4].alpha = 'E';
record[5].alpha = 'F';
record[6].alpha = 'G';
record[7].alpha = 'H';
record[8].alpha = 'I';
record[9].alpha = 'J';
record[10].alpha = 'K';
record[11].alpha = 'L';
record[12].alpha = 'M';
record[13].alpha = 'N';
record[14].alpha = 'O';
record[15].alpha = 'P';
record[16].alpha = 'Q';
record[17].alpha = 'R';
record[18].alpha = 'S';
record[19].alpha = 'T';
record[20].alpha = 'U';
record[21].alpha = 'V';
record[22].alpha = 'W';
record[23].alpha = 'X';
record[24].alpha = 'Y';
record[25].alpha = 'Z';
record[26].alpha = '*';
record[27].alpha = '*';
record[28].alpha = '1';
record[29].alpha = '2';
record[30].alpha = '3';
record[31].alpha = '4';
record[32].alpha = '5';
record[33].alpha = '6';
record[34].alpha = '7';
record[35].alpha = '8';
record[36].alpha = '9';
record[37].alpha = '0';
record[38].alpha = '.';
record[39].alpha = ',';
record[40].alpha = '?';
record[41].alpha ='!';
record[42].alpha =':';
record[43].alpha =';';
record[44].alpha ='(';
record[45].alpha =')';
//record[46].alpha ='\';
record[47].alpha ='@';
record[48].alpha ='&';
record[0].morse = ".-";
record[1].morse = "-...";
record[2].morse = "-.-.";
record[3].morse = "-..";
record[4].morse = ".";
record[5].morse = "..-.";
record[6].morse = "--.";
record[7].morse = "....";
record[8].morse = "..";
record[9].morse = ".---";
record[10].morse = "-.-";
record[11].morse = ".-..";
record[12].morse = "--";
record[13].morse = "-.";
record[14].morse = "---";
record[15].morse = ".--.";
record[16].morse = "--.-";
record[17].morse = ".-.";
record[18].morse = "...";
record[19].morse = "-";
record[20].morse = "..-";
record[21].morse = "...-";
record[22].morse = ".--";
record[23].morse = "-..-";
record[24].morse = "-.--";
record[25].morse = "--..";
// backspace
record[26].morse = ".......";
// backspace
record[27].morse = "........";
record[28].morse = ".----";
record[29].morse = "..---";
record[30].morse = "...--";
record[31].morse = "....-";
record[32].morse = ".....";
record[33].morse = "-....";
record[34].morse = "--...";
record[35].morse = "---..";
record[36].morse = "----.";
record[37].morse = "-----";
record[38].morse = ".-.-.-";
record[39].morse = "--..--";
record[40].morse = "..--..";
record[41].morse = "-.-.--";
record[42].morse = "---...";
record[43].morse = "-.-.-.";
record[44].morse = "-.--.";
record[45].morse = "-.--.-";
record[46].morse = //".-..-.";
record[47].morse = ".--.-.";
record[48].morse = ".-...";
alpha4.clear();
alpha4.writeDisplay();
delay(500);
}
void loop()
{
//searchKey="";
searchKey = "-.-.";
Serial.print("searchKey:");
Serial.println(searchKey);
morseLookup();
}
void morseLookup() {
for (int i = 0; i < 49; i++) {
if (record[i].morse == searchKey){
Serial.print ("Alpha:");
Serial.println (record[i].alpha);
alpha4.writeDigitAscii(0, record[i].alpha);
alpha4.writeDisplay();
delay(100);
}
}
while(1) { }
}
Why do you initialize an array that stops at element 46 so that elements 47 and 48, outside of the array, get assigned?
One element at a time, that's all you can do.
You could put it in PROGMEM so it's not tie-ing up SRAM, and save start up time as the SRAM does not need to get loaded. Not sure you'd notice that time tho.
Does that compile okay? You've got that while(1) just hanging out there, not part of loop() and not part of morseLookup()
CrossRoads:
You could put it in PROGMEM so it's not tie-ing up SRAM, and save start up time as the SRAM does not need to get loaded. Not sure you'd notice that time tho.
That will be an interesting experience, given that the struct contains a String.
typedef struct
{
char alpha;
String morse;
} record_type;
You can initialize the array like this
record_type record[47] = {
{ 'A', ".-" },
{ 'B', "-..." },
};
Yeah, I wasn't thinking about the dots/dashes as actually being multiple characters.
Still, it can all be put in PROGMEM/const to save SRAM and speed up startup, yes?
I've never done that, my PROGMEM experience is limited to some const's occasionally.
Still, it can all be put in PROGMEM/const to save SRAM and speed up startup, yes?
Strings can't be put in PROGMEM. NULL terminated arrays of chars, aka strings, can.
There is no reason of OP to be pissing away resources on the String class, wrapping constant strings.
Thank you for your responses.
Whandal: Thanks, that is better than I was doing.
Vaj4088: Oops. Mistake. Thanks
CrossRoads: Thanks. The "Dangling while" was an experiment to see if it would cause the loop ton only run once. Yes, it did compile, and it worked.
PaulS: Thanks
Avoid using the String class.
An easier way to do this and put it all in progmem is to hold a fixed-size array in the struct. That is, rather than each item in the struct holding a pointer to string, each holds an array of char that is big enough for the longest string of morse plus a '\0' terminator.
typedef struct
{
const char alpha;
const char morse[10];
} record_type;
PROGMEM record_type morsetable[] = {
{ 'A', ".-" },
{ 'B', "-..." },
};
This wastes some space, but not all that much, and certainly not as much as using String. Remember that every string will be in progmem.
If you list the characters according to their ASCII value (alphabetically), then there's no need to store 'alpha', as it's just given by the offset in the array. Just remember to add/subtract the numeric value of 'A' (ie: 'A'
) to convert a letter to an array index.
So, get rid of the typedef and just use a two-dimensional progmem array:
// letters - 'A' is at index zero, 'Z' at 25
PROGMEM char morseLetter[][10] = {".-", "-...", /* etc */ };
Thanks Paul. You answered another question that I had, but forgot to ask: How to do this without the String class.
I did consider using the ascii values as an index into the array but was interested in learning a method that was more generally applicable (I'm an old fortran & BASIC programmer who is just learning c).
Thanks again to everyone.
JJ
I know this post is old, but i was looking for a solution to a problem I was having with something else entirely....
If you wanted to avoid using characters, simplify how you want to represent the mosre code in your code. in this case there are only 2 state which is perfect for binary operations.
i had a project in college using Z80 microprocess (oldie but goodie apparently) 8-bit and 256 bytes memory. my project was to make a morse code generator in assembly language.
Long story short, i used bits 1s and 0s to represent dashes and dots. Of the 8bit byte, i had the 5 msb represent the dashes and dots and the 3 lsb represent how many symbols there where (dots and dashes in this case) to play. so "B" would be represent as -... 01000100. [01000][100] = x-... and 4 symbols to read, msb was not read.
How i did this was byte shift. i would mask out the 3 lsb 9which was used in what would be a for loop) and shift the initial byte by three (0x01000100 >> 3) then had a loop that would read the 0 or 1, play a sound with the appropriate delay, shift right 1 and so on.
Massively more efficient on space and significantly faster (relatively). With only 8bits I could only represent A-Z and a few more characters, but if you use 16bit byte variables you can handle a lot more.
"...16bit byte variables..."
With most Arduinos, 16 bits is two bytes or an int.