You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

420 lines
11 KiB
C

/** @file functions.c
* @brief Diverse Funktionen
* @author Tom, DL7BJ
*/
#include "functions.h"
// EEProm
uint8_t Dummy;
uint8_t ee_Dummy EEMEM = 0x55; // Dummy for Address 0
uint8_t ee_WpM EEMEM = 12; // WpM
uint8_t ee_Sidetone EEMEM = 1; // Mithörton An (1) oder Aus (0)
uint16_t ee_FrequencySidetone EEMEM = 600; // Frequenz des Mithörtons
uint8_t ee_IambicMode EEMEM = 0; // Iambic Mode A oder B
uint8_t ee_Weight EEMEM = 3; // Dah dit Ratio
uint8_t ee_TRX EEMEM = 2; // TRX 1 (0), TRX 2 (1), Beide (2)
// Stringkonstanten für VT100 Terminals
char CLRSCR[] = "\033[2J";
/** @brief Ein paar Millisekunden warten
*
* Dieser Variable muss atomar sein, weil es eine 16Bit Variable ist,
* die im Timer 0 verwendet wird.
* @param Zeit in Millisekunden, die gewartet werden soll
* @return void
*/
void DelayMilliSeconds(uint16_t ms)
{
t_delayms = 0;
// ResetMilliSeconds();
//ATOMIC_BLOCK(ATOMIC_FORCEON) {
while(t_delayms < ms);
//}
}
/** @brief Wert des Zählers für Millisekunden lesen
*
* Dieser Variable muss atomar sein, weil es eine 16Bit Variable ist,
* die im Timer 0 verwendet wird.
* @param none
* @return milliseconds
*/
uint16_t GetMilliSeconds(void)
{
uint16_t m;
ATOMIC_BLOCK(ATOMIC_FORCEON){
m = t_delayms;
}
return m;
}
/** @brief Setzt den Zähler für Millisekunden auf 0
*
* Dieser Variable muss atomar sein, weil es eine 16Bit Variable ist,
* die im Timer 0 verwendet wird.
* @param none
* @return none
*/
void ResetMilliSeconds(void)
{
//ATOMIC_BLOCK(ATOMIC_FORCEON){
t_delayms = 0;
//}
}
/** @brief SREG wieder herstellen und Interrupts erlauben
* @param none
* @return none
*/
void IntEnable(void)
{
SREG = sreg_tmp;
sei();
}
/** @brief SREG sichern und Interrupts verbieten
* @param none
* @return none
*/
void IntDisable(void)
{
sreg_tmp = SREG;
cli();
}
/** \brief EEPROM schreiben
*/
void WriteEEprom(void)
{
cli();
eeprom_write_byte(&ee_Dummy,0x55);
eeprom_write_byte(&ee_WpM, bConfig.WpM);
eeprom_write_byte(&ee_IambicMode, bConfig.IambicMode);
eeprom_write_word(&ee_FrequencySidetone, bConfig.FrequencySidetone);
eeprom_write_byte(&ee_TRX, bConfig.TRX);
sei();
}
void ReadEEprom(void)
{
// wpm = eeprom_read_byte(&ee_wpm);
}
void WriteEEpromWpM(void)
{
cli();
sprintf(sdebug," %i WpM in EEprom schreiben\r\n",bConfig.WpM);
SendSerialString(sdebug);
eeprom_write_byte(&ee_WpM, bConfig.WpM);
sei();
}
void ReadEEpromWpM(void)
{
cli();
bConfig.WpM = eeprom_read_byte(&ee_WpM);
sei();
sprintf(sdebug," %i WpM von EEprom gelesen\r\n",bConfig.WpM);
SendSerialString(sdebug);
if(bConfig.WpM > 50) {
bConfig.WpM = 15;
WriteEEpromWpM();
}
}
void SendSerialChar(unsigned char data)
{
while(!(UCSR0A & (1<<UDRE0)));
UDR0 = data;
}
void SendSerialString(char *s)
{
while(*s != 0x00)
SendSerialChar(*s++);
}
/** \brief Read port pin of morse keys
* This function reads the input of
* the Paddle or Straight key.
*
*/
uint8_t ReadKeyPin(uint8_t pin)
{
return(PIND & (1<<pin));
}
/*
** SideToneOn
*/
void SideToneOn(void)
{
state_sidetoneoff = 0;
StateRiseTime = bConfig.RiseTime;
StateRiseTimeCounter = 0;
icnt = 0;
sbi(TIMSK1,OCIE1A);
}
/*
** SideToneOff
*/
void SideToneOff(void)
{
state_sidetoneoff = 1;
StateRiseTime = 0;
StateRiseTimeCounter = 0;
}
/*
** TXKey
**
** Tastung TRX1, TRX2 oder beide
*/
void TXKey(uint8_t State, uint8_t SendingType)
{
if((State) && (KeyState == 0))
{
if(KeyTX)
{
SideToneOn();
sbi(PORTC,MORSE_LED);
KeyState = 1;
}
}
else
{
if((State == 0) && (KeyState))
{
if(KeyTX)
{
SideToneOff();
cbi(PORTC,MORSE_LED);
}
KeyState = 0;
}
}
}
/** \brief StraigtKey
*
* Check Straightkey
*
*/
void CheckStraightKey(void)
{
if(PIND & (1<<STRAIGHT_KEY))
{
TXKey(0,MAN);
StateStraightKeyPressed = 0;
} else {
if(StateStraightKeyPressed == 0)
{
StateStraightKeyPressed = 1;
TimerStraightKeyPressed = 0;
}
if(StateStraightKeyPressed == 2)
{
TXKey(1,MAN);
}
}
}
/** \brief CheckPaddles
**
*/
void CheckPaddles(void)
{
CheckDitPaddle();
CheckDahPaddle();
}
/** \brief CheckDitPaddle
*
*
*/
void CheckDitPaddle(void)
{
uint8_t pinvalue = 0;
uint8_t ditpaddle = 0;
if(PaddleMode == PADDLE_NORMAL) // no reverse paddle
ditpaddle = LEFT_PADDLE;
else
ditpaddle = RIGHT_PADDLE; // reverse paddle
pinvalue = ReadKeyPin(ditpaddle);
if(pinvalue == 0)
DitBuffer = 1;
}
/*
** CheckDahPaddle
*/
void CheckDahPaddle(void)
{
uint8_t pinvalue = 0;
uint8_t dahpaddle = 0;
if(PaddleMode == PADDLE_NORMAL) // no reverse paddle
dahpaddle = RIGHT_PADDLE;
else
dahpaddle = LEFT_PADDLE; // reverse paddle
pinvalue = ReadKeyPin(dahpaddle);
if(pinvalue == 0) {
if(DahBuffer == 0) {
DahCounter++;
DitCounter = 0;
}
DahBuffer = 1;
}
}
/** \brief Schleife für die Dauer der Zeichenelemente
**
** len = count of dits * weigthing / 50
** AddMiliSeconds = increase pausing between elements
** SendingType = AUTO or MAN
*/
void ElementLoop(uint8_t len, uint8_t AddMilliSeconds, uint8_t SendingType)
{
uint16_t LoE; // lengths of one element in ms
uint16_t ticks; // lengths of len elements + AddMilliSeconds in ms
if((len == 0) || (len < 0))
return;
LoE = 1200/WpM;
ticks = LoE * len + AddMilliSeconds;
mselement = 0; // Reset Timer 0 variable
while(mselement < ticks) {
if((KeyerMode == IAMBIC_A) && (!(ReadKeyPin(LEFT_PADDLE))) && (!(ReadKeyPin(RIGHT_PADDLE))))
IambicFlag = 1;
if(SendStatus == SENDING_DIT)
CheckDahPaddle();
else if(SendStatus == SENDING_DAH)
CheckDitPaddle();
else {
CheckDahPaddle();
CheckDitPaddle();
}
}
if((KeyerMode == IAMBIC_A) && (IambicFlag) && ReadKeyPin(LEFT_PADDLE) && ReadKeyPin(RIGHT_PADDLE)) {
IambicFlag = 0;
DitBuffer = 0;
DahBuffer = 0;
}
}
/*
** void SendDit(uint8_t SendingType)
*/
void SendDit(uint8_t SendingType)
{
SendStatus = SENDING_DIT;
TXKey(1,SendingType);
ElementLoop(1,0,SendingType);
TXKey(0,SendingType);
ElementLoop(1,0,SendingType);
}
/** \brief Send a dah
** A Dah with weight = 50 has the length of 3 Dits.
*/
void SendDah(uint8_t SendingType)
{
SendStatus = SENDING_DAH;
TXKey(1,SendingType);
ElementLoop(3,0,SendingType);
TXKey(0,SendingType);
ElementLoop(1,0,SendingType);
}
/*
** Set sidetone frequency
*/
void SetFrequency(uint16_t f)
{
IntDisable();
OCR1A = (F_CPUPRESIN / f) - 1;
IntEnable();
}
/*
** Output a tone width frequency f and duration duration
**
*/
void Tone(uint16_t f, uint8_t duration)
{
SetFrequency(f);
SideToneOn();
DelayMilliSeconds(duration);
SideToneOff();
SetFrequency(bConfig.FrequencySidetone);
}
void Boop(void)
{
Tone(600,100);
}
void Beep(void)
{
Tone(1200,100);
}
void BeepBoop(void)
{
sbi(PORTB,AUDIO_EN);
DelayMilliSeconds(10);
Beep();
DelayMilliSeconds(100);
Boop();
}
void SendChar(unsigned char c)
{
switch(c)
{
// Buchstaben
case 'A': SendDit(AUTO); SendDah(AUTO); break;
case 'B': SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case 'C': SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case 'D': SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case 'E': SendDit(AUTO); break;
case 'F': SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case 'G': SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); break;
case 'H': SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case 'I': SendDit(AUTO); SendDit(AUTO); break;
case 'J': SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case 'K': SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case 'L': SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case 'M': SendDah(AUTO); SendDah(AUTO); break;
case 'N': SendDah(AUTO); SendDit(AUTO); break;
case 'O': SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case 'P': SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); break;
case 'Q': SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case 'R': SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); break;
case 'S': SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case 'T': SendDah(AUTO); break;
case 'U': SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case 'V': SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case 'W': SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case 'X': SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case 'Y': SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case 'Z': SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); break;
// Zahlen
case '0': SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case '1': SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case '2': SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case '3': SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case '4': SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case '5': SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case '6': SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case '7': SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case '8': SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case '9': SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); break;
// Sonderzeichen
case '=': SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case '/': SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); break;
case '.': SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); break;
case ',': SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); break;
case '?': SendDit(AUTO); SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); SendDit(AUTO); break;
case '@': SendDit(AUTO); SendDah(AUTO); SendDah(AUTO); SendDit(AUTO); SendDah(AUTO); SendDit(AUTO); break;
}
ElementLoop(3,0,WpM);
}