/****************************************************************
      JI3BNB AX.25 HF PACKET (300baud) DECODE ENGINE <CORE>
      ARDUINO MEGA 2560
      v1.31 2026.02.21
      --  THIS PROGRAM IS IN THE PUBLIC DOMAIN  --
/****************************************************************/

//Digital input 19
//Serial output 115200 baud

#include <TimerOne.h>

volatile  int   pArray[7];
volatile  int   syncPoint;
volatile  bool  state_1;
volatile  bool  state_2;
volatile  bool  state_3;
volatile  bool  state_4;
 
void setup()
{
        Timer1.initialize();
        Timer1.attachInterrupt(timer_interrupt, 333); //300Baud
        Serial.begin(115200);
}

void timer_interrupt(void)
{
        static int  syncClock;
        static bool smplReady;
        static int  skips;
        static byte ones;
        static bool fiveOnes;
        static byte count8;
        static byte buf8;
        static int  addr;
        
        //save sync points
        state_2 = digitalRead(19);
        if(state_1 == 0 && state_2 == 1) //rising edge
        {
                for(int s = 0; s < 7; s++)
                {
                        pArray[s] = pArray[s + 1];
                }
                pArray[6] = syncClock;
        }
        //sample and get byte
        if(syncClock - syncPoint >= -1 && syncClock - syncPoint <= 1)
        {
                smplReady = true;
        }
        else if(syncClock - syncPoint == -9 || syncClock - syncPoint == 9)
        {
                smplReady = true;
        }
        else if(smplReady == true)
        {
                skips++;
                if(skips == 5) //go sample now!
                {
                        state_4 = digitalRead(19);
                        if(state_3 != state_4) //(NRZI) inverted = 0
                        {
                                if(fiveOnes == true)
                                {
                                        //zero insertion
                                        //do nothing
                                }
                                else
                                {
                                        buf8 = buf8 >> 1;
                                        bitWrite(buf8, 7, 0);
                                        Serial.print('0');
                                        count8++;
                                }
                                fiveOnes = false;
                                ones = 0;
                        }
                        else //(NRZI) no change = 1
                        {
                                buf8 = buf8 >> 1;
                                bitWrite(buf8, 7, 1);
                                Serial.print('1');
                                ones++;
                                if(ones == 5)
                                {
                                        fiveOnes = true;
                                }
                                else
                                {
                                        fiveOnes = false;
                                }
                                count8++;
                                if(ones == 6) //flag
                                {
                                        count8 = 7; //reset position
                                }
                        }
                        if(count8 == 8) //get BYTE now!
                        {
                                /*
                                Serial.print("  ");
                                if(buf8 < 16)
                                {
                                        Serial.print('0');
                                }
                                Serial.print(buf8, HEX);
                                */
                                if(buf8 != 0x7E && addr < 15) //address field
                                {
                                        buf8 = buf8 >> 1;
                                }
                                Serial.print("  ");
                                Serial.println((char)buf8);
                                count8 = 0;
                                addr++;
                                if(buf8 == 0x7E) //after flag
                                {
                                        addr = 1;
                                }
                        }
                        smplReady = false;
                        skips = 0;
                }
        }
        syncClock++;
        if(syncClock > 9)
        {
                syncClock = 0;
        }
        state_1 = state_2;
        state_3 = state_4;
}

void loop()
{
        volatile int tMax;
        int sumArray[] = {0,0,0,0,0,0,0,0,0,0};
        
        //find MOST SEEN point
        for(int p = 0; p < 7; p++)
        {
                /*
                Serial.print(pArray[p]);
                Serial.print(' ');
                */
                for(int s = 0; s < 10; s++)
                {
                        if(pArray[p] == s)
                        {
                                sumArray[s] += 1;
                        }
                }
        }
        /*
        for(int s = 0; s < 10; s++)
        {
                Serial.print(sumArray[s]);
                Serial.print(' ');
        }
        */
        tMax = -1;
        syncPoint = -1;
        for(int s = 0; s < 10; s++)
        {
                if(sumArray[s] > tMax)
                {
                        tMax = sumArray[s];
                        syncPoint = s;
                }
        }
        /*
        Serial.print("tMax:");
        Serial.print(tMax);
        Serial.print(' ');
        Serial.print("syncPoint:");
        Serial.print(syncPoint);
        Serial.print(' ');
        Serial.println();
        */
        delay(1);
}