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;
}