Problem in order of execution of functions

I made a morse code interpreter with basic components and Arduino UNO.. It encodes text to morse code and decodes morse code to text within the serial monitor and gives output via a buzzer and a led.. and takes input through a push switch.
The problem is that when i task it to encode text to morse, It only does it after decoding something.. Is there a fix so that i can use both encoding and decoding in no particuar order..
I will attach the code and diagram..
I'm new to coding. so a help will be greatly appreciated..
Morse_Code.ino (8.9 KB)

You also seem to have waited until you have an entire program written to begin testing. I suggest you separate the functions into separate programs and test them individually and get all the bugs out and combine the code back into a final program.

I actually did like that.
I did the encoder first in one program and decoder in another and combined it.. it did fine on its own. so i don't know how to fix it

Very good for you. Usually we see people doing a whole huge program and then begin to test.
Have you user serial print() instructions to verify the logic steps of what you want to do?

I'm assuming its correct.. If you have time, please go through that code and pls tell me if there are any errors, or anything to be added..

If you detect serial input, your program should invoke the Morse code generator on the character just received.
If, on the other hand, the program detects input on the defined GPIO pin, it should invoke the Morse code interpreter part.
Are you expecting to simultaneously generate and interpret Morse code?

Anyway, your main problem appears to be the structure of the interpreter part. Once it gets into that, it gets stuck:

  while (digitalRead(inputPin) == HIGH) {}
  t1 = millis(); 
  digitalWrite(ledPin, HIGH);
  while (digitalRead(inputPin) == LOW) {}
  t2 = millis();

You’ll have to add timeouts to those while statements so that inactivity there does not block everything.

Your use of goto is likely to cause some discussion.
The Morse code generator part could also be drastically reduced in size.

Can you pls help me in doing it.. I'm only learning coding..

Really, all the blocking code with the goto statement should be re-written if you want to use both main parts simultaneously and / or automatically swap between them. It is simpler if, say, you want a button press to change the mode from generate to interpret at the time the program is started.

As a quick and dirty solution, you can try this. Change the original code below into the new code.

Original part:

while (Serial.available())
   code = Serial.readString();
   Serial.print(" = ");

New part:

static bool generateMode = true ;  // change to false to use the interpreter part
while ( generateMode && Serial.available())
   code = Serial.readString();
   Serial.print(" = ");
if ( generateMode ) return ;

Pls tell me how to include a push button in there to toggle between true and false... I did as you told and searched the internet too but no progress..

Did you try both true and false and confirm that it works as you want ?

The best solution is to rewrite the code using a finite state machine type approach instead of that blocking code. However, a button can be used during setup() to configure the program for a session but to change the mode, it would be necessary to reset the Arduino.

In principle, you would move this to near the top of the program with all the global variables and remove the static keyword.

In setup(), you'd add code like this (untested):

void setup() {
   . . .
   . . .
   const uint8_t modeButtonPin = X ; // your choice of pin
   pinMode( modeButtonPin, INPUT_PULLUP ) ; // Button is wired between ground and pin X.

   Serial.println(F("Press the button within 5 seconds to enter Morse Interpret mode otherwise the device remains in Morse Generate mode")) ;
   uint32_t modeSelectStartAtMs = millis() ;
   generateMode = true ;
   for(;;) {
      if ( digitalRead( modeButtonPin ) == LOW ) {
         generateMode = false ;  
         break ;
      if ( millis() - modeSelectStartAtMs > 5000UL ) break ;
   . . .
   . . .

You have a function for each letter and an interminable chain of else if statements in void morse(). You can save the patterns for each letter in a lookup table and have a single function look in there.

Last sentence is not very informative. Can you explain better what the program is supposed to do? How do you envision encoding and decoding simultaneously? Also, what is working and what is not working for the time being? Do both modes work individually?

I wanted to use both the modes simultaneously.. When i start the arduino. it would be in decode mode. to encode something, i would have to enter the text, then use the input button to start encoding.

So the prototype should be in standby mode and ready to receive. When it gets a string from serial, it should keep it in memory and then play it back as a morse sequence when you press a button. Is that it?

Ya... That's the encode function i had in mind

Alright. But what would the other mode be, then?

I would input something in morse via a push button.. and it give it as string in the serial monitor

I get it now; let's call it mode B. This will be harder to implement than mode A, because of all the timing involved. The program must be able to distinguish between a dash and a dot and also among:

  1. a pause between a dash and a dot
  2. a pause between words
  3. a longer pause that will mean "end of transmission"

You will probably need at least 2 buttons: one to toggle between modes and the other to work as the playback button (mode A) or the input button (mode B).

Since mode B is harder, I would first work on having mode A up and running. Maybe start with some code refactoring and restrict the problem to a smaller one, e.g. digits only, or only letters from A to F.

Get one character at time, then a string of fixed length, then a string of any length and so on.

I did mode A and B separately as 2 programs and tested it... it worked as intended..

So it's only a matter of merging them. A second button to toggle states is all that's needed.

Ya... I was trying to do that and added 1 more button.. it worked one time.. but now it won't