DDS-Software for AD9835 and ATMega8 (QRP SSB Transceiver)

The following article is outdated. See a complete revision of the software for an AD9835-based DDS here:

https://dk7ih.de/2015/08/15/update-software-for-dds-controlled-qrp-ssb-handheld-transceiver-ad9835-atmega328p/

 

This blog page is about the software for my handheld 20 meter QRP SSB transceiver (Link).

The software…

  • …is written in C.
  • …needs an ATMega controller, preferably ATMega8 (running on 8 MHz),
  • …uses 5 push-buttons: 2 for frequency up/down, 1 for selecting tunings step, 1 for vfo select, 1 for Sleepmode (reduces receiver noise to a maximum),
  • …offers 4 VFOs, + 2 for SPLIT-MODE,
  • …offers frequency steps for tuning: 1, 5, 10, 50, 100, 250, 500, 1000, 5000 Hz. Software returns after 2 idle seconds always to 10-Hz tuning step.
  • …has got a scan mode,
  • …drives an LCD-Display (2×8 characters),
  • …accepts a dc voltage by an 1:3 voltage divider to monitor battery status.

Port connections are as follows:

OUTPUT:

  • LCD – RS: PB6, E: PB7, Data: D4…D7 = PD4..PD7
  • AD9835 DDS-Chip:  FSYNC: PB0, SDATA: PB1,  SCLK: PB2

INPUT:

  • VFO SELECT: PC5 (Push-button)
  • TUNE UP: PD2 (Push-button)
  • TUNE DOWN: PD3 (Push-button)
  • Tuning Step: PC3 (Push-button)
  • VBat = PC0 (DC line by voltage divider 1:3)

All inputs switch to ground!

So, if you plan this project, make sure that the respective ports are available and use them. Or use a larger controller an connect to your own choice.

The C-code is underneath. Sorry, most comments are in German due to the fact that this is my native language. 😉 Function names are in English which should help.

 

/*****************************************************************/
/*  DDS for RF SSB QRP rig with ATMega 8 aund AD 9835            */
/*  ************************************************************ */
/*  Mikrocontroller:  ATMEL AVR ATmega32, 8 MHz                  */
/*                                                               */
/*  Compiler:         GCC (GNU AVR C-Compiler)                   */
/*  Author:           Peter Rachow  (DK7IH)                      */
/*  Last update:      2014-07-01                                   */
/*****************************************************************/
/*    PORTBELEGUNG    */
// LCD
// RS      = PB6
// E       = PB7
// D4...D7 = PD4..PD7
//
// SPI
// FSYNC    = PB0
// SDATA:   = PB1
// SCLK:    = PB2
//
// VFO SET = PC5
// TUNE UP= PD2
// TUNE DOWN= PD3
// Tuning Step = PC3
// VBat = PC0
/**********************/
#define F_CPU 8000000
#define MAXSHIFT 10
#define MAXVFO 7
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#define SCLOCK 8 //Systemtakt in MHz
#define AD9835INIT 1 //AD9835 wird vollständig mit Freqeunz initalisiert
#define AD9835UPDATE 0 //AD9835 wird nur "upgedated"
void wait_ms(int);
//Timer 1
unsigned long runsecs = 0;
int main(void);
/*******************/
//       SPI
/*******************/
//Belegung
//FSYNC: PB0 (1)
//SCLK: PB1 (2)
//SDATA: PB2 (4)
void spi_start(void);
void spi_send_bit(int);
void spi_send_byte(unsigned int);
void spi_send_word(unsigned int);
void spi_stop(void);
void set_frequency(unsigned long, unsigned long, int);
/***************/
/* LCD-Display */
/***************/
//Daten: PD4..PD7
//E: PC0
//RS: PC1
#define LCD_INST 0x00
#define LCD_DATA 0x01
void lcd_write(char, unsigned char, int);
void set_rs(char);
void set_e(char);
void lcd_init(void);
void lcd_cls(void);
void lcd_linecls(int, int);
void lcd_putchar(int, int, unsigned char);
void lcd_putstring(int, int, char*);
int lcd_putnumber(int, int, long, int, int, char, char);
void lcd_display_test(void);
//****************
//      ADC
//****************
#define ADWAITSTATE 3
int get_adc(int);
//EEPROM
void savefreq(int, unsigned long);
unsigned long loadfreq(int vfo_num);
//SLEEPMODE
unsigned long idlesecs = 0;
void save_cur_vfo(int);
int load_cur_vfo(void);
void save_cur_vfo(int vfo_num)
{
    while(!eeprom_is_ready());
    eeprom_write_byte((uint8_t*)511, vfo_num);
}
int load_cur_vfo(void)
{
    int lvfo = eeprom_read_byte((uint8_t*)511);
    if(lvfo < 0 || lvfo > MAXVFO)
    {
        return 0;
    }
    else
    {
        return lvfo;
    }
}
void savefreq(int vfo_num, unsigned long num)
{
    unsigned int hiword, loword;
    unsigned char hmsb, lmsb, hlsb, llsb;
    int start_adr = vfo_num * 4;
    hiword = num / 65536;
    loword = num - hiword * 65536;
    hmsb = hiword / 256;
    hlsb = hiword - hmsb * 256;
    lmsb = loword / 256;
    llsb = loword - lmsb * 256;
    while(!eeprom_is_ready());
    eeprom_write_byte((uint8_t*)start_adr, hmsb);
    while(!eeprom_is_ready());
    eeprom_write_byte((uint8_t*)start_adr + 1, hlsb);
    while(!eeprom_is_ready());
    eeprom_write_byte((uint8_t*)start_adr + 2, lmsb);
    while(!eeprom_is_ready());
    eeprom_write_byte((uint8_t*)start_adr + 3, llsb);
}
unsigned long loadfreq(int vfo_num)
{
    unsigned long num2;
    unsigned char hmsb, lmsb, hlsb, llsb;
    int start_adr = vfo_num * 4;
    hmsb = eeprom_read_byte((uint8_t*)start_adr);
    hlsb = eeprom_read_byte((uint8_t*)start_adr + 1);
    lmsb = eeprom_read_byte((uint8_t*)start_adr + 2);
    llsb = eeprom_read_byte((uint8_t*)start_adr + 3);
    num2 = (unsigned long) 16777216 * hmsb + 65536 * hlsb + (unsigned int) 256 * lmsb + llsb;
    if(num2 >= 13900000 && num2 <= 14380000)
    {
        return num2;
    }
    else
    {
        return 1415000;
    }
}
//************
//    SPI
//************
void spi_start(void)
{
    //FSYNC lo
    PORTB &= ~(1); // Bit PB0 löschen
}
void spi_stop(void)
{
    //FSYNC hi
    PORTB |= 1; // Bit PB0 setzen
}
void spi_send_bit(int sbit)
{
    //Bit setzen oder löschen
    if(sbit)
    {
        PORTB |= 2;  //SDATA Bit PB1 setzen
    }
    else
    {
        PORTB &= ~(2);  //SDATA Bit PB1 löschen
    }
    //SCLK hi
    PORTB |= 4;  //Bit PB2 setzen
    //SCLK lo
    PORTB &= ~(4);  //Bit PB2 löschen
}
void spi_send_byte(unsigned int sbyte)
{
    int t1, x = 128;
    for(t1 = 0; t1 < 8; t1++)
    {
        spi_send_bit(sbyte & x);
        x = x >> 1;
    }
    PORTB |= 2;  //PB1 SDATA hi
}
void spi_send_word(unsigned int sbyte)
{
    unsigned int t1, x = 32768;
    for(t1 = 0; t1 < 16; t1++)
    {
        spi_send_bit(sbyte & x);
        x = x >> 1;
    }
    PORTB |= 2; //PB1 SDATA hi
}
/* Wartezeit in Millisekunden */
void wait_ms(int ms)
{
    int t1, t2;
    for(t1 = 0; t1 < ms; t1++)
    for(t2 = 0; t2 < 137 * SCLOCK; t2++)
    asm volatile ("nop" ::);
}
/**************************************/
/* Funktionen und Prozeduren fuer LCD */
/**************************************/
//Anschlussbelegeung am uC:
//LCD-Data: PD0..PD4
//E: PC0
//RS: PC1
/* Ein Byte (Befehl bzw. Zeichen) zum Display senden */
void lcd_write(char lcdmode, unsigned char value, int waitcycles)
{
    int x = 16, t1;
    set_e(0);
    if(!lcdmode)
    set_rs(0);    /* RS=0 => Befehl */
    else
    set_rs(1);    /* RS=1 => Zeichen */
    _delay_ms(waitcycles * 2);
    set_e(1);
    //PORTD = (value & 0xF0);
    /* Hi nibble */
    for(t1 = 0; t1 < 4; t1++)
    {
        if(value & x)
        {
            PORTD |= x;              // Bit setzen
        }
        else
        {
            PORTD &= ~(x);          // Bit löschen
        }
        x *= 2;
    }
    set_e(0);
    x = 16;
    set_e(1);
    /* Lo nibble */
    for(t1 = 0; t1 < 4; t1++)
    {
        if((value & 0x0F) * 16 & x)
        {
            PORTD |= x;              // Bit setzen
        }
        else
        {
            PORTD &= ~(x);          // Bit löschen
        }
        x *= 2;
    }
    set_e(0);
}
/* RS setzen */
void set_rs(char status) /* PORT PB6  */
{
    if(status)
    {
        PORTB |= 64;
    }
    else
    {
        PORTB &= ~(64);
    }
}
/* E setzen */
void set_e(char status)  /* PORT PB7*/
{
    if(status)
    {
        PORTB |= 128;
    }
    else
    {
        PORTB &= ~(128);
    }
}
/* Ein Zeichen (Char) zum Display senden, dieses in */
/* Zeile row und Spalte col positionieren           */
void lcd_putchar(int row, int col, unsigned char ch)
{
    lcd_write(LCD_INST, col + 128 + row * 0x40, 1);
    lcd_write(LCD_DATA, ch, 1);
}
/* Eine Zeichenkette direkt in das LCD schreiben */
/* Parameter: Startposition, Zeile und Pointer   */
void lcd_putstring(int row, int col, char *s)
{
    unsigned char t1;
    for(t1 = col; *(s); t1++)
    {
        lcd_putchar(row, t1, *(s++));
    }
}
/* Display loeschen */
void lcd_cls(void)
{
    lcd_write(LCD_INST, 1, 5);
}
/* Display loeschen (eine Zeile) */
void lcd_linecls(int displine, int chars)
{
    unsigned char t1;
    for(t1 = 0; t1 <= chars; t1++)
    lcd_putchar(displine, t1, 32);
}
/* LCD-Display initialisieren */
void lcd_init(void)
{
    /* Grundeinstellungen: 2 Zeilen, 5x7 Matrix, 4 Bit */
    lcd_write(LCD_INST, 40, 5);
    lcd_write(LCD_INST, 40, 5);
    lcd_write(LCD_INST, 40, 5);
    //MAtrix 5*7
    lcd_write(LCD_INST, 8, 5);
    /* Display on, Cursor off, Blink off */
    lcd_write(LCD_INST, 12, 5);
    /* Entrymode !cursoincrease + !displayshifted */
    lcd_write(LCD_INST, 4, 5);
    //4-Bit-Mode
    lcd_write(LCD_INST, 2, 5);
    lcd_cls();
}
/* Eine n-stellige Zahl direkt in das LCD schreiben */
/* Parameter: Startposition und Zeile; Zahl,        */
/* darzustellende Ziffern, Position des Dezimalpunktes, (l)links- oder (r)echtsbuendig */
int lcd_putnumber(int row, int col, long num, int digits, int dec, char orientation, char showplussign)
{
    char cl = col, minusflag = 0;
    unsigned char cdigit[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, digitcnt = 0;
    long t1, t2, n = num, r, x = 1;
    if(num < 0)
    {
        minusflag = 1;
        n *= -1;
    }
    /* Stellenzahl automatisch bestimmen */
    if(digits == -1)
    {
        for(t1 = 1; t1 < 10 && (n / x); t1++)
        x *= 10;
        digits = t1 - 1;
    }
    if(!digits)
    digits = 1;
    for(t1 = digits - 1; t1 >= 0; t1--)
    {
        x = 1;
        for(t2 = 0; t2 < t1; t2++)
        x *= 10;
        r = n / x;
        cdigit[digitcnt++] = r + 48;
        if(t1 == dec)
        cdigit[digitcnt++] = 46;
        n -= r * x;
    }
    digitcnt--;
    t1 = 0;
    /* Ausgabe */
    switch(orientation)
    {
        case 'l':
        cl = col;
        if(minusflag)
        {
            lcd_putchar(row, cl++, '-');
            digitcnt++;
        }
        else
        {
            if(showplussign)
            {
                lcd_putchar(row, cl++, '+');
                digitcnt++;
            }
        }
        while(cl <= col + digitcnt)                       /* Linksbuendig */
        lcd_putchar(row, cl++, cdigit[t1++]);
        break;
        case 'r':
        t1 = digitcnt;                              /* Rechtsbuendig */
        for(cl = col; t1 >= 0; cl--)
        lcd_putchar(row, cl, cdigit[t1--]);
        if(minusflag)
        lcd_putchar(row, --cl, '-');
    }
    if(dec == -1)
    return digits;
    else
    return digits + 1;
}
void set_frequency(unsigned long freq, unsigned long ifrequency, int ad9835fullinit)
{
    unsigned long fxtal = 50000450;  //fQuarz in MHz  0030 double
    //double fxtal = 5000045;
    double fword0;
    unsigned long fword1;
    unsigned long hiword, loword;
    unsigned char hmsb, lmsb, hlsb, llsb;
    fword0 = (double) (freq - ifrequency) / fxtal;
    fword1 = (unsigned long) (fword0 * 0xFFFFFFFF);
    //Aufspalten der 32 Bit in 2 * 16 Bit
    hiword = (unsigned long) fword1 / 65536;
    loword = (unsigned long) fword1 - hiword * 65536;
    //Aufspalten der 1. 16 Bit in 2 * 8 Bit
    hmsb = hiword / 256;
    lmsb = hiword - hmsb * 256;
    //Aufspalten der 2. 16 Bit in 2 * 8 Bit
    hlsb = loword / 256;
    llsb = loword - hlsb * 256;
    if(ad9835fullinit)
    {
        //Initialisierung, AD9835 in Sleepmode setzen
        spi_start();
        spi_send_word(0xF800);
        spi_stop();
    }
    //Senden der 4 * 16 Bit
    spi_start();
    spi_send_word(0x33 * 0x100 + hmsb);
    spi_stop();
    spi_start();
    spi_send_word(0x22 * 0x100 + lmsb);
    spi_stop();
    spi_start();
    spi_send_word(0x31 * 0x100 + hlsb);
    spi_stop();
    spi_start();
    spi_send_word(0x20 * 0x100 + llsb);
    spi_stop();
    //Sequenzende
    spi_start();
    if(ad9835fullinit)
    {
        //AD9835 aus Sleepmode wecken
        spi_send_word(0xC000);
    }
    else
    {
        //AD9835 Daten übertragen ohne volle Initialisierung
        spi_send_word(0x8000);
    }
    spi_stop();
    //Frequenz anzeigen
    //lcd_putnumber(0, 0, freq, -1, 2, 'l', 0);
    lcd_putnumber(0, 0, freq, -1, -1, 'l', 0);
}
ISR(TIMER1_OVF_vect)          // Timer1 Überlauf
{
    runsecs++;
    TCNT1 = 57724;
}
ISR(INT0_vect)
{
}
ISR(INT1_vect)
{
}
//***************************************************
//                      ADC
//***************************************************
int get_adc(int adcmode)
{
    int adc_val = 0;
    ADMUX = (ADMUX &~(0x1F)) | (adcmode & 0x1F);     // Kanal adcmode aktivieren PA0=TUNE
    wait_ms(ADWAITSTATE);
    ADCSRA |= (1<<ADSC);
    wait_ms(ADWAITSTATE);
    adc_val = ADCL;
    adc_val += ADCH * 256;
    while(ADCSRA & (1<<ADSC));
    return adc_val;
}
int main()
{
    unsigned long freq1;  //Sendefrequenz in 10 Hz
    unsigned long freq_tmp;
    unsigned long vfo[MAXVFO + 1] = {14150000, 14100000, 14200000, 14300000, 14150000, 14000000, 14270000, 14280000}; //VFO A, B, C, D, E, F, STX, SRX
    char *vfo_str[MAXVFO + 1] = {"VFOA", "VFOB", "VFOC", "VFOD", "VFOE", "VFOF", "SPRX", "SPTX"};
    unsigned int  cur_freq_shift = 2; //Frequenzschritt beim Abstimmen
    unsigned int freq_shift[MAXSHIFT + 1] = {1, 5, 10, 20, 50, 100, 250, 500, 1000, 5000, 10};
    char *freq_shift_str[MAXSHIFT + 1] = {"  1", "  5", " 10", " 20", " 50", "100", "250", "500", " 1k", " 5k", "SCN"};
    int scan_mode = 0;
    int on_air = 0;
    int vfo_cnt = 0, vfo_cnt_old = 0, ok;
    unsigned long interfreq = 9832000; //Zwischenfrequenz in 10Hz
    unsigned int adc_val;
    unsigned long runsecsold = 0;
    unsigned long runsecsold2 = 0;
    unsigned long runsecsold3 = 0;
    char displayed = 0;
    //double voltage1;
    unsigned long voltage2;
    int t1;
    /* Ports einrichten */
    /* OUTPUT */
    DDRB = 0xC7; //SPI (PB0..PB2) und und LCD RS und E an PB6 und PB7
    DDRD = 0xF0; //LCD (Daten) an PD4...PD7
    /*Input*/
    PORTD = 0x0F; //Pull-Up-Widerstand u. a. an PD2 und PD3 aktivieren
    //PD2 = Tune up
    //PD3 = Tune down
    PORTC = 0x3E; //Pull-Up-Widerstand an PC1..PC5 aktivieren
    // PC2 = TX Indicator
    // PC3 =
    // PC4 = SLEEP
    // PC5 = VFO Select
    //Display
    lcd_init();
    wait_ms(50);
    //Watchdog abschalten
    WDTCR = 0;
    WDTCR = 0;
    //ADC initialisieren
    ADMUX = (1<<REFS0);     // Referenz = AVCC
    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADEN); //Frequenzvorteiler 64 u. //ADC einschalten
    ADCSRA |= (1<<ADSC); //Eine Wandlung vornehmen
    while (ADCSRA & (1<<ADSC)); //Eine Wandlung abwarten
    adc_val = ADCL;
    adc_val += ADCH * 256;   //Wert auslesen
    adc_val = 0;
    //Timer 1
    TCCR1A = 0;                      // normal mode, keine PWM Ausgänge
    TCCR1B = (1<<CS12) + (1<<CS10) ;   // start Timer mit Systemtakt, Prescaler = /1024
    //Auslösung des Overflow alle Sekunde sec.
    TIMSK = (1<<TOIE1);   // overflow aktivieren.
    TCNT1 = 57724;        //Startwert für Sekundentakt
    //4 VFO Frequenzen aus EEPROM laden, wenn vorhanden
    for(t1 = 0; t1 <= MAXVFO; t1++)
    {
        freq_tmp = loadfreq(t1);
        if(freq_tmp > 13000000)
        {
            vfo[t1] = freq_tmp;
        }
    }
    vfo_cnt = load_cur_vfo();
    freq1 = vfo[vfo_cnt];
    set_frequency(freq1, interfreq, AD9835UPDATE);
    set_frequency(freq1, interfreq, AD9835INIT);
    lcd_putstring(1, 0, vfo_str[vfo_cnt]);
    lcd_putstring(1, 5, "  ");
    lcd_putstring(1, 5, freq_shift_str[cur_freq_shift]);
    runsecsold2 = runsecs;
    idlesecs = runsecs;
    sei();
    for(;;)
    {
        //SPLIT-Betrieb
        if(!(PINC & (1<<PINC2))) //TX indicator
        {
            if(vfo_cnt == 6)
            {
                if(!on_air)
                {
                    set_frequency(vfo[7], interfreq, AD9835UPDATE);
                    on_air = 1;
                }
            }
        }
        else
        {
            if(on_air)
            {
                set_frequency(vfo[6], interfreq, AD9835UPDATE);
                on_air = 0;
            }
        }
        if(!(PINC & (1<<PINC3))) //VFO-Select
        {
            //Aktuelle Frequenz speichern
            freq_tmp = freq1;
            vfo_cnt_old = vfo_cnt; //Aktuellen VFO speichern
            lcd_putstring(1, 0, "        ");
            while(!(PINC & (1<<PINC3))); //Warten bis Taste losgelassen
            runsecsold = runsecs;
            while(runsecsold + 2 >= runsecs)
            {
                //Aktuellen VFO anzeigen
                lcd_putstring(1, 0, vfo_str[vfo_cnt]);
                //Frequenz anzeigen
                lcd_putnumber(0, 0, vfo[vfo_cnt], -1, -1, 'l', 0);
                if(!(PINC & (1<<PINC3))) //Taste gedrückt
                {
                    runsecsold = runsecs; //Zeit zurücksetzen
                    if(vfo_cnt < MAXVFO)
                    {
                        vfo_cnt++;
                    }
                    else
                    {
                        vfo_cnt = 0;
                    }
                    //Frequenz setzen
                    set_frequency(vfo[vfo_cnt], interfreq, AD9835UPDATE);
                    while(!(PINC & (1<<PINC3))); //Warten bis Taste losgelassen
                }
            } //Zeit abgelaufen
            save_cur_vfo(vfo_cnt);
            //VFO x mit aktueller Frequenz belegen?
            lcd_cls();
            lcd_putnumber(0, 0, freq_tmp, -1, -1, 'l', 0);
            lcd_putstring(1, 0, "Save");
            lcd_putchar(1, 5, vfo_cnt + 65);
            lcd_putstring(1, 6, "?");
            runsecsold = runsecs;
            ok = 0;
            while(runsecsold + 2 >= runsecs) //2 sec. Zeit zum Bestätigen geben
            {
                if(!(PINC & (1<<PINC3))) //Bestätigt
                {
                    ok = 1;
                    runsecsold = 0;
                }
                else
                {
                    lcd_putnumber(1, 7, runsecsold + 2 - runsecs, -1, -1, 'l', 0);
                }
            }
            lcd_cls();
            if(ok)
            {
                //VFO neu setzen UND Frequenz einstellen
                vfo[vfo_cnt] = freq_tmp;
                lcd_putnumber(0, 0, freq_tmp, -1, -1, 'l', 0);
                lcd_putstring(1, 0, "Saved");
                lcd_putchar(1, 6, vfo_cnt + 65);
                lcd_putchar(1, 7, '.');
                savefreq(vfo_cnt, freq_tmp);
            }
            else  //Nur VFO wechseln mit bereits gegebener Frequenz
            {
                freq1 = vfo[vfo_cnt];
            }
            lcd_cls();
            set_frequency(freq1, interfreq, AD9835UPDATE);
            lcd_putstring(1, 0, vfo_str[vfo_cnt]);
            //Schrittweite anzeigen
            lcd_putstring(1, 5, "  ");
            lcd_putstring(1, 5, freq_shift_str[cur_freq_shift]);
            idlesecs = runsecs;
        }
        if(!(PIND & (1<<PIND2))) //TUNE UP
        {
            freq1 += freq_shift[cur_freq_shift];
            set_frequency(freq1, interfreq, AD9835UPDATE);
            runsecsold3 = runsecs;
            idlesecs = runsecs;
            if(cur_freq_shift == 10)
            {
                scan_mode = 1;
            }
        }
        if(!(PIND & (1<<PIND3))) //TUNE DOWN
        {
            freq1 -= freq_shift[cur_freq_shift];
            set_frequency(freq1, interfreq, AD9835UPDATE);
            runsecsold3 = runsecs;
            idlesecs = runsecs;
            if(cur_freq_shift == 10)
            {
                scan_mode = 2;
            }
        }
        if(scan_mode)
        {
            switch(scan_mode)
            {
                case 1: freq1 += 10;
                set_frequency(freq1, interfreq, AD9835UPDATE);
                break;
                case 2: freq1 -= 10;
                set_frequency(freq1, interfreq, AD9835UPDATE);
                break;
            }
        }
        //Schrittweite setzen und ggf. anzeigen
        //Set Frequency-Shift for tuning
        if(!(PINC & (1<<PINC5))) //Frequency-Shift when tuning
        {
            runsecsold = runsecs;
            runsecsold3 = runsecs;
            if(cur_freq_shift < MAXSHIFT)
            {
                cur_freq_shift++;
            }
            else
            {
                cur_freq_shift = 0;
            }
            while(!(PINC & (1<<PINC5)));
            lcd_putstring(1, 5, "  ");
            lcd_putstring(1, 5, freq_shift_str[cur_freq_shift]);
            idlesecs = runsecs;
            //Evtl. Scan abbrechen
            if(scan_mode)
            {
                scan_mode = 0;
            }
        }
        //Shift nach 3 Sekunden, in denen nicht abgestimmt wurde, auf 10 Hz einstellen
        if(runsecsold3 + 3 < runsecs && cur_freq_shift != 2)
        {
            cur_freq_shift = 2;
            //Schrittweite anzeigen
            lcd_putstring(1, 5, "   ");
            lcd_putstring(1, 5, freq_shift_str[cur_freq_shift]);
            runsecsold3 = runsecs;
        }
        //VFO anzeigen
        if(runsecs > runsecsold2 + 1 && displayed != 2)
        {
            if(displayed != 2)
            {
                lcd_putstring(1, 0, "     ");
                lcd_putstring(1, 0, vfo_str[vfo_cnt]);
                displayed = 2;
                runsecsold2 = runsecs;
            }
        }
        //Anzeige Betriebsspannung
        if(runsecs > runsecsold2 + 3 && displayed != 1)
        {
            //ADC abfragen (Akkuspannung)
            adc_val = get_adc(0);
            voltage2 = (unsigned long) adc_val * 5 * 32 / 1024;
            lcd_putstring(1, 0, "     ");
            lcd_putnumber(1, 0, voltage2, -1, 1, 'l', 0);
            lcd_putstring(1, 4, "V");
            runsecsold2 = runsecs;
            displayed = 1;
        }
        //In den Sleepmode schalten
        //Schrittweite auf 10Hz setzen
        if(!(PINC & (1<<PINC4)))
        {
            cur_freq_shift = 2;
            //Schrittweite anzeigen
            lcd_putstring(1, 5, "  ");
            lcd_putstring(1, 5, freq_shift_str[cur_freq_shift]);
            GICR |= (1<<INT0) | (1<<INT1);
            set_sleep_mode(SLEEP_MODE_PWR_DOWN);
            lcd_putstring(1, 0, "SLEEP!  ");
            sleep_mode();
            lcd_putstring(1, 0, "        ");
            lcd_putstring(1, 5, freq_shift_str[cur_freq_shift]);
            GICR &= ~(1<<INT0) ;
            GICR &= ~(1<<INT1) ;
            idlesecs = runsecs;
        }
    }
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *