// Mario's Ideas
// Morse Code transmiter
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Oled display size
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
//Potentiometer PIN A1
int Potentiometer=A1;
// Variables capturing current and newly calculated position on the letter board (Values 0-26)
int New_Position=0;
int Old_Position=0;
// Variable capturing Potentimeter read (Values 0 1023)
int Pot_read=0;
// Variable used for calculating moving average of potentiometer reading to stabilise the input
int Count_For_Moving_Average=0;
// String variable holding the text to transmit
String To_Transmit="";
// Length of the text to transmit
int To_Transmit_Length=0;
// Flag indicating the letter was entered on the leter board to be added to To_Transmit string
int Letter_Entered=0;
int Transmit=0;
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Array holding all Morse code letter dot dash combinations
char MorseCode[26][6] = {
{'.','-','x','x','x','A'},
{'-','.','.','.','x','B'},
{'-','.','-','.','x','C'},
{'-','.','.','x','x','D'},
{'.','x','x','x','x','E'},
{'.','.','-','.','x','F'},
{'-','-','.','x','x','G'},
{'.','.','.','.','x','H'},
{'.','.','x','x','x','I'},
{'.','-','-','-','x','J'},
{'-','.','-','x','x','K'},
{'.','-','.','.','x','L'},
{'-','-','x','x','x','M'},
{'-','.','x','x','x','N'},
{'-','-','-','x','x','O'},
{'.','-','-','.','x','P'},
{'-','-','.','-','x','Q'},
{'.','-','.','x','x','R'},
{'.','.','.','x','x','S'},
{'-','x','x','x','x','T'},
{'.','.','-','x','x','U'},
{'.','.','.','-','x','V'},
{'.','-','-','.','x','X'},
{'-','-','.','-','x','Y'},
{'.','-','.','x','x','Z'},
};
// Used for displaying Leter board
char Letters[28]="ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
// Play/Display Morse code representation of the letter
void Play_Letter (char Letter){
// searching in MorseCode array for the corresponding letter
if (Letter=='_') delay(350); else {
for (int j=0; j<27; j++){
if (MorseCode[j][5]==Letter)
// if the right letter is detected run Play_Dot_Dash for . or -
for (int k=0; k<4;k++){
if (MorseCode[j][k]!='x') Play_Dot_Dash(MorseCode[j][k]);
}
}
delay(200);
}
}
// Playing/Displaying . or -
void Play_Dot_Dash(char sign){
if (sign=='.'){
digitalWrite(5, 100);
digitalWrite(4, HIGH);
delay(100);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
delay(100);
}
if (sign=='-'){
digitalWrite(5, 100);
digitalWrite(4, HIGH);
delay(300);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
delay(100);
}
}
void Add_To_String(){
Letter_Entered=1;
}
void Triger_Transmit(){
Transmit=1;
}
void setup() {
Serial.begin(9600);
// Define two interrupts
// D2- when button pressed the current letter on the letter board is entered to To_Transmit
// D3- When button is pressed To_Transmit string is output in Morse code
attachInterrupt(0,Add_To_String, FALLING);
attachInterrupt(1,Triger_Transmit, FALLING);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Buzzer PIN
pinMode(5, OUTPUT);
digitalWrite(5, LOW);
// LED PIN
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
display.display();
// Display Letter Board 3 rows 9 character in each row
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
for (int j=0; j<3;j++){
for (int i=0; i<9;i++){
display.setCursor(i*12+2*i+1,j*16+17);
display.println(Letters[i+j*9]);
//display.fillRect(i*12+2*i, j*16 +16, 12, 16, SSD1306_INVERSE);
display.display();
}
}
// Display filled in rect in the top section of the display when To_Transfer would be output
display.fillRect(0, 0, 128, 15, SSD1306_INVERSE);
// Highlight character A by displaying Inverse rect at first position
display.fillRect(0, 16, 12, 16, SSD1306_INVERSE);
display.display();
}
void Highlight_letter(int New_Pos, int Old_Pos){
// When position changes from Old_Pos to New_Pos
// Draw the inverse rect in the Old_pos to deactivate the highlight in the old spot
// Draw the inverse rect to Highlite the new spot
int X_pos;
int Y_pos;
// Calculate X and Y coordinates of the New_Pos on the letter board
X_pos=New_Pos - ((int)New_Pos/9)*9;
Y_pos=(int)New_Pos/9;
// Displaying Inverse rect
display.fillRect(X_pos*12+2*X_pos, Y_pos*16 +16, 12, 16, SSD1306_INVERSE);
// Calculate X and Y coordinates of the Old_Pos on the letter board
X_pos=Old_Pos - ((int)Old_Pos/9)*9;
Y_pos=(int)Old_Pos/9;
// Displaying Inverse rect
display.fillRect(X_pos*12+2*X_pos, Y_pos*16 +16, 12, 16, SSD1306_INVERSE);
display.display();
}
void loop()
{
// Increase Count_For_Moving_Average 30 times before calcluating moving average
Count_For_Moving_Average++;
Pot_read =Pot_read + analogRead(Potentiometer);
if (Count_For_Moving_Average==30){
// Calculate moving average for 30 potentiometer reads
// Without calculating moving average reads are to volatile
Pot_read=(int)Pot_read/30;
// As potentiometer read was not stable around 0 and 1023 values
// Here is the code to fix it and make sure that values 0 and 26 are properly mapped
// Between values 101 and 899 the potentiometer read is mapped to the range 0,26
// New_Position is the new position calculated on the letter board corresponding to
//potentiometer read
if (Pot_read<100 or Pot_read==100) New_Position=0;
if (Pot_read >100 or Pot_read<900) New_Position= map(Pot_read,101,899,0,26);
if (Pot_read>900 or Pot_read==900) New_Position=26;
// If new position differes fro the previous one
// remove highlight from the old one and Highlight a new one
// New position becomes also the current position now
if (Old_Position!=New_Position){
Highlight_letter (New_Position,Old_Position);
Old_Position=New_Position;
}
// reset Count_For_Moving_Average and Pot_read to start calculating the new moving average
Count_For_Moving_Average=0;
Pot_read=0;
}
delay(5);
// Wait 100 loop cycles before checking if the new letter was entered
// If letter was entered add the letter to To_Transmit and output it on the display
if (Letter_Entered==1 ){
To_Transmit=To_Transmit + Letters[New_Position];
To_Transmit_Length++;
display.setCursor(3,0);
display.setTextColor(BLACK );
display.fillRect(0, 0, 128, 15, SSD1306_WHITE);
display.println(To_Transmit);
display.display();
Letter_Entered=0;
delay(100);
}
// If Transmit button was pressed start morse code transmition
if (Transmit==1){
for (int i=0; i<To_Transmit_Length;i++ ){
Play_Letter(To_Transmit.charAt(i));
Transmit=0;
}
}
}