Witam.
Ostatnio złożyłem koledze wracającemu po latach do telegrafii klucz wg opisu powyżej. Przy okazji dodałem funkcję nauki - pseudolosowe znaki nadawane typowo w grupach po pięć znaków.
Może się przyda kod komuś uczącemu się C dla AVR .
73! Robert
Kod:
// main.c
// Created on: 10 sty 2016/poprawki 24.09.2019
// Author: SP6RGB
// Wersja 2.0 z nadawaniem treningowym
//Klucz telegraficzny - wyjscie PB4 na wejście KEY TRX (wymagany dodatkowy tranzystor kluczujacy)
//( w oryginale wyjscie PB4 przez rezystor 6,8kOhm steruje BC547B)
//Podłaczenie klucza do PB0 (kropka) i PB1(kreska)
//Krótkie przyciśnięcie PB3 - ruchomienie nadawania z pamieci / przytrzymanie klawisza PB3 - uruchomienie nadawania treningowego
//Regulacja tempa potencjometrem podlaczonym do PB2
//Wykorzystany pomysł z nadawaniem z pamieci wg Simon Monk
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#define PIN_KROPKA ( 1<<PB0 ) //Wejscie PB0jako przycisk kropek
#define PIN_KRESKA ( 1<<PB1 ) //Wejscie PB1 jako przycisk kresek
#define PIN_PAMIEC ( 1<<PB3 ) //Pamiec klucza
#define PIN_KEY ( 1<<PB4 ) //Wyjscie do sterowania TXa
#define PIN_STOP ( 1<<PB5 ) //Przycisk STOP nadawania z pamięci (reset procesora)
//Deklaracje funkcji
void kropkiNadawanie( uint16_t tempoF );
void kreskiNadawanie( uint16_t tempoF );
void zmienneDelay( uint16_t tempoF );
void nadajPamiec( void );
void znakNaMorse( char ch );
void nadajZnak( char* ktoryZnak );
void nadajKropkaLubKreska( char kropkaLubKreska );
void nadajNauka ( void );
uint16_t czytajTempo( void );
//Deklaracje zmiennych
uint16_t tempo; //Zmienna globalna do ustawiania tempa nadawania
//Im wieksza tym wolniejsze nadawanie
char* litery[] = //Deklaracja liter Morse'a
{ ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", // A-I Tylko duze litery do nadawanie z pamieci.
".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", // J-R
"...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.." }; // S-Z
char* numery[] = //Deklaracja liczb Morse'a
{ "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----." };
char* symbole[] = { "-..-.", "..--.." }; //Tylko dwa symbole "/" i "?" - wiecej sie w praktyce nie uzywa, a nie sa po kolei w ASCII jak dla liter i cyfr i nie mozna analogicznie wybierac
const char trening_P[] PROGMEM = "ABCDEFGHIJKLMNOPQRSTUWVXYZ01234567890/?"; //Tablica do nadawnia przy nauce - 39 znaków
const char pamiec_P[] PROGMEM = "CQ CQ CQ DE SP0XXX SP0XXX SP0XXX CQ CQ CQ DE SP0XXX SP0XXX SP0XXX PSE K"; //Tekst dowolny - DUZE LITERY!!!
int main ( void )
{
DDRB &= ~(PIN_KROPKA | PIN_KRESKA | PIN_PAMIEC | PIN_STOP); //Ustawienie wejsc
DDRB |= PIN_KEY; //Ustawienie wyjsc
PORTB |= PIN_KROPKA | PIN_KRESKA | PIN_PAMIEC | PIN_STOP; //Podciagniecie wejsc
ADCSRA |= (1<<ADEN); //Zalaczenie przetwornika ADC
ADMUX |= (1<<ADLAR)| (1<<MUX0); //Ustawienie prezentacji wyniku od lewej i wejscia PB2
ADMUX &= ~((1<<REFS0) | (1<<REFS1) | (1<<REFS2)); //Napiecie odniesienia rowne Vcc
while( 1 )
{
czytajTempo();
if (!(PINB & PIN_KROPKA)) kropkiNadawanie( tempo ); //Nacisniety pin kropki to kropkiNadawanie
if (!(PINB & PIN_KRESKA)) kreskiNadawanie( tempo ); //Nacisniety pin kreski to kreskiNadawanie
if (!(PINB & PIN_PAMIEC)) //Nacisniety krótko przycisk PAMIEĆ - nadawanie tekstu z pamięci
{
_delay_ms(100); //Przytrzymany chwilę przycisk PAMIEC - nadawanie treningowe losowego tekstu
if (!(PINB &PIN_PAMIEC))
nadajNauka();
else
nadajPamiec();
}
}
}
//Definicje funkcji
void kropkiNadawanie( uint16_t tempoF )
{
PORTB |= PIN_KEY; //Zalaczenie sterowania TRX
zmienneDelay( tempoF ); //na czas okreslony przez zmienna tempo
PORTB &= ~PIN_KEY;
zmienneDelay( tempoF ); //czas pomiedzy znakami równy kropce
}
void kreskiNadawanie( uint16_t tempoF )
{
PORTB |= PIN_KEY;
zmienneDelay( tempoF*3 ); //Kreska równa trzem kropkom
PORTB &= ~PIN_KEY;
zmienneDelay( tempoF ); //Przerwa miedzy kreskami rowna kropce
}
void zmienneDelay( uint16_t tempoF )
{
while( tempoF-- ) _delay_us( 700 );
}
uint16_t czytajTempo( void ) //uint16_t bo wynik jest mnozony przez 3 i przekracza uint8_t
{ //chociaz odczytujemy tylko 8 bitow z ADCH
ADCSRA |= ( 1<<ADSC ); //Wyzwolenie jednorazowej konwersji
while((ADCSRA & ( 1<<ADSC ))); //Oczekiwanie na koniec pomniaru
tempo = ADCH + 1; //Wynik odczytwywany z rejestru ADCH plus 1 (zeby nie bylo 0)
return tempo;
}
void nadajPamiec( void ) //Funkcja wysylania danych z pamieci - dane okreslone w tablicach char Memory
{
int i = 0;
char ch;
while (pgm_read_byte(&pamiec_P[i])) //Petla az do napotkania w lancuchu "\0"
{
ch = (pgm_read_byte(&pamiec_P[i++])); //Wyodrebnienie z tabeli pamiec_P kolejnego znaku do wyslania znakowi do wyslania
znakNaMorse( ch ); //Funkcja przeksztalcajaca znak z tabeli "pamiec_P" w grupe "." i "-" do wyslania
}
}
void znakNaMorse( char ch ) //Funkcja do wybrania wlasciwej z tabeli litery lub cyfry
{
if (ch >= 'A' && ch <= 'Z') //Jezeli znak miesci sie pomiedzy A a Z to tabela liter
{
nadajZnak( litery[ch - 'A'] ); //Wywolanie funkcji wysylajacej wlasciwy znak. Znaki w tabeli opisane w kodzie ASCII podlegaja porownywaniu jak w operacjach
} //matematycznych. Kod ASCII(ch) - kod ASCII(A) da nam pozycje grupy w " " z tabeli letters do wyslania. Np A-A=0 czyli pierwsza grupa z tablicy.
else if ( ch >= '0' && ch <= '9' ) //Jezeli znak miesci sie pomiedzy 0 a 9 to tabela cyfr (numbers)
{
nadajZnak(numery[ ch - '0'] ); //Tak samo jak dla liter
}
else if ( ch == '/' )
{
nadajZnak(symbole[0]);
}
else if( ch == '?' )
{
nadajZnak(symbole[1]);
}
else if ( ch == ' ' ) //Jezeli pobrana zostala z tablicy pamiec_P spacja to generujemy przerwe miedzy slowami rowna dlugosci 4 kropek
{
zmienneDelay(tempo * 4);
}
}
void nadajZnak( char *ktoryZnak ) //Z tabeli char* [] pobrana zostaje grupa znaków w " " z pozycji okreslonej przez funkcje znakNaMorse
{
int i = 0;
while( ktoryZnak[i] ) //Pobiera kropki i kreski, az natrafi na znak konca lancucha
{
nadajKropkaLubKreska( ktoryZnak[i++] ); //Pobrana kropka lub kreska przekazana jest do funkcji generujacej kropki lub kreski
czytajTempo(); //W każdej chwili można zmienić tempo nadawania potencjometrem
}
zmienneDelay( tempo * 3 ); //Po NULL jest nowy znak i bedzie pobrana kolejna grupa kropek i kresek. Przerwa pomiedzy znakami rowna trzem kropkom
}
void nadajKropkaLubKreska( char kropkaLubKreska ) //Prosta funkcja identyfikujaca czy przekazano do niej kropke czy kreske i je wysylajaca
{
if ( kropkaLubKreska == '.' )
{
kropkiNadawanie( tempo ); //Uzyte do generowania kropek i kresek te same funkcje co wyzej
}
else
{
kreskiNadawanie( tempo );
}
}
void nadajNauka ( void )
{
char ch;
uint8_t i, j;
srand( tempo ); //W celu utrzymnania losowości znaków należy zmieniac tempo (pokęcic potencjometrem) przed kolejnmy uruchomieniem nauki
while( 1 ) //i dopasowac tempo do swoich preferencji po uruchomieniu. srand() ustawia dane wejsciowe do generatora liczb pseudolosowych na podstawie wartości tempo.
{ //wywoływanego przez funkcję rand() - generator liczb pseudolosowych nie jest dobry, ale dla tych potrzeb wystarczający.
for (j = 0; j < 5; j++) //nadajemy w grupach po 5 znaków
{
i = rand()%38; //pseudolosowy wybór liczby od 0 do 38
ch = pgm_read_byte(&trening_P[i]); //odczyt losowego znaku z tablicy trening_P[]
znakNaMorse( ch ); //nadanie wybranego znaku
}
zmienneDelay(tempo * 4); //spacja - przerwa między grupami równa 4 kropkom
}
}