#ifndef GLOBALS_H_INCLUDED
#define GLOBALS_H_INCLUDED
  
#define F_CPU           16000000UL
#define PRESCALER       8
#define SINEWAVELENGTH  64
#define F_CPUPRESIN     (F_CPU/(PRESCALER*SINEWAVELENGTH))
#define USART_BAUDRATE  9600
#define UBRR_VALUE      (((F_CPU/(USART_BAUDRATE*16UL)))-1)
  
#define LENGTH 256
#define AMP 127
#define OFFSET 128
#define PI2 6.283185

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <inttypes.h>
  
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <util/atomic.h>

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // clear bit
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))  // set bit

#include "oled/i2c.h"
#include "oled/lcd.h"
#include "oled/font.h"

#ifndef EEMEM
#define EEMEM __attribute__ ((section (".eeprom")))
#endif
  
#ifndef NOINIT
#define NOINIT __attribute__ ((section (".noinit")))
#endif

#define L_WAIT                  500     // Frequency for debug LED Timer 0

#define CALL  "  DL7BJ   "
#define PRG   " BJ-Keyer "
#define VER   "  V1.00   "


// Keying states
#define NOTHING                   0
#define DIT_DAH_OFF               1
#define DAH_DIT_OFF               2
#define DIT_DAH_ON                3
#define DAH_DIT_ON                4
// Keyer mode
#define STRAIGHT                  0
#define IAMBIC_B                  1
#define IAMBIC_A                  2
#define ULTIMATIC                 3
#define SINGLE_PADDLE             4
// Paddle Mode
#define PADDLE_NORMAL             0
#define PADDLE_REVERSE            1
// Sending Mode
#define SENDING_NOTHING           0
#define SENDING_DIT               1
#define SENDING_DAH               2
#define SENDING_ELEMENT_SPACE     3
#define SENDING_STRAIGHT          4
// Sending Type
#define AUTO                      0         // Automatische Pausen zwischen Elementen
#define MAN                       1         // Manuelle Pausen zwischen Elementen
// Side Tone
#define SIDETONE_OFF              0
#define SIDETONE_ON               1
// Ports
#define LEFT_PADDLE               PD2     // Left Paddle Input
#define RIGHT_PADDLE              PD3     // Right Paddle Input
#define STRAIGHT_KEY              PD4     // Straight key Input
#define MORSE_LED                 PC3     // LED Morse Output
#define MEM1                      PD5     // Mem 1 Input
#define MEM2                      PD6     // Mem 2 Input
#define MEM3                      PD7     // Mem 3 Input
#define MEM4                      PC0     // Mem 4 Input
#define MEM5                      PB5     // Mem 5 Input
#define TRX1                      PC1     // TRX1 Output
#define TRX2                      PC2     // TRX2 Output
#define AUDIO                     PB3     // PWM Audio Output
#define AUDIO_EN                  PB4     // Audio PA Enable
#define SCL                       PC5     // I²C LC Display
#define SDA                       PC4     // I²C LC Display
// States
#define ON                       1
#define OFF                      0
#define DIT                      1
#define DAH                      0
#define NO_KEY_PRESSED           0
#define KEY_PRESSED_DEBOUNCE     1
#define KEY_PRESSED              2
// Menue und Drehencoder
#define M_TRX1                   1
#define M_TRX2                   2
#define M_TON                    3
#define M_TON_FREQ               4
#define M_IAMBICA                5
#define M_IAMBICB                6
#define M_ULTIMATIC              7
#define M_MEMORY                 8
#define M_REVERSE                9
#define M_RATIO                 10
#define M_SPEEDRATIO            11
#define M_WPMBPM                12
#define M_RISETIME              13
#define M_DEBOUNCE              14
#define M_MAX                   14          // maximale Menuepunke
// LCD
#define CLEARLINE               "                     "
#define NORMAL                  0

// Debugausgabe
char sdebug[64];

// Structs für Status, Menü und Einstellungen
struct State
{
    uint8_t WpMChanged:  1;             // Geschwindigkeit geändert
    uint8_t WriteWpMEEprom: 1;          // nicht gespeicherte Geschwindigkeit 
    uint8_t WriteEEprom: 1;             // nicht gespeicherte EEprom Werte
    uint8_t SidetoneOff: 1;             // Mithörton an oder aus
    uint8_t SidetoneEnabled: 1;         // Mithörton ein- oder ausgeschaltet
    uint8_t SendStatus;                 // Status, ob Symbol gesendet wird
    uint8_t LastSymbolWasDit: 1;        // letztes Symbol war ein Punkt
    uint8_t DitPressed: 1;              // Dit Hebel betätigt
    uint8_t DahPressed: 1;              // Dah Hebel betätigt
    uint8_t Encoder: 1;                 // Drekencoder wurde betätigt
    uint8_t KeyState:1;                 //
    uint8_t KeyTX:1;
};

struct MenuCtrl
{
    uint8_t  buttonPressed: 1;
    uint8_t  buttonPressedLong: 1;
    uint8_t  m_buttonPressed: 2;
    uint8_t  m_buttonPressedLong: 1;
    uint8_t  ClrScr: 1;
    uint8_t  Config: 1;
    uint8_t  WriteEEprom: 1;
    uint8_t  Update: 1;
    uint8_t  CurMenue;
    uint8_t  SubMenue: 1;
};

struct Config
{
    uint8_t TRX: 2;                     // TRX 1 oder 2 oder beide
    uint8_t KeyerMode: 3;               // Iambic A, Iambic B oder Ultimatic
    uint8_t SidetoneEnabled: 1;         // Mithörton eingeschaltet
    uint8_t WpMBpM: 1;                  // WpM oder BpM Anzeige
    uint8_t Reverse: 1;                 // linkes/rechtes Paddle vertauschen
    uint8_t SpeedRatioEnabled: 1;       // Punkt/Strich Verhältnis Auto
    uint8_t Ratio;                      // Punkt/Strich Verhältnis 1:3
    uint8_t Memory:1;                   // Punkt/Strich Speicher
    uint16_t SidetoneFreq;              // Frequenz des Mithörtons
    uint8_t WpM;                        // WpM
    uint8_t RiseTime;                   // Anstiegszeit Sinuston
    uint8_t RiseTimeCounter;            // Anzahl Sinusschwingungen für den Anstieg
    uint8_t DebounceTime;               // Entprellzeit für Straight Key Eingang
};
// Pin Change Interrupt Merker für Port 
uint8_t LastPINDState;

// Drehencoder
volatile uint8_t EncoderTimer;          // 10ms Timer for Encoder
volatile int8_t EncoderCounter;         // Vor/Rück Zähler
volatile int8_t EncoderPos;             // Encoderposition für WpM/BpM
volatile int8_t EncoderPosConfig;       // Encoderposition für Einstellungen
volatile int8_t EncoderPosSubConfig;    // Encoderposition für Submenues

uint16_t StoreEEprom;

// Globale Variablen für diverse Zwecke
uint8_t WpM;
uint8_t Weight;
uint8_t LengthOfElement;

 
// State Machines
uint8_t PaddleMode;
uint8_t KeyerMode;
// History
uint8_t keyhistory;
uint8_t KeyTX;
uint8_t DahBuffer;
uint8_t DitBuffer;
uint8_t Weighting;
uint8_t IambicFlag;
uint8_t DitCounter;
uint8_t DahCounter;
uint8_t CurrentTRX1;

// Sidetone generation
volatile uint8_t icnt;
volatile uint8_t ocr2a;
// Variablen in Timer 0
volatile uint16_t l_timer;                      // counter for LED on
volatile uint8_t t_timer;                       // Frequency of audio output
volatile uint16_t t_wait;                       // delayms max. 65535ms
volatile uint8_t t_pwm;
volatile uint16_t t_wait_led;
volatile uint8_t lastButton;                    // Wert der letzten Buttonabfrage
volatile uint16_t DitMillis;
volatile uint16_t DahMillis;
// Zähler und Status für Entprellung der Tasteneingänge und Mithörton
volatile uint8_t    StateStraightKeyPressed;    // Merker für StraightKey betätigt
volatile uint8_t    TimerStraightKeyPressed;    // Timer Variable für Entprellung
volatile uint8_t    StatePaddleDitKeyPressed;   // Merker für Paddle betätigt
volatile uint8_t    TimerPaddleDitKeyPressed;   // Timer Variable für Entprellung
volatile uint8_t    StatePaddleDahKeyPressed;   // Merker für Paddle betätigt
volatile uint8_t    TimerPaddleDahKeyPressed;   // Timer Variable für Entprellung
volatile uint8_t    StateRiseTimeCounter;       // Zähler für Anstieg des Mithörtons
volatile uint8_t    StateRiseTime;
volatile uint8_t    StateRiseTimeCounter;
// Diverse Zähler für Timer 0
uint16_t MenuCtrlTimer;                         // Wartezeit bis zur Betriebsanzeige nach Config
volatile uint16_t t_delayms;                    // Timer 0 max. 65535ms, all purpose timer variable
volatile uint16_t t_elementlength;              // Timer 0 max. 65535ms, element length of dit or dah
#endif 
