add avr firmware code

This commit is contained in:
King Kévin 2015-02-21 10:32:45 +01:00
parent 1b50259948
commit 99347586bd
8 changed files with 908 additions and 0 deletions

View File

@ -18,3 +18,9 @@ decode.rb
decode the MilesTag v2 recorded transmission
avr
===
firmware for the IR grenade.
based on the TV-B-Gone firmware

80
avr/Makefile Normal file
View File

@ -0,0 +1,80 @@
# required packages
# sudo aptitude install avrdude gcc-avr avr-libc
# the program
PROG=ir-cock-grenade
# to compile
CC=avr-gcc
OBJDUMP=avr-objdump
OBJCOPY=avr-objcopy
CFLAGS=-g -Wall -O3
# the target
#DEVICE=atmega328p
DEVICE=attiny85
F_CPU=1000000
# the port to flash
#PORT=/dev/ttyUSB0
# the flasher
#PROGRAMMER=buspirate
PROGRAMMER=usbtiny
# to flash
#AVRDUDE=avrdude -p $(DEVICE) -P $(PORT) -c $(PROGRAMMER)
AVRDUDE=avrdude -p $(DEVICE) -c $(PROGRAMMER) -B 50
all: prog
prog: verify $(PROG).c
$(CC) $(CFLAGS) -I. -mmcu=$(DEVICE) -DF_CPU=$(F_CPU) -o $(PROG) $(PROG).c
$(OBJDUMP) -h -S $(PROG) > $(PROG).lst
$(OBJCOPY) -j .text -j .data -O ihex $(PROG) $(PROG).hex
# Fuse extended byte:
# 0x07 = - - - - - 1 1 1
# \-+-/
# +------ BODLEVEL 2..0 (Brown-out Detector trigger level -> disabled)
#
# Fuse high byte:
# 0xdf = 1 1 0 1 1 1 1 1
# ^ ^ ^ ^ ^ \+/ ^
# | | | | | | +---- BOOTRST (Select Reset Vector -> jump to application at start)
# | | | | | +------- BOOTSZ 1..0 (Select Boot Size -> 256 words starting at 0x3F00)
# | | | | +---------- EESAVE (preserve EEPROM on Chip Erase -> not preserved)
# | | | +-------------- WDTON (watchdog timer always on -> disable)
# | | +---------------- SPIEN (enable serial programming -> enabled)
# | +------------------ DWEN (debug wire enable -> enabled)
# +-------------------- RSTDISBL (disable external reset -> reset disabled)
#
# Fuse low byte:
# 0x62 = 0 1 1 0 0 0 1 0
# ^ ^ \+/ \--+--/
# | | | +------- CKSEL 3..0 (clock selection -> Internal RC oscillator)
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power)
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled)
# +-------------------- CKDIV8 (divide clock by 8 -> divide)
burn-fuse:
$(AVRDUDE) -U efuse:w:0x07:m -U hfuse:w:0xdf:m -U lfuse:w:0x62:m
read-fuse:
$(AVRDUDE) -U efuse:r:efuse.raw:r -U hfuse:r:hfuse.raw:r -U lfuse:r:lfuse.raw:r
flash:
$(AVRDUDE) -U flash:w:$(PROG).hex:i
read-flash:
$(AVRDUDE) -U flash:r:flash_dump.hex:i
flash: prog load
install : prog load
load:
$(AVRDUDE) -U flash:w:$(PROG).hex:i
clean:
rm -f $(PROG) *.hex *.lst
verify:
$(AVRDUDE)
if [ $$? -eq 0 ]; then \
echo "avrdude configured correctly"; \
else \
echo "avrdude not configured correctly in Makefile"; \
exit 1; \
fi

9
avr/README.md Normal file
View File

@ -0,0 +1,9 @@
packages needed:
sudo apt-get install gcc-avr avr-libc avrdude
I used the sparkfune AVR Pocket programmer, a USBtinyISP clone (http://ladyada.net/make/usbtinyisp/)
it uses libusb, not a serial port
to be able to use it a non-root part of the dialout group (on ubuntu distributions)
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="1781", ATTR{idProduct}=="0c9f", MODE="0660", GROUP="dialout"' | sudo tee /etc/udev/rules.d/99-avr.rules
sudo service udev reload

371
avr/ir grenade/Makefile Normal file
View File

@ -0,0 +1,371 @@
# MCU name
MCU = attiny85
F_CPU = 8000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = tvbgone
#NA_CODE = 1
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c util.c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create assembler listing
CFLAGS = -g -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-DF_CPU=$(F_CPU) \
-Wa,-adhlns=$(<:.c=.lst) \
$(patsubst %,-I%,$(EXTRAINCDIRS))
# Set a "language standard" compiler flag.
# Unremark just one line below to set the language standard to use.
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
#CFLAGS += -std=c89
#CFLAGS += -std=gnu89
#CFLAGS += -std=c99
CFLAGS += -std=gnu99
ifdef EU_CODE
CFLAGS += -DEU_CODES
else ifdef NA_CODE
CFLAGS += -DNA_CODES
else
CFLAGS += -DEU_CODES -DNA_CODES
endif
# Optional assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
# Optional linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
# Additional libraries
# Minimalistic printf version
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires -lm below)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
# -lm = math library
LDFLAGS += -lm
# Programming support using avrdude. Settings and variables.
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
#
AVRDUDE_PROGRAMMER = usbtiny
#AVRDUDE_PROGRAMMER = stk500v2
#AVRDUDE_PORT = com3 # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -B 5 -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
AVRDUDE_FLAGS = -p $(MCU) -c $(AVRDUDE_PROGRAMMER)
#AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE += -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_FLAGS += -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_FLAGS += -v -v
# ---------------------------------------------------------------------------
# Define directories, if needed.
DIRAVR = c:/winavr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
# Programming support using avrdude.
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
$(TARGET).lss $(TARGET).sym sizeafter finished end
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
finished:
@echo $(MSG_ERRORS_NONE)
end:
@echo $(MSG_END)
@echo
# Display size of file.
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Convert ELF to COFF for use in debugging / simulating in
# AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
reset:
$(AVRDUDE) $(AVRDUDE_FLAGS)
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
full: $(TARGET).hex
make burn-fuse
make program
burn-fuse:
$(AVRDUDE) $(AVRDUDE_FLAGS) -B 250 -u -U lfuse:w:0xfd:m -U hfuse:w:0xdf:m
read-fuse:
$(AVRDUDE) $(AVRDUDE_FLAGS) -u -U lfuse:r:l.txt:r
$(AVRDUDE) $(AVRDUDE_FLAGS) -u -U hfuse:r:h.txt:r
$(AVRDUDE) $(AVRDUDE_FLAGS) -u -U efuse:r:e.txt:r
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
avr-nm -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list finished end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
# Automatically generate C source code dependencies.
# (Code originally taken from the GNU make user manual and modified
# (See README.txt Credits).)
#
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
# (see the SHELL variable defined above).
# This may not work with other shells or other seds.
#
%.d: %.c
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
[ -s $@ ] || rm -f $@
# Remove the '-' if you want to see the dependency files generated.
-include $(SRC:.c=.d)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program

290
avr/ir grenade/main.c Normal file
View File

@ -0,0 +1,290 @@
/*
TV-B-Gone Firmware version 1.2
for use with ATtiny85v and v1.2 hardware
(c) Mitch Altman + Limor Fried 2009
Last edits, August 16 2009
With some code from:
Kevin Timmerman & Damien Good 7-Dec-07
Distributed under Creative Commons 2.5 -- Attib & Share Alike
This is the 'universal' code designed for v1.2 - it will select EU or NA
depending on a pulldown resistor on pin B1 !
*/
#include <avr/io.h> // this contains all the IO port definitions
#include <avr/eeprom.h>
#include <avr/sleep.h> // definitions for power-down modes
#include <avr/pgmspace.h> // definitions or keeping constants in program memory
#include <avr/wdt.h>
#include "main.h"
#include "util.h"
/*
This project transmits a bunch of TV POWER codes, one right after the other,
with a pause in between each. (To have a visible indication that it is
transmitting, it also pulses a visible LED once each time a POWER code is
transmitted.) That is all TV-B-Gone does. The tricky part of TV-B-Gone
was collecting all of the POWER codes, and getting rid of the duplicates and
near-duplicates (because if there is a duplicate, then one POWER code will
turn a TV off, and the duplicate will turn it on again (which we certainly
do not want). I have compiled the most popular codes with the
duplicates eliminated, both for North America (which is the same as Asia, as
far as POWER codes are concerned -- even though much of Asia USES PAL video)
and for Europe (which works for Australia, New Zealand, the Middle East, and
other parts of the world that use PAL video).
Before creating a TV-B-Gone Kit, I originally started this project by hacking
the MiniPOV kit. This presents a limitation, based on the size of
the Atmel ATtiny2313 internal flash memory, which is 2KB. With 2KB we can only
fit about 7 POWER codes into the firmware's database of POWER codes. However,
the more codes the better! Which is why we chose the ATtiny85 for the
TV-B-Gone Kit.
This version of the firmware has the most popular 100+ POWER codes for
North America and 100+ POWER codes for Europe. You can select which region
to use by soldering a 10K pulldown resistor.
*/
/*
This project is a good example of how to use the AVR chip timers.
*/
/*
The hardware for this project is very simple:
ATtiny85 has 8 pins:
pin 1 RST + Button
pin 2 one pin of ceramic resonator MUST be 8.0 mhz
pin 3 other pin of ceramic resonator
pin 4 ground
pin 5 OC1A - IR emitters, through a '2907 PNP driver that connects
to 4 (or more!) PN2222A drivers, with 1000 ohm base resistor
and also connects to programming circuitry
pin 6 Region selector. Float for US, 10K pulldown for EU,
also connects to programming circuitry
pin 7 PB0 - visible LED, and also connects to programming circuitry
pin 8 +3-5v DC (such as 2-4 AA batteries!)
See the schematic for more details.
This firmware requires using an 8.0MHz ceramic resonator
(since the internal oscillator may not be accurate enough).
IMPORTANT: to use the ceramic resonator, you must perform the following:
make burn-fuse_cr
*/
/* This function is the 'workhorse' of transmitting IR codes.
Given the on and off times, it turns on the PWM output on and off
to generate one 'pair' from a long code. Each code has ~50 pairs! */
void xmitCodeElement(uint16_t ontime, uint16_t offtime, uint8_t PWM_code )
{
// start Timer0 outputting the carrier frequency to IR emitters on and OC0A
// (PB0, pin 5)
TCNT0 = 0; // reset the timers so they are aligned
TIFR = 0; // clean out the timer flags
if(PWM_code) {
// 99% of codes are PWM codes, they are pulses of a carrier frequecy
// Usually the carrier is around 38KHz, and we generate that with PWM
// timer 0
TCCR0A =_BV(COM0A0) | _BV(WGM01); // set up timer 0
TCCR0B = _BV(CS00);
} else {
// However some codes dont use PWM in which case we just turn the IR
// LED on for the period of time.
PORTB &= ~_BV(IRLED);
}
// Now we wait, allowing the PWM hardware to pulse out the carrier
// frequency for the specified 'on' time
delay_ten_us(ontime);
// Now we have to turn it off so disable the PWM output
TCCR0A = 0;
TCCR0B = 0;
// And make sure that the IR LED is off too (since the PWM may have
// been stopped while the LED is on!)
PORTB |= _BV(IRLED); // turn off IR LED
// Now we wait for the specified 'off' time
delay_ten_us(offtime);
}
/* transmit IR burst, using the miles tag II format
* one IR burst is ticks*600uS on, and 600uS off
* n=1 codes 0
* n=2 codes 1
* n=4 codes header
*/
void transmit_ir(uint8_t ticks) {
xmitCodeElement(ticks*600/10*TIMING_CORRECTION,600/10*TIMING_CORRECTION,1); // added some correction to transmit code
}
void transmit_ir_byte(uint8_t data) {
uint8_t tick;
int8_t i;
//DEBUGP(putstring("byte burst "));
for (i=7;i>=0;i--) {
tick = ((data>>i)&0x01);
//DEBUGP(putnum_ud(tick));
transmit_ir(tick+1);
}
//DEBUGP(putstring("\r\n"));
}
int main(void) {
uint8_t i;
TCCR1 = 0; // Turn off PWM/freq gen, should be off already
TCCR0A = 0;
TCCR0B = 0;
// set OCR for Timer1 to output this POWER code's carrier frequency (lasertag milestag II uses 56kHz)
OCR0A = freq_to_timerval(56000);
i = MCUSR; // Save reset reason
MCUSR = 0; // clear watchdog flag
WDTCR = _BV(WDCE) | _BV(WDE); // enable WDT disable
WDTCR = 0; // disable WDT while we setup
DDRB = _BV(LED) | _BV(IRLED) | _BV(TX); // set the visible and IR LED pins to outputs
PORTB = _BV(LED) | // visible LED is off when pin is high
_BV(IRLED) | // IR LED is off when pin is high
_BV(TX); // Turn on pullup on region switch pin
DEBUGP(putstring_nl("\r\nHello cock suckers! Ready to swallow some infrared?\r\n"));
// check the reset flags
if (i & _BV(BORF)) { // Brownout
// Flash out an error and go to sleep
flashslowLEDx(2);
tvbgone_sleep();
}
delay_ten_us(5000); // Let everything settle for a bit
// blink half the time for 4 seconds
for (i=0;i<4;i++) {
PORTB &= ~_BV(LED); // turn on visible LED at PB0 by pulling pin to ground
delay_ten_us(50000);// wait 0.5s
PORTB |= _BV(LED); // turn off visible LED at PB0 by pulling pin to +3V
delay_ten_us(50000);// wait 0.5s
}
// blink fast for 1 seconds
for (i=0;i<5;i++) {
PORTB &= ~_BV(LED); // turn on visible LED at PB0 by pulling pin to ground
delay_ten_us(10000); // wait 0.1s
PORTB |= _BV(LED); // turn off visible LED at PB0 by pulling pin to +3V
delay_ten_us(10000); // wait 0.1s
}
// turn on watchdog timer immediately, this protects against
// a 'stuck' system by resetting it
wdt_enable(WDTO_8S); // 1 second long timeout
DEBUGP(putstring("fire in the hole\r\n"));
transmit_ir(4);
transmit_ir_byte(0x83);
transmit_ir_byte(0x0b);
transmit_ir_byte(0xe8); // end byte not needed
delay_ten_us(50000); // wait 0.1s
// the protprietary recorded version
transmit_ir(4);
transmit_ir_byte(0x84);
transmit_ir_byte(0x00);
transmit_ir_byte(0xa4);
// We are done, no need for a watchdog timer anymore
wdt_disable();
// flash the visible LED on PB0 4 times to indicate that we're done
//delay_ten_us(65500); // wait maxtime
quickflashLEDx(4);
tvbgone_sleep();
}
/****************************** SLEEP FUNCTIONS ********/
void tvbgone_sleep( void )
{
// Shut down everything and put the CPU to sleep
TCCR0A = 0; // turn off frequency generator (should be off already)
TCCR0B = 0; // turn off frequency generator (should be off already)
PORTB |= _BV(LED) | // turn off visible LED
_BV(IRLED); // turn off IR LED
wdt_disable(); // turn off the watchdog (since we want to sleep
delay_ten_us(1000); // wait 10 millisec
MCUCR = _BV(SM1) | _BV(SE); // power down mode, SE enables Sleep Modes
sleep_cpu(); // put CPU into Power Down Sleep Mode
}
/****************************** LED AND DELAY FUNCTIONS ********/
// This function delays the specified number of 10 microseconds
// it is 'hardcoded' and is calibrated by adjusting DELAY_CNT
// in main.h Unless you are changing the crystal from 8mhz, dont
// mess with this.
void delay_ten_us(uint16_t us) {
uint8_t timer;
while (us != 0) {
// for 8MHz we want to delay 80 cycles per 10 microseconds
// this code is tweaked to give about that amount.
for (timer=0; timer <= DELAY_CNT; timer++) {
NOP;
NOP;
}
NOP;
us--;
}
}
// This function quickly pulses the visible LED (connected to PB0, pin 5)
// This will indicate to the user that a code is being transmitted
void quickflashLED( void ) {
PORTB &= ~_BV(LED); // turn on visible LED at PB0 by pulling pin to ground
delay_ten_us(3000); // 30 millisec delay
PORTB |= _BV(LED); // turn off visible LED at PB0 by pulling pin to +3V
}
// This function just flashes the visible LED a couple times, used to
// tell the user what region is selected
void quickflashLEDx( uint8_t x ) {
quickflashLED();
while(--x) {
wdt_reset();
delay_ten_us(15000); // 150 millisec delay between flahes
quickflashLED();
}
wdt_reset(); // kick the dog
}
// This is like the above but way slower, used for when the tvbgone
// crashes and wants to warn the user
void flashslowLEDx( uint8_t num_blinks )
{
uint8_t i;
for(i=0;i<num_blinks;i++)
{
// turn on visible LED at PB0 by pulling pin to ground
PORTB &= ~_BV(LED);
delay_ten_us(50000); // 500 millisec delay
wdt_reset(); // kick the dog
// turn off visible LED at PB0 by pulling pin to +3V
PORTB |= _BV(LED);
delay_ten_us(50000); // 500 millisec delay
wdt_reset(); // kick the dog
}
}

40
avr/ir grenade/main.h Normal file
View File

@ -0,0 +1,40 @@
// What pins do what
#define LED PB2
#define IRLED PB0
#define TX PB1
// Lets us calculate the size of the NA/EU databases
#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)));
// set define to 0 to turn off debug output
#define DEBUG 1
#define DEBUGP(x) if (DEBUG == 1) { x ; }
// Shortcut to insert single, non-optimized-out nop
#define NOP __asm__ __volatile__ ("nop")
// Tweak this if neccessary to change timing
#define DELAY_CNT 11
#define TIMING_CORRECTION 1.18
// Makes the codes more readable. the OCRA is actually
// programmed in terms of 'periods' not 'freqs' - that
// is, the inverse!
#define freq_to_timerval(x) ((F_CPU / x - 1)/ 2)
// The structure of compressed code entries
struct IrCode {
uint8_t timer_val;
uint8_t numpairs;
uint8_t bitcompression;
uint16_t const *times;
uint8_t codes[];
};
void xmitCodeElement(uint16_t ontime, uint16_t offtime, uint8_t PWM_code );
void flashslowLEDx( uint8_t num_blinks );
void quickflashLEDx( uint8_t x );
void tvbgone_sleep( void );
void delay_ten_us(uint16_t us);
void quickflashLED( void );

91
avr/ir grenade/util.c Normal file
View File

@ -0,0 +1,91 @@
#include <avr/io.h> // this contains all the IO port definitions
#include <avr/interrupt.h> // definitions for interrupts
#include "main.h"
#include "util.h"
#define TXPORT PORTB
#define TX 1
#if (DEBUG == 1)
#define SERIALDELAY 75 // to make 19200 baud
void serialdelay(void) {
uint16_t timer;
for (timer=0; timer <= SERIALDELAY; timer++) {
NOP;
}
}
void uart_putchar(char d) {
int i;
cli(); // turn off interrupts, make it nice & kleen
TXPORT &= ~_BV(TX);
serialdelay();
for (i=0; i< 8; i++) {
if (d & 0x1) {
TXPORT |= _BV(TX);
} else {
TXPORT &= ~_BV(TX);
}
serialdelay();
d >>= 1;
}
TXPORT |= _BV(TX);
sei(); // turn on interrupts
serialdelay();
}
void printhex(uint8_t hex) {
hex &= 0xF;
if (hex < 10)
uart_putchar(hex + '0');
else
uart_putchar(hex + 'A' - 10);
}
void putnum_uh(uint16_t n) {
if (n >> 12)
printhex(n>>12);
if (n >> 8)
printhex(n >> 8);
if (n >> 4)
printhex(n >> 4);
printhex(n);
return;
}
void putnum_ud(uint16_t n) {
uint8_t cnt=0, flag=0;
while (n >= 10000UL) { flag = 1; cnt++; n -= 10000UL; }
if (flag) uart_putchar('0'+cnt);
cnt = 0;
while (n >= 1000UL) { flag = 1; cnt++; n -= 1000UL; }
if (flag) uart_putchar('0'+cnt);
cnt = 0;
while (n >= 100UL) { flag = 1; cnt++; n -= 100UL; }
if (flag) uart_putchar('0'+cnt);
cnt = 0;
while (n >= 10UL) { flag = 1; cnt++; n -= 10UL; }
if (flag) uart_putchar('0'+cnt);
cnt = 0;
uart_putchar('0'+n);
return;
}
void ROM_putstring(const char *str, uint8_t nl) {
uint8_t i;
for (i=0; pgm_read_byte(&str[i]); i++) {
uart_putchar(pgm_read_byte(&str[i]));
}
if (nl) {
uart_putchar('\n'); uart_putchar('\r');
}
}
#endif

21
avr/ir grenade/util.h Normal file
View File

@ -0,0 +1,21 @@
#include <avr/pgmspace.h>
uint8_t internal_eeprom_read(uint16_t addr);
void internal_eeprom_write(uint16_t addr, uint8_t data);
void delay_ms(uint16_t ms);
void uart_init(uint16_t baud);
void uart_putchar(char c);
char uart_getchar(void);
char uart_getch(void);
void putnum_ud(uint16_t n);
void putnum_uh(uint16_t n);
void printhex(uint8_t hex);
void ROM_putstring(const char *str, uint8_t);
uint16_t uart_read16(void);
void print_div(void);
#define putstring(x) ROM_putstring(PSTR(x), 0)
#define putstring_nl(x) ROM_putstring(PSTR(x), 1)
#define NOP __asm__ __volatile__ ("nop")