From df6ceb8394d26b9ef5a212d08100b1d975e01e08 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Sat, 16 Jun 2012 22:16:37 -0300 Subject: [PATCH] fw/: first version of experimental firmware --- fw/Makefile | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++ fw/antorcha.c | 60 +++++++++++++++++ fw/io.h | 53 ++++++++++++++++ fw/rf.c | 137 +++++++++++++++++++++++++++++++++++++++ fw/rf.h | 23 +++++++ fw/spi.c | 51 +++++++++++++++ fw/spi.h | 24 +++++++ fw/version.h | 23 +++++++ 8 files changed, 544 insertions(+) create mode 100644 fw/Makefile create mode 100644 fw/antorcha.c create mode 100644 fw/io.h create mode 100644 fw/rf.c create mode 100644 fw/rf.h create mode 100644 fw/spi.c create mode 100644 fw/spi.h create mode 100644 fw/version.h diff --git a/fw/Makefile b/fw/Makefile new file mode 100644 index 0000000..f05d224 --- /dev/null +++ b/fw/Makefile @@ -0,0 +1,173 @@ +# +# Makefile - Makefile of the ATUSB firmware +# +# Written 2010-2011 by Werner Almesberger +# Copyright 2010-2011 by Werner Almesberger +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + +SHELL = /bin/bash + +NAME = antorcha + +CFLAGS = -g -mmcu=$(CHIP) -DBOOT_ADDR=$(BOOT_ADDR) \ + -Wall -Wextra -Wshadow -Werror -Wno-unused-parameter \ + -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes + +CHIP=atmega168 +HOST=jlime +BOOT_ADDR=0x7000 + +AVR_PREFIX = $(BIN_PATH) avr- +CC = $(AVR_PREFIX)gcc +OBJCOPY = $(AVR_PREFIX)objcopy +#OBJDUMP = $(AVR_PREFIX)objdump +SIZE = $(AVR_PREFIX)size + +USB_ID = 20b7:1540 + +OBJS = $(NAME).o rf.o spi.o + +CFLAGS += -Iinclude + +# ----- Verbosity control ----------------------------------------------------- + +CC_normal := $(CC) +BUILD_normal := +DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG + +CC_quiet = @echo " CC " $@ && $(CC_normal) +BUILD_quiet = @echo " BUILD " $@ && $(BUILD_normal) +DEPEND_quiet = @$(DEPEND_normal) + +ifeq ($(V),1) + CC = $(CC_normal) + BUILD = $(BUILD_normal) + DEPEND = $(DEPEND_normal) +else + CC = $(CC_quiet) + BUILD = $(BUILD_quiet) + DEPEND = $(DEPEND_quiet) +endif + +# ----- Rules ----------------------------------------------------------------- + +.PHONY: all clean upload prog update version.c bindist +.PHONY: prog-app prog-read on off reset + +all: $(NAME).bin + +$(NAME).elf: $(OBJS) + $(MAKE) version.o + $(CC) $(CFLAGS) -o $@ $(OBJS) version.o + +#boot.elf: $(BOOT_OBJS) +# $(CC) $(CFLAGS) -o $@ $(BOOT_OBJS) \ +# -Wl,--section-start=.text=$(BOOT_ADDR) + +%.bin: %.elf + $(BUILD) $(OBJCOPY) -j .text -j .data -O binary $< $@ + @echo "build #`cat .version`, `ls -l $@`" + +%.hex: %.elf + $(BUILD) $(OBJCOPY) -j .text -j .data -O ihex $< $@ + $(SIZE) $@ + +# ----- Cleanup --------------------------------------------------------------- + +clean: + rm -f $(NAME).bin $(NAME).elf + rm -f $(OBJS) $(OBJS:.o=.d) + rm -f boot.hex boot.elf + rm -f $(BOOT_OBJS) $(BOOT_OBJS:.o=.d) + rm -f version.c version.d version.o + +# ----- Build version --------------------------------------------------------- + +version.c: + @if [ -f .version ]; then \ + v=`cat .version`; \ + expr $$v + 1 >.version; \ + else \ + echo 0 >.version; \ + fi + @[ -s .version ] || echo 0 >.version + @echo '/* MACHINE-GENERATED. DO NOT EDIT ! */' >version.c + @echo '#include "version.h"' >>version.c + @echo "const char *build_date = \"`date`\";" >>version.c + @echo "const uint16_t build_number = `cat .version`;" \ + >>version.c + +# ----- Dependencies ---------------------------------------------------------- + +MKDEP = \ + $(DEPEND) $< | \ + sed \ + -e 's|^$(basename $(notdir $<)).o:|$@:|' \ + -e '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \ + -e '$${g;p;}' \ + -e d >$(basename $@).d; \ + [ "$${PIPESTATUS[*]}" = "0 0" ] || \ + { rm -f $(basename $@).d; exit 1; } + +%.o: %.c + $(CC) $(CFLAGS) -Os -c $< + $(MKDEP) + +-include $(OBJS:.o=.d) + +# ----- Distribution ---------------------------------------------------------- + +BINDIST_BASE=http://downloads.qi-hardware.com/people/werner/wpan/bindist +ATUSB_BIN_NAME=atusb-`git rev-parse HEAD | cut -c 1-7`.bin + +bindist: + qippl atusb.bin wpan/bindist/$(ATUSB_BIN_NAME) + @echo $(BINDIST_BASE)/$(ATUSB_BIN_NAME) + @echo md5sum: `md5sum atusb.bin | sed 's/ .*//'` + @echo atrf-id: \ + `sed '/.*number = \(.*\);/s//#\1/p;d' version.c` \ + `sed '/.*date = "\(.*\)";/s//\1/p;d' version.c` + +# ----- Programming and device control ---------------------------------------- + +#upload: $(NAME).bin boot.hex +# scp $(NAME).bin boot.hex $(HOST): +upload: $(NAME).bin + scp $(NAME).bin $(HOST): + +# lfuse: external clock, slow start-up +# hfuse: 4 kB boot loader, reset into boot loader +# lock: allow everything but SPM to the boot loader +# Note: when trying to program 0xef, we get back 0x2f, failing +# verification. So we just program 0x2f. + +prog: + ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_antorcha -e \ + -U flash:w:antorcha.bin:r +# -U lfuse:w:0x60:m + +#prog: +# ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb -e \ +# -U flash:w:boot.hex:i \ +# -U lfuse:w:0x60:m \ +# -U hfuse:w:0xd8:m \ +# -U lock:w:0x2f:m + +prog-read: + ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb \ + -U flash:r:mcu.bin:r + +on: + ssh $(HOST) poke 0x10010318 4 + +off: + ssh $(HOST) poke 0x10010314 4 + +reset: + ssh $(HOST) poke 0x10010318 2048 + ssh $(HOST) poke 0x10010314 2048 diff --git a/fw/antorcha.c b/fw/antorcha.c new file mode 100644 index 0000000..9d36889 --- /dev/null +++ b/fw/antorcha.c @@ -0,0 +1,60 @@ +/* + * fw/main.c - Initialization of Antorcha firmware + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include + +#include "io.h" +#include "rf.h" + + +int main(void) +{ + /* Port B has two LEDs and the rest is SPI */ + PORTB = MASK(B, RF_nSS) | MASK(B, RF_nRST); + DDRB = MASK(B, RF_SCLK) | MASK(B, RF_MOSI) | MASK(B, RF_nSS) | + MASK(B, RF_nRST) | 0xc0; + + /* All port C pins drive LEDs */ + PORTC = 0; + DDRC = 0x3f; + + /* All port D pins drive LEDs */ + PORTD = 0; + DDRD = 0xff; + + /* disable pull-ups */ + MCUCR |= 1 << PUD; + + rf_init(); + + while (0) { + PORTC = 2; + PORTC = 0; + rf_send("HOLA ?", 6); + } + + while (1) { + uint8_t buf[1], got; + + do { +PORTC = 1; +PORTC = 0; +got = rf_recv(buf, 1); +} + while (!got); + +PORTC = 2; +PORTC = 0; + PORTD = buf[0]; + } +} diff --git a/fw/io.h b/fw/io.h new file mode 100644 index 0000000..7e6979f --- /dev/null +++ b/fw/io.h @@ -0,0 +1,53 @@ +/* + * fw/io.h - I/O helper macros + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef IO_H +#define IO_H + +#define LED_B8 D, 7 + +#define RF_SCLK B, 5 +#define RF_MISO B, 4 +#define RF_MOSI B, 3 +#define RF_nSS B, 2 /* called nSS in schematics */ +#define RF_IRQ B, 1 +#define RF_nRST B, 0 + +#define __SET(port, bit) PORT##port |= 1 << (bit) +#define __CLR(port, bit) PORT##port &= ~(1 << (bit)) +#define __OUT(port, bit) DDR##port |= 1 << (bit) +#define __IN(port, bit) DDR##port &= ~(1 << (bit)) +#define __PIN(port, bit) ((PIN##port >> (bit)) & 1) + +#define SET(...) __SET(__VA_ARGS__) +#define CLR(...) __CLR(__VA_ARGS__) +#define OUT(...) __OUT(__VA_ARGS__) +#define IN(...) __IN(__VA_ARGS__) +#define PIN(...) __PIN(__VA_ARGS__) + +#define __SEL_BB(v) (v) +#define __SEL_CC(v) (v) +#define __SEL_DD(v) (v) + +#if 0 +#define __SEL_BC(v) (0) +#define __SEL_BD(v) (0) +#define __SEL_CB(v) (0) +#define __SEL_CD(v) (0) +#define __SEL_DB(v) (0) +#define __SEL_DC(v) (0) +#endif + +#define __MASK(sel, port, bit) __SEL_##sel##port(1 << (bit)) +#define MASK(...) __MASK(__VA_ARGS__) + +#endif /* IO_H */ diff --git a/fw/rf.c b/fw/rf.c new file mode 100644 index 0000000..ed5d819 --- /dev/null +++ b/fw/rf.c @@ -0,0 +1,137 @@ +/* + * fw/rf.c - RF interface + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include + +#include +#define F_CPU 8000000UL +#include + +#include "at86rf230.h" +#include "io.h" +#include "spi.h" +#include "rf.h" + + +/* + * According to IEEE 802.15.4-2003 section E.2.6, channel 15 is the only + * channel that falls into the 802.11 guard bands in North America an Europe. + */ + +#define DEFAULT_CHAN 15 /* channel 15, 2425 MHz */ + +/* + * Transmit power, dBm. IEEE 802.15.4-2003 section E.3.1.3 specifies a transmit + * power of 0 dBm for IEEE 802.15.4. We assume an antenna gain of 3 dB or + * better. + */ + +#define DEFAULT_POWER -3.2 /* transmit power, dBm */ + + +static uint8_t reg_read(uint8_t reg) +{ + uint8_t value; + + spi_begin(); + spi_io(AT86RF230_REG_READ | reg); + value = spi_io(0); + spi_end(); + + return value; +} + + +static void reg_write(uint8_t reg, uint8_t value) +{ + spi_begin(); + spi_io(AT86RF230_REG_WRITE | reg); + spi_io(value); + spi_end(); +} + +void rf_init(void) +{ + spi_init(); + CLR(RF_nRST); + _delay_us(10); /* tTR10 = 625 ns */ + SET(RF_nRST); + _delay_us(40); /* tTR13 = 37 us */ + + reg_write(REG_TRX_STATE, TRX_CMD_TRX_OFF); + _delay_us(40); /* tTR13 = 37 us */ + reg_write(REG_PHY_CC_CCA, DEFAULT_CHAN); + + reg_write(REG_TRX_STATE, TRX_CMD_RX_ON); + _delay_us(200); /* tTR19(max) = 166 us */ + + //reg_write(REG_IRQ_MASK, IRQ_TRX_END); + reg_write(REG_IRQ_MASK, 0xff); + reg_read(REG_IRQ_STATUS); +} + + +void rf_send(const void *buf, uint8_t size) +{ + uint8_t i; + + reg_write(REG_TRX_STATE, TRX_CMD_PLL_ON); + _delay_us(1); /* tTR9 = 1 us */ + + spi_begin(); + spi_io(AT86RF230_BUF_WRITE); + spi_io(size+2); /* CRC */ + for (i = 0; i != size; i++) + spi_io(((const uint8_t *) buf)[i]); + spi_end(); + + reg_read(REG_IRQ_STATUS); + + reg_write(REG_TRX_STATE, TRX_CMD_TX_START); + _delay_us(16); /* tTR10 = 16 us */ + + while (!(reg_read(REG_IRQ_STATUS) & IRQ_TRX_END)) { + PORTC = 1; + PORTC = 0; + } + + reg_write(REG_TRX_STATE, TRX_CMD_RX_ON); + _delay_us(1); /* tTR8 = 1 us */ +} + + +uint8_t rf_recv(void *buf, uint8_t size) +{ + uint8_t irq, len, i; + + irq = reg_read(REG_IRQ_STATUS); + if (!(irq & IRQ_TRX_END)) + return 0; + + if (!(reg_read(REG_PHY_RSSI) & RX_CRC_VALID)) + return 0; + + spi_begin(); + spi_io(AT86RF230_BUF_READ); + len = spi_io(0); + if (!len || (len & 0x80)) { + spi_end(); + return 0; + } + if (size > len) + size = len; + for (i = 0; i != size; i++) + ((uint8_t *) buf)[i] = spi_io(0); + spi_end(); + return len; +} diff --git a/fw/rf.h b/fw/rf.h new file mode 100644 index 0000000..02b1d04 --- /dev/null +++ b/fw/rf.h @@ -0,0 +1,23 @@ +/* + * fw/rf.h - RF interface + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef RF_H +#define RF_H + +#include + + +void rf_init(void); +void rf_send(const void *buf, uint8_t size); +uint8_t rf_recv(void *buf, uint8_t size); + +#endif /* !RF_H */ diff --git a/fw/spi.c b/fw/spi.c new file mode 100644 index 0000000..97f0321 --- /dev/null +++ b/fw/spi.c @@ -0,0 +1,51 @@ +/* + * fw/spi.c - SPI I/O + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include + +#include "io.h" +#include "spi.h" + + +#define nSS B, 2 +#define MOSI B, 3 +#define MISO B, 4 +#define SCLK B, 8 + + +void spi_init(void) +{ + /* Enable, SPI mode 0, master, MSB first, fosc/4 */ + SPCR = (1 << SPE) | (1 << MSTR); +} + + +void spi_begin(void) +{ + CLR(nSS); +} + + +uint8_t spi_io(uint8_t v) +{ + SPDR = v; + while (!(SPSR & (1 << SPIF))); + return SPDR; +} + + +void spi_end(void) +{ + SET(nSS); +} diff --git a/fw/spi.h b/fw/spi.h new file mode 100644 index 0000000..d07d592 --- /dev/null +++ b/fw/spi.h @@ -0,0 +1,24 @@ +/* + * fw/spi.h - SPI I/O + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef SPI_H +#define SPI_H + +#include + + +void spi_init(void); +void spi_begin(void); +uint8_t spi_io(uint8_t v); +void spi_end(void); + +#endif /* !SPI_H */ diff --git a/fw/version.h b/fw/version.h new file mode 100644 index 0000000..8fd6a2c --- /dev/null +++ b/fw/version.h @@ -0,0 +1,23 @@ +/* + * fw/version.h - Automatically generated version string + * + * Written 2008, 2011 by Werner Almesberger + * Copyright 2008, 2011 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef VERSION_H +#define VERSION_H + +#include + + +extern const char *build_date; +extern const uint16_t build_number; + +#endif /* !VERSION_H */