ARCHITECTURE studentVersion OF charToMorseController IS

signal isA, isB, isC, isD, isE, isF, isG, isH,
       isI, isJ, isK, isL, isM, isN, isO, isP,
       isQ, isR, isS, isT, isU, isV, isW, isX,
       isY, isZ,
       is0, is1, is2, is3, is4, is5, is6, is7,
       is8, is9 : std_ulogic;

type T_MORSE is (SHORT, LONG, SPACE, END_WORD);
--type registers_type is array (1 to 5) of T_MORSE;
signal register1: T_MORSE;
signal register2: T_MORSE;
signal register3: T_MORSE;
signal register4: T_MORSE;
signal register5: T_MORSE;

TYPE GENERAL_STATE_TYPE IS (
        waitForChar,
        storeChar,
        sendRegisters,
        sended
    );
signal general_current_state, general_next_state : GENERAL_STATE_TYPE;

TYPE SENDING_STATE_TYPE IS (
        waiting,
        sendR1,
        waitR1,
        sendR2,
        waitR2,
        sendR3,
        waitR3,
        sendR4,
        waitR4,
        sendR5,
        waitSpace,
        waitEndWord
    );
signal sending_current_state, sending_next_state : SENDING_STATE_TYPE;

signal signSendRegisters, signRegistersSended: std_ulogic;

BEGIN
  ------------------------------------------------------------------------------
                                                   -- conditions for morse units
  isA <= '1' when std_match(unsigned(char), "1-0" & x"1") else '0'; -- 1-0 0001
  isB <= '1' when std_match(unsigned(char), "1-0" & x"2") else '0'; -- 1-0 0010
  isC <= '1' when std_match(unsigned(char), "1-0" & x"3") else '0'; -- 1-0 0011
  isD <= '1' when std_match(unsigned(char), "1-0" & x"4") else '0'; -- 1-0 0100
  isE <= '1' when std_match(unsigned(char), "1-0" & x"5") else '0'; -- 1-0 0101
  isF <= '1' when std_match(unsigned(char), "1-0" & x"6") else '0'; -- 1-0 0110
  isG <= '1' when std_match(unsigned(char), "1-0" & x"7") else '0'; -- 1-0 0111
  isH <= '1' when std_match(unsigned(char), "1-0" & x"8") else '0'; -- 1-0 1000
  isI <= '1' when std_match(unsigned(char), "1-0" & x"9") else '0'; -- 1-0 1001
  isJ <= '1' when std_match(unsigned(char), "1-0" & x"A") else '0'; -- 1-0 1010
  isK <= '1' when std_match(unsigned(char), "1-0" & x"B") else '0'; -- 1-0 1011
  isL <= '1' when std_match(unsigned(char), "1-0" & x"C") else '0'; -- 1-0 1100
  isM <= '1' when std_match(unsigned(char), "1-0" & x"D") else '0'; -- 1-0 1101
  isN <= '1' when std_match(unsigned(char), "1-0" & x"E") else '0'; -- 1-0 1110
  isO <= '1' when std_match(unsigned(char), "1-0" & x"F") else '0'; -- 1-0 1111
  isP <= '1' when std_match(unsigned(char), "1-1" & x"0") else '0'; -- 1-1 0000
  isQ <= '1' when std_match(unsigned(char), "1-1" & x"1") else '0'; -- 1-1 0001
  isR <= '1' when std_match(unsigned(char), "1-1" & x"2") else '0'; -- 1-1 0010
  isS <= '1' when std_match(unsigned(char), "1-1" & x"3") else '0'; -- 1-1 0011
  isT <= '1' when std_match(unsigned(char), "1-1" & x"4") else '0'; -- 1-1 0100
  isU <= '1' when std_match(unsigned(char), "1-1" & x"5") else '0'; -- 1-1 0101
  isV <= '1' when std_match(unsigned(char), "1-1" & x"6") else '0'; -- 1-1 0110
  isW <= '1' when std_match(unsigned(char), "1-1" & x"7") else '0'; -- 1-1 0111
  isX <= '1' when std_match(unsigned(char), "1-1" & x"8") else '0'; -- 1-1 1000
  isY <= '1' when std_match(unsigned(char), "1-1" & x"9") else '0'; -- 1-1 1001
  isZ <= '1' when std_match(unsigned(char), "1-1" & x"A") else '0'; -- 1-1 1010
  is0 <= '1' when std_match(unsigned(char), "011" & x"0") else '0'; -- 011 0000
  is1 <= '1' when std_match(unsigned(char), "011" & x"1") else '0'; -- 011 0001
  is2 <= '1' when std_match(unsigned(char), "011" & x"2") else '0'; -- 011 0010
  is3 <= '1' when std_match(unsigned(char), "011" & x"3") else '0'; -- 011 0011
  is4 <= '1' when std_match(unsigned(char), "011" & x"4") else '0'; -- 011 0100
  is5 <= '1' when std_match(unsigned(char), "011" & x"5") else '0'; -- 011 0101
  is6 <= '1' when std_match(unsigned(char), "011" & x"6") else '0'; -- 011 0110
  is7 <= '1' when std_match(unsigned(char), "011" & x"7") else '0'; -- 011 0111
  is8 <= '1' when std_match(unsigned(char), "011" & x"8") else '0'; -- 011 1000
  is9 <= '1' when std_match(unsigned(char), "011" & x"9") else '0'; -- 011 1001
  ------------------------------------------------------------------------------

  process(reset, clock) begin
    if reset = '1' then
      general_current_state <= waitForChar;
      sending_current_state <= waiting;
    elsif rising_edge(clock) then
      general_current_state <= general_next_state;
      sending_current_state <= sending_next_state;
    end if;
  end process;


  process(reset, clock) begin
    case general_current_state is
      when waitForChar =>
        --report "General current state is wait for char" severity note;
        register1 <= SPACE;
        register2 <= SPACE;
        register3 <= SPACE;
        register4 <= SPACE;
        register5 <= SPACE;
        signSendRegisters <= '0';
        if charNotReady = '0' then
          general_next_state <= storeChar;
          readChar <= '1';
          report "charReady" severity note;
        else
          general_next_state <= waitForChar;
          readChar <= '0';
          --report "charNotReady" severity note;
        end if;

      when storeChar =>
        report "General current state is store char" severity note;
        if isA then
          register1 <= SHORT;
          register2 <= LONG;
          general_next_state <= sendRegisters;
          report "New char: A" severity note;
        elsif isB then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isC then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= LONG;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isD then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isE then
          register1 <= SHORT;
          general_next_state <= sendRegisters;
          report "New char: E" severity note;
        elsif isF then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= LONG;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isG then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isH then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isI then
          register1 <= SHORT;
          register2 <= SHORT;
          general_next_state <= sendRegisters;
          report "New char: I" severity note;
        elsif isJ then
          register1 <= SHORT;
          register2 <= LONG;
          register3 <= LONG;
          register4 <= LONG;
          general_next_state <= sendRegisters;
        elsif isK then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= LONG;
          general_next_state <= sendRegisters;
        elsif isL then
          register1 <= SHORT;
          register2 <= LONG;
          register3 <= SHORT;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isM then
          register1 <= LONG;
          register2 <= LONG;
          general_next_state <= sendRegisters;
          report "New char: M" severity note;
        elsif isN then
          register1 <= LONG;
          register2 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isO then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= LONG;
          general_next_state <= sendRegisters;
        elsif isP then
          register1 <= SHORT;
          register2 <= LONG;
          register3 <= LONG;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isQ then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= SHORT;
          register4 <= LONG;
          general_next_state <= sendRegisters;
        elsif isR then
          register1 <= SHORT;
          register2 <= LONG;
          register3 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isS then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= SHORT;
          general_next_state <= sendRegisters;
        elsif isT then
          register1 <= LONG;
          general_next_state <= sendRegisters;
          report "New char: T" severity note;
        elsif isU then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= LONG;
          general_next_state <= sendRegisters;
        elsif isV then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= LONG;
          general_next_state <= sendRegisters;
        elsif isW then
          register1 <= SHORT;
          register2 <= LONG;
          register3 <= LONG;
          general_next_state <= sendRegisters;
        elsif isX then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= LONG;
          general_next_state <= sendRegisters;
        elsif isY then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= LONG;
          register4 <= LONG;
          general_next_state <= sendRegisters;
        elsif isZ then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= SHORT;
          register4 <= SHORT;
          general_next_state <= sendRegisters;
        elsif is0 then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= LONG;
          register4 <= LONG;
          register5 <= LONG;
          general_next_state <= sendRegisters;
        elsif is1 then
          register1 <= SHORT;
          register2 <= LONG;
          register3 <= LONG;
          register4 <= LONG;
          register5 <= LONG;
          general_next_state <= sendRegisters;
        elsif is2 then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= LONG;
          register4 <= LONG;
          register5 <= LONG;
          general_next_state <= sendRegisters;
        elsif is3 then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= LONG;
          register5 <= LONG;
          general_next_state <= sendRegisters;
        elsif is4 then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= SHORT;
          register5 <= LONG;
          general_next_state <= sendRegisters;
        elsif is5 then
          register1 <= SHORT;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= SHORT;
          register5 <= SHORT;
          general_next_state <= sendRegisters;
        elsif is6 then
          register1 <= LONG;
          register2 <= SHORT;
          register3 <= SHORT;
          register4 <= SHORT;
          register5 <= SHORT;
          general_next_state <= sendRegisters;
        elsif is7 then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= SHORT;
          register4 <= SHORT;
          register5 <= SHORT;
          general_next_state <= sendRegisters;
        elsif is8 then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= LONG;
          register4 <= SHORT;
          register5 <= SHORT;
          general_next_state <= sendRegisters;
        elsif is9 then
          register1 <= LONG;
          register2 <= LONG;
          register3 <= LONG;
          register4 <= LONG;
          register5 <= SHORT;
          general_next_state <= sendRegisters;
        else
          register1 <= SPACE;
          register2 <= SPACE;
          register3 <= SPACE;
          register4 <= SPACE;
          register5 <= SPACE;
          general_next_state <= storeChar;
          report "Char look not correct" severity warning;
        end if;
        signSendRegisters <= '1';

      when sendRegisters =>
        --report "General current state is send registers" severity note;
        readChar <= '0';
        signSendRegisters <= '0';
        if signRegistersSended then
          general_next_state <= sended;
          report "Char is send" severity note;
        end if;

      when sended =>
        --report "General current state is sended" severity note;
        general_next_state <= waitForChar;
        register1 <= SPACE;
        register2 <= SPACE;
        register3 <= SPACE;
        register4 <= SPACE;
        register5 <= SPACE;
      
      WHEN OTHERS =>
        report "General current state is BROKEN" severity warning;
        general_next_state <= waitForChar;

    end case;
  end process;

  process(reset, clock) begin
    case sending_current_state is

      when waiting =>
        morseOut <= '0';
        startCounter <= '0';
        unitNb <= "000";
        signRegistersSended <= '0';
        if signSendRegisters = '1' then
          sending_next_state <= sendR1;
          report "Start to send new char" severity note;
        else 
          sending_next_state <= waiting;
        end if;

      when sendR1 =>
        report "Send register1" severity note;
        startCounter <= '1';
        morseOut <= '1';
        case register1 is
          when SHORT =>
            unitNb <= "001";
          when LONG =>
            unitNb <= "011";
          when others =>
            report "Error when sending register1" severity error;
        end case;

        case register2 is
          when SPACE =>
            sending_next_state <= waitSpace;
          when END_WORD =>
            sending_next_state <= waitEndWord;
          when others =>
            sending_next_state <= waitR1;
        end case;

      when waitR1 =>
        report "Wait register1" severity note;
        startCounter <= '0';
        if counterDone = '1' then
          morseOut <= '0';
          sending_next_state <= sendR2;
        end if;
      
      when sendR2 =>
        report "Send register2" severity note;
        startCounter <= '1';
        morseOut <= '1';
        case register2 is
          when SHORT =>
            unitNb <= "001";
          when LONG =>
            unitNb <= "011";
          when others =>
            report "Error when sending register2" severity error;
        end case;

        case register3 is
          when SPACE =>
            sending_next_state <= waitSpace;
          when END_WORD =>
            sending_next_state <= waitEndWord;
          when others =>
            sending_next_state <= waitR2;
        end case;

      when waitR2 =>
        report "Wait register2" severity note;
        startCounter <= '0';
        if counterDone = '1' then
          morseOut <= '0';
          sending_next_state <= sendR3;
        end if;
      
      when sendR3 =>
        report "Send register3" severity note;
        startCounter <= '1';
        morseOut <= '1';
        case register3 is
          when SHORT =>
            unitNb <= "001";
          when LONG =>
            unitNb <= "011";
          when others =>
            report "Error when sending register3" severity error;
        end case;

        case register4 is
          when SPACE =>
            sending_next_state <= waitSpace;
          when END_WORD =>
            sending_next_state <= waitEndWord;
          when others =>
            sending_next_state <= waitR3;
        end case;

      when waitR3 =>
        startCounter <= '0';
        if counterDone = '1' then
          morseOut <= '0';
          sending_next_state <= sendR4;
        end if;
      
      when sendR4 =>
        startCounter <= '1';
        morseOut <= '1';
        case register4 is
          when SHORT =>
            unitNb <= "001";
          when LONG =>
            unitNb <= "011";
          when others =>
            report "Error when sending register4" severity error;
        end case;

        case register5 is
          when SPACE =>
            sending_next_state <= waitSpace;
          when END_WORD =>
            sending_next_state <= waitEndWord;
          when others =>
            sending_next_state <= waitR4;
        end case;

      when waitR4 =>
        startCounter <= '0';
        if counterDone = '1' then
          morseOut <= '0';
          sending_next_state <= sendR5;
        end if;
      
      when sendR5 =>
        startCounter <= '1';
        morseOut <= '1';
        case register5 is
          when SHORT =>
            unitNb <= "001";
          when LONG =>
            unitNb <= "011";
          when others =>
            report "Error when sending register5" severity error;
        end case;

          sending_next_state <= waitSpace;  

      when waitSpace =>
        startCounter <= '0';
        if counterDone = '1' then
          morseOut <= '0';
          sending_next_state <= waiting;
        end if;
        signRegistersSended <= '1';
      
      when waitEndWord =>
        sending_next_state <= waiting;
      when others =>
        sending_next_state <= waiting;

    end case;
  end process;


END ARCHITECTURE studentVersion;
