From ff29bc2b3dbad7885497cfd9aa2b3aa98cc4ebb0 Mon Sep 17 00:00:00 2001 From: simimeie Date: Sat, 24 Jul 2010 20:55:48 +0000 Subject: [PATCH] - add eepromdata.h - add rfm12 module to makefile - preliminary initialization for rfm12 - console command 'rfstatus' - display of last reset reason moved to console (so it displays properly now). --- Makefile | 4 ++-- console.c | 56 ++++++++++++++++++++++++++++++++++++-------- eepromdata.h | 18 ++++++++++++++ main.c | 32 ++++++------------------- rfm12.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-------- rfm12.h | 4 +++- 6 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 eepromdata.h diff --git a/Makefile b/Makefile index 5de17a8..acb33a2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 2010/06/27 22:19:15 simimeie Exp $ +# $Id: Makefile,v 1.4 2010/07/24 20:56:28 simimeie Exp $ # Makefile for HaWo Moodlight CC = avr-gcc @@ -27,7 +27,7 @@ CPUFREQ = 8000000UL # desired baudrate of serial debug console BAUDRATE = 9600UL -SRCS = console.c ledpwm.c ircontrol.c timers.c main.c +SRCS = console.c ledframing.c ledpwm.c ircontrol.c timers.c main.c rfm12.c PROG = moodlight # compiler flags diff --git a/console.c b/console.c index 87f2043..8dff9f4 100644 --- a/console.c +++ b/console.c @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.3 2010/06/30 19:40:49 simimeie Exp $ +/* $Id: console.c,v 1.4 2010/07/24 20:55:48 simimeie Exp $ * Functions for a serial console. */ @@ -6,11 +6,13 @@ #include #include #include +#include #include #include #include #include "console.h" #include "ledpwm.h" +#include "rfm12.h" /* PD0 is RXD, PD1 is TXD, but we don't need to address them manually */ @@ -38,6 +40,19 @@ static prog_uint8_t WELCOMEMSG[] = "\r\n"\ "\r\nSoftware Version 0.1, Compiled " __DATE__ " " __TIME__; static prog_uint8_t PROMPT[] = "\r\nroot@moodlight# "; +uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); + +/* This is needed to recover from a watchdog reset, as the watchdog + * stays active after the reset. + * The variable is just to make the reason of the last reset accessible + * later. */ +void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3"))); +void get_mcusr(void) { + mcusr_mirror = MCUSR; + MCUSR = 0; + wdt_disable(); +} + /* Handler for TXC (TX Complete) IRQ */ ISR(USART_TX_vect) { if (outputhead == outputtail) { /* Nothing more to send! */ @@ -177,6 +192,19 @@ void console_init(void) { /* Enable Send and Receive and IRQs */ UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(TXCIE0) | _BV(RXCIE0); console_printpgm_noirq_P(WELCOMEMSG); + console_printpgm_noirq_P(PSTR("\r\nNOTE: last reset was from")); + if (mcusr_mirror & _BV(WDRF)) { + console_printpgm_noirq_P(PSTR(" WatchdogTimer")); + } + if (mcusr_mirror & _BV(BORF)) { + console_printpgm_noirq_P(PSTR(" Brownout")); + } + if (mcusr_mirror & _BV(EXTRF)) { + console_printpgm_noirq_P(PSTR(" ExternalReset")); + } + if (mcusr_mirror & _BV(PORF)) { + console_printpgm_noirq_P(PSTR(" PowerOn")); + } console_printpgm_noirq_P(PROMPT); return; } @@ -263,6 +291,7 @@ ISR(USART_RX_vect) { console_printpgm_noirq_P(PSTR("\r\n showpins [x] shows the avrs inputpins")); console_printpgm_noirq_P(PSTR("\r\n status show status / counters")); console_printpgm_noirq_P(PSTR("\r\n [rgb] n sets the brightness of the red / green / blue LED to n")); + console_printpgm_noirq_P(PSTR("\r\n rfstatus show RFM12 status")); /* console_printpgm_noirq_P(PSTR("\r\n save saves settings to EEPROM")); */ } else if (strcmp_P(inputbuf, PSTR("motd")) == 0) { console_printpgm_noirq_P(WELCOMEMSG); @@ -329,28 +358,27 @@ ISR(USART_RX_vect) { console_printhex8_noirq(ledpwm_bl); console_printpgm_noirq_P(PSTR(", brightness = ")); console_printhex8_noirq(ledpwm_bri); - /*console_printpgm_noirq_P(CRLF);*/ } else if (strncmp_P(inputbuf, PSTR("r "), 2) == 0) { uint8_t v; v = strtoul(&inputbuf[2], NULL, 0); ledpwm_re = v; ledpwm_setled(LEDPWM_REDLED, (((uint16_t)ledpwm_re * ledpwm_bri) / 255)); - console_printpgm_P(PSTR("RED value set to 0x")); - console_printhex8(v); + console_printpgm_noirq_P(PSTR("RED value set to 0x")); + console_printhex8_noirq(v); } else if (strncmp_P(inputbuf, PSTR("g "), 2) == 0) { uint8_t v; v = strtoul(&inputbuf[2], NULL, 0); ledpwm_gr = v; ledpwm_setled(LEDPWM_GREENLED, (((uint16_t)ledpwm_gr * ledpwm_bri) / 255)); - console_printpgm_P(PSTR("GREEN value set to 0x")); - console_printhex8(v); + console_printpgm_noirq_P(PSTR("GREEN value set to 0x")); + console_printhex8_noirq(v); } else if (strncmp_P(inputbuf, PSTR("b "), 2) == 0) { uint8_t v; v = strtoul(&inputbuf[2], NULL, 0); ledpwm_bl = v; ledpwm_setled(LEDPWM_BLUELED, (((uint16_t)ledpwm_bl * ledpwm_bri) / 255)); - console_printpgm_P(PSTR("BLUE value set to 0x")); - console_printhex8(v); + console_printpgm_noirq_P(PSTR("BLUE value set to 0x")); + console_printhex8_noirq(v); } else if (strncmp_P(inputbuf, PSTR("bri "), 2) == 0) { uint8_t v; v = strtoul(&inputbuf[4], NULL, 0); @@ -358,8 +386,16 @@ ISR(USART_RX_vect) { ledpwm_setled(LEDPWM_REDLED, (((uint16_t)ledpwm_re * ledpwm_bri) / 255)); ledpwm_setled(LEDPWM_GREENLED, (((uint16_t)ledpwm_gr * ledpwm_bri) / 255)); ledpwm_setled(LEDPWM_BLUELED, (((uint16_t)ledpwm_bl * ledpwm_bri) / 255)); - console_printpgm_P(PSTR("brightness set to 0x")); - console_printhex8(v); + console_printpgm_noirq_P(PSTR("brightness set to 0x")); + console_printhex8_noirq(v); + } else if (strcmp_P(inputbuf, PSTR("rfstatus")) == 0) { + uint32_t st; + st = rfm12_readstatus(); + console_printpgm_noirq_P(PSTR("rfm12 status is ")); + console_printhex8_noirq(st >> 24); + console_printhex8_noirq(st >> 16); + console_printhex8_noirq(st >> 8); + console_printhex8_noirq(st >> 0); #ifdef JOKECMDS } else if (strncmp_P(inputbuf, PSTR("ls"), 2) == 0) { console_printpgm_noirq_P(PSTR("Total 4711\r\n")); diff --git a/eepromdata.h b/eepromdata.h new file mode 100644 index 0000000..96e4268 --- /dev/null +++ b/eepromdata.h @@ -0,0 +1,18 @@ +/* $Id: eepromdata.h,v 1.1 2010/07/24 20:55:48 simimeie Exp $ + * Defines the contents of the EEPROM. + * The EEPROM contains settings and can also contain "programs" for the LEDs. + * Usually you only need to reprogram the eeprom after changing values here, + * unless compiler version changed and thus the data got reordered. + */ + +#define EEPROM __attribute__ ((section (".eeprom"))) + +/* The default brightness */ +uint8_t EEPROM ee_defledbrightness = 128; + +/* All the rest of the memory is used for storing LED "programs". + * For the following to work, needs to be included before this file - + * which usually should be the case anyways. + * Formula is: E2END + 1 - (number of bytes used by other stuff in EEPROM) */ +uint8_t EEPROM ee_ledprograms[E2END + 1 - 1]; + diff --git a/main.c b/main.c index 8f6f34f..3e66f1a 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.6 2010/07/10 07:32:08 simimeie Exp $ +/* $Id: main.c,v 1.7 2010/07/24 20:55:48 simimeie Exp $ * Main file for the HaWo moodlight. * This is the main file that glues it all together. It also contains all * functionality that is too small to require an extra file. @@ -19,20 +19,9 @@ #include "ledpwm.h" #include "ircontrol.h" #include "timers.h" -/* #include "eepromdata.h" */ - -uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); - -/* This is needed to recover from a watchdog reset, as the watchdog - * stays active after the reset. - * The variable is just to make the reason of the last reset accessible - * later. */ -void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3"))); -void get_mcusr(void) { - mcusr_mirror = MCUSR; - MCUSR = 0; - wdt_disable(); -} +#include "ledframing.h" +#include "rfm12.h" +#include "eepromdata.h" #define IRSTATE_RED 1 #define IRSTATE_GREEN 2 @@ -44,15 +33,15 @@ int main(void) uint8_t irstate = 0; /* Load settings from EEPROM */ -#if 0 - something = eeprom_read_byte(&ee_something); -#endif /* LEDMODULE */ + ledpwm_bri = eeprom_read_byte(&ee_defledbrightness); /* Initialize stuff */ console_init(); timers_init(); ledpwm_init(); + ledframing_init(); ircontrol_init(); + rfm12_init(); wdt_enable(WDTO_2S); @@ -63,13 +52,6 @@ int main(void) /* All set up, enable interrupts and go. */ sei(); - if (mcusr_mirror & _BV(WDRF)) { - console_printpgm_P(PSTR("NOTE: last reset was from Watchdog Timer.")); - } - if (mcusr_mirror & _BV(BORF)) { - console_printpgm_P(PSTR("NOTE: last reset was from Brownout.")); - } - while (1) { /* We should never exit */ wdt_reset(); uint8_t k = ircontrol_getlastcommand(); diff --git a/rfm12.c b/rfm12.c index 01297e4..30a2a0e 100644 --- a/rfm12.c +++ b/rfm12.c @@ -1,4 +1,4 @@ -/* $Id: rfm12.c,v 1.1 2010/07/11 09:09:26 simimeie Exp $ +/* $Id: rfm12.c,v 1.2 2010/07/24 20:55:48 simimeie Exp $ * Functions for communicating with the rfm12(b) module */ @@ -14,30 +14,76 @@ /* Consequently, this SELECTS the chip */ #define spi_ss_lo() { PORTC &= (uint8_t)~_BV(0); } -static void spi_sendbyte(uint8_t v) { +/* write and (at the same time) read a word from RFM12. + * The module uses 16 bit commands and replies that are + * synchronous to the command - except for the status read. + * Note: This does not handle chip select! */ +static uint16_t rfm12_spi_wrword(uint16_t v) { + uint16_t res; /* Start transmission */ - SPDR = v; + SPDR = v >> 8; /* Wait for transmission complete */ while ((SPSR & _BV(SPIF)) == 0) { } -} - -static uint8_t spi_readbyte() { - SPDR = 0x00; /* Dummy write */ + res = (uint16_t)(SPDR) << 8; + SPDR = v & 0xff; + /* Wait for transmission complete */ while ((SPSR & _BV(SPIF)) == 0) { } - /* Return Data Register */ - return SPDR; + res |= SPDR & 0xff; + return res; +} + +void rfm12_sendcommand(uint16_t cmd) { + spi_ss_lo(); + rfm12_spi_wrword(cmd); + spi_ss_hi(); +} + +uint32_t rfm12_readstatus(void) { + uint32_t res; + spi_ss_lo(); + res = (uint32_t)rfm12_spi_wrword(0x0000) << 16; + res |= rfm12_spi_wrword(0x0000); + spi_ss_hi(); + return res; } void rfm12_init(void) { /* Set MOSI, SCK and SS output, MISO input */ - DDRB |= _BV(3) | _BV(5); + /* Frickel Alert: Also set PB2 output. It is not used, but noise on the + * pin could reset our SPI mode to slave (!!!) if it is left as input. */ + DDRB |= _BV(3) | _BV(5) | _BV(2); DDRC |= _BV(0); DDRB &= (uint8_t)~_BV(4); spi_ss_hi(); +#if (CPUFREQ <= 10000000UL) /* Enable SPI, Master, set clock rate fck/4. * This works as long as our own clockrate is below 10 MHz - because * 2.5 MHz is the maximum the rfm12b can do. */ SPCR |= _BV(SPE) | _BV(MSTR); +#else + /* For higher clock rates set fck/16. */ + SPCR |= _BV(SPE) | _BV(MSTR) | _BV(SPR0); +#endif /* CPUFREQ */ + /* Now send some initialization commands. */ + /* Mostly taken over from http://www.joachim-neu.de/post/70/rfm12b-868/ + * Seems to be mostly black magic anyways. */ + rfm12_sendcommand(0x80E7); /* EL, EF, 868band, 12.0pF */ + rfm12_sendcommand(0x8219); /* !er, !ebb, !ET, ES, EX, !eb, !ew, DC */ + /* Frequency setting: 0xAnnn; the 12 nnn-bits of value are + * calculated like this: v = ((freq / 20) - 43) * 4000 + */ + rfm12_sendcommand(0xA7BC); /* 869,900 MHz */ + rfm12_sendcommand(0xC647); /* 4.8kbps FIXME? */ + rfm12_sendcommand(0x94C0); /* VDI, FAST, 67kHz, 0dBm, -103dBm */ + rfm12_sendcommand(0xC2AC); /* AL, !ml, DIG, DQD4 */ + rfm12_sendcommand(0xCA81);//FIFO8,SYNC,!ff,DR + rfm12_sendcommand(0xCED4);//SYNC=2DD4; + rfm12_sendcommand(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN + rfm12_sendcommand(0x9820);// !mp,45kHz,MAX OUT*/ + rfm12_sendcommand(0xCC77);//OB1,OB0, LPX,!ddy,DDIT,BW0 + rfm12_sendcommand(0xE000);//NOT USE + rfm12_sendcommand(0xC800);//NOT USE + rfm12_sendcommand(0xC040);//1.66MHz,2.2V } diff --git a/rfm12.h b/rfm12.h index df96924..3873e22 100644 --- a/rfm12.h +++ b/rfm12.h @@ -1,4 +1,4 @@ -/* $Id: rfm12.h,v 1.1 2010/07/11 09:09:26 simimeie Exp $ +/* $Id: rfm12.h,v 1.2 2010/07/24 20:55:48 simimeie Exp $ * Functions for communicating with the rfm12(b) module */ @@ -6,5 +6,7 @@ #define __RFM12B_H__ void rfm12_init(void); +void rfm12_sendcommand(uint16_t cmd); +uint32_t rfm12_readstatus(void); #endif /* __RFM12B_H__ */ -- 2.25.1