Started following some tutorial on att85 usi. Downloaded example code from make avr book.

This commit is contained in:
Dan
2022-09-20 01:08:01 -04:00
parent d0cbc0000e
commit 361a828c46
295 changed files with 68746 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 1000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,32 @@
/* First steps into using program memory */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "USART.h"
const char myVeryLongString[] PROGMEM = "\r\nHi there, \
this is an example of a long string.\r\n\
The kind that you wouldn't want to store in RAM.\r\n";
const uint16_t sixteenBits PROGMEM = 12345;
int main(void) {
initUSART();
char oneLetter;
uint8_t i;
while (1) {
for (i = 0; i < sizeof(myVeryLongString); i++) {
oneLetter = pgm_read_byte(&(myVeryLongString[i]));
transmitByte(oneLetter);
_delay_ms(100); /* slow it down to simulate typing effect :) */
}
_delay_ms(1000);
printWord(&sixteenBits); /* this throws a compiler warning... */
transmitByte('\r');
transmitByte('\n');
printWord(pgm_read_word(&sixteenBits));
} /* End event loop */
return 0; /* This line is never reached */
}

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 1000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,37 @@
/* Second steps into using program memory */
/* Storing the addresses in pointers */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "USART.h"
const char myVeryLongString[] PROGMEM = "\r\nHi there, \
this is an example of a long string.\r\n\
The kind that you wouldn't want to store in RAM.\r\n";
const uint16_t sixteenBits PROGMEM = 12345;
int main(void) {
initUSART();
const char *stringPointer;
const uint16_t *wordPointer;
uint8_t i;
char oneLetter;
stringPointer = &myVeryLongString[0]; /* address of first char */
// stringPointer = myVeryLongString; /* same as above */
wordPointer = &sixteenBits; /* address of first byte */
while (1) {
for (i = 0; i < sizeof(myVeryLongString); i++) {
oneLetter = pgm_read_byte(stringPointer + i);
transmitByte(oneLetter);
_delay_ms(100); /* slow it down to simulate typing effect :) */
}
_delay_ms(1000);
printWord(pgm_read_word(wordPointer));
} /* End event loop */
return 0; /* This line is never reached */
}

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 1000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,33 @@
/* Third step into using program memory */
/* Passing pointers to functions */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "USART.h"
const char myVeryLongString1[] PROGMEM = "\r\nHi there, \
this is an example of a long string.\r\n\
The kind that you wouldn't want to store in RAM.\r\n";
const char myVeryLongString2[] PROGMEM = "All work and no play \
makes Jack something something.\r\n";
void printString_Progmem(const char *stringP) {
char oneLetter;
while ((oneLetter = pgm_read_byte(stringP))) {
transmitByte(oneLetter);
stringP++;
_delay_ms(100); /* only b/c it's cute */
}
}
int main(void) {
initUSART();
while (1) {
printString_Progmem(&myVeryLongString1[0]);
printString_Progmem(&myVeryLongString1[50]);
printString_Progmem(myVeryLongString2);
_delay_ms(1000);
} /* End event loop */
return 0; /* This line is never reached */
}

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 1000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,36 @@
/* Fourth step into using program memory */
/* Passing data array pointers to functions */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "USART.h"
const uint16_t myData[] PROGMEM =
{ 1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 10000 };
const uint16_t myData2[] PROGMEM = { 123, 456, 789, 012, 345, 678, 999 };
void printData_Progmem(const uint16_t * dataPointer, uint8_t length) {
while (length) {
printWord((uint16_t) dataPointer); /* print out address */
printString(": ");
printWord(pgm_read_word(dataPointer)); /* print out data */
printString("\r\n");
dataPointer++; /* move to next byte */
length--; /* one less byte to go */
_delay_ms(100);
}
}
int main(void) {
initUSART();
while (1) {
printData_Progmem(myData, sizeof(myData) / 2);
printString("\r\n");
_delay_ms(1000);
printData_Progmem(myData2, sizeof(myData2) / sizeof(myData2[0]));
printString("\r\n");
_delay_ms(1000);
} /* End event loop */
return 0; /* This line is never reached */
}

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 1000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,68 @@
/* Fourth step into using program memory */
/* Passing data array pointers to functions */
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "USART.h"
const uint16_t myData[] PROGMEM =
{ 1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 10000 };
const char string1[] PROGMEM = "Hey, string one!\r\n";
const char string2[] PROGMEM = "Oh my, string two!\r\n";
const char *const stringIndex[] PROGMEM = { string1, string2 };
void printData_Progmem(const uint16_t * dataPointer, uint8_t length) {
while (length) {
printWord((uint16_t) dataPointer); /* print out address */
printString(": ");
printWord(pgm_read_word(dataPointer)); /* print out data */
printString("\r\n");
dataPointer++; /* move to next byte */
length--; /* one less byte to go */
_delay_ms(100);
}
}
void printString_Progmem(const char *stringP) {
char oneLetter;
while ((oneLetter = pgm_read_byte(stringP))) {
transmitByte(oneLetter);
stringP++;
}
}
int main(void) {
initUSART();
uint8_t myArray[] = { 10, 11, 12 };
uint8_t *p;
uint8_t i;
p = &myArray[0];
for (i = 0; i < sizeof(myArray); i++) {
printByte(*(p + i));
printString("\r\n");
_delay_ms(1000);
}
/* To use them: */
char *stringPointer;
/* Get the pointer to the string you want from PROGMEM */
stringPointer = (char *) pgm_read_word(&stringIndex[0]);
printString_Progmem(stringPointer);
/* or */
stringPointer = (char *) pgm_read_word(&stringIndex[1]);
printString_Progmem(&stringPointer[0]);
/* or */
printString_Progmem(PSTR("And this string got inlined.\r\n"));
while (1) {
printData_Progmem(myData, sizeof(myData) / sizeof(myData[0]));
printString("\r\n");
_delay_ms(1000);
} /* End event loop */
return 0; /* This line is never reached */
}

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 8000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,186 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168
F_CPU = 8000000
BAUD = 9600
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## This is where your main() routine lives (without .c extension)
TARGET = speech_1_bit_diff
## If you've split your program into multiple .c / .h files,
## include the additional source here (without the .c or .h extension)
LOCAL_SOURCE =
EXTRA_SOURCE_DIR = ../../../learningAVR/
EXTRA_SOURCE_FILES = USART
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## Defined programs / locations
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
## Compilation options, type man avr-gcc if you're curious.
CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -DBAUD=$(BAUD) -Os -I. -I$(EXTRA_SOURCE_DIR)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -g -ggdb
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
CFLAGS += -std=gnu99
## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
## Lump target and extra source files together
TARGET = $(strip $(basename $(MAIN)))
SRC = $(TARGET).c
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
SRC += $(EXTRA_SOURCE)
SRC += $(LOCAL_SOURCE)
## List of all header files
HEADERS = $(SRC:.c=.h)
## For every .c file, compile an .o object file
OBJ = $(SRC:.c=.o)
## Generic Makefile targets. (Only .hex file is necessary)
all: $(TARGET).hex
%.hex: %.elf
$(OBJCOPY) -R .eeprom -O ihex $< $@
%.elf: $(SRC)
$(CC) $(CFLAGS) $(SRC) --output $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
debug:
@echo
@echo "Source files:" $(SRC)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
eeprom: $(TARGET).eeprom
%.lst: %.elf
$(OBJDUMP) -S $< > $@
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,84 @@
% Speech encoder for Mega644/GCC decoder
clear all
%===================================%the Encoder
[d,r] = wavread('mega644small.wav'); %4
%scale to about unity
res = 1/(max(max(d),abs(min(d)) ));
dd = diff(d * res);
%init the code vector
ddcode = zeros(1,length(dd));
brkpt1= 0 ;
%quantize the first derivative
ddcode(find(dd<brkpt1)) = 0;
ddcode(find(dd>=brkpt1)) = 1;
%make the length of ddcode a multiple of 8
ddcode = [ddcode,zeros(1,8-mod(length(ddcode),8))];
length(ddcode)
index=1;
for i=1:8:length(ddcode)
packed(index)= ...
ddcode(i)*128 + ddcode(i+1)*64 + ...
ddcode(i+2)*32 + ddcode(i+3)*16 + ...
ddcode(i+4)*8 + ddcode(i+5)*4 + ...
ddcode(i+6)*2 + ddcode(i+7) ;
index=index+1;
end
%make a textfile with GCC source code in it.
fname='mega644_1_bit.h';
fid = fopen(fname,'w');
fprintf(fid,'const prog_uint8_t mega644[%d]={\r',length(packed));
for i=1:length(packed)-1
fprintf(fid,' %5d,\r',packed(i));
end
fprintf(fid,' %5d};\r',packed(end));
fclose(fid);
%===================================%the Decoder
%value based on quantizer
value = [-.16, .16];
dl(1)=0;
j=2;
highpassfactor = 1/8;
for i=1:length(packed)
p1 = round(bitand(packed(i),128)/128);
p2 = round(bitand(packed(i),64)/64);
p3 = round(bitand(packed(i),32)/32);
p4 = round(bitand(packed(i),16)/16);
p5 = round(bitand(packed(i),8)/8);
p6 = round(bitand(packed(i),4)/4);
p7 = round(bitand(packed(i),2)/2);
p8 = round(bitand(packed(i),1)/1);
%note that a bit of highpass has been added to reduce drift
dl(j) = dl(j-1)+ value(p1+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p2+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p3+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p4+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p5+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p6+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p7+1) - highpassfactor * dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p8+1) - highpassfactor * dl(j-1);
j=j+1;
end
% dl(1)=0;
% for i=1:length(ddcode)
% dl(i) = dl(i-1)+ value(ddcode(i)+1) - .125*dl(i-1); % .* w';
% end
%return
%====================================%playback and graphing
% sound(dl,r);
dl = dl/(max(abs(dl))+.001);
wavwrite(dl', 'mega644_1_bit.wav');

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,113 @@
//Voice decompressor example
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "USART.h"
#define TableSize 3280 //refers to the following incl file
//Contains the packed 1-bit codes for syntehsis
#include "mega644_1_bit.h"
//reconstruction differentials
//volatile signed char PCMvalue[4] = {-78, -16, 16, 78};
volatile signed char PCMvalue[2] = {-10, 10};
volatile unsigned int outI, tableI; //indexes
volatile unsigned char cycle ; //decode phase counter
volatile signed char out, lastout, newvalue; //output values
volatile unsigned char p1,p2,p3,p4,p5,p6,p7,p8; //hold 8 differentials
volatile unsigned char packed ; //byte containing 4 2-bit values
volatile uint8_t speaking; /* flag for whether currently speaking or not */
//generate waveform at 7812 scamples/sec
ISR (TIMER2_COMPA_vect){
//compute next sample
cycle = outI & 7; // outI modulo 8
if (cycle==0) //do we need to unpack more data?
{
if (tableI<TableSize) //} of stored wave?
{
//unpack a table entry into 2-bit indexs
// pgm_read_byte (address_short)
packed = pgm_read_byte(&mega644[tableI]) ;
//packed = DPCMAllDigits[tableI];
p1 = (packed & 128) == 128 ;
p2 = (packed & 64) == 64 ;
p3 = (packed & 32) == 32 ;
p4 = (packed & 16) == 16 ;
p5 = (packed & 8) == 8 ;
p6 = (packed & 4) == 4 ;
p7 = (packed & 2) == 2 ;
p8 = (packed & 1) == 1 ;
tableI++ ;
} //end unpack table entry
//compute the output and send to PWM
newvalue = PCMvalue[p1] ;
}
else if (cycle==1) //don't need to unpack yet--just ouput
newvalue = PCMvalue[p2] ;
else if (cycle==2)
newvalue = PCMvalue[p3] ;
else if (cycle==3)
newvalue = PCMvalue[p4] ;
else if (cycle==4)
newvalue = PCMvalue[p5] ;
else if (cycle==5)
newvalue = PCMvalue[p6] ;
else if (cycle==6)
newvalue = PCMvalue[p7] ;
else if (cycle==7)
newvalue = PCMvalue[p8] ;
out = lastout + newvalue - (lastout>>3);
//update outputs
OCR0A = out + 128;
lastout = out;
outI++;
//at end, turn off TCCRO
if (tableI==TableSize) TCCR2B = 0;
} //ISR
int main(void){
DDRD |= (1<<PD6);
DDRB |= (1<<PB0);
// turn on pwm with period= 256 cycles
// (62,500 samples/sec) in fast PWM mode.
// BUT OCR0A update is done using timer2 at 7800/sec
// timer 0 runs at full rate set in MAIN loop; TCCR0B = 1 ;
// turn on fast PWM and OC0A output
// 16 microsec per PWM cycle sample time
TCCR0A = (1<<COM0A0) | (1<<COM0A1) | (1<<WGM00) | (1<<WGM01) ;
OCR0A = 128 ; // initialize PWM to half full scale
TCCR0B = (1<<CS00); /* full speed */
// turn on timer2 set to overflow at 7812 Hz
// (prescaler set to divide by 8)
TCCR2A = (1<<WGM21); /* CTC, count to OCR2A */
OCR2A = 128; /* control sample playback frequency */
TCCR2B = (1<<CS21); /* clock source / 8 = 1MHz */
TIMSK2 = (1<<OCIE2A); // turn on compare interrupt
sei();
while(1) {
//init the output indexes
outI = 0;
tableI = 0;
//init the ouptut value
lastout = 0;
// turn on PWM
TCCR2B = (1<<CS21);
//wait until the speech is done then
//time delay the next utterance.
while (TCCR2B>0){};
OCR0A = 128 ;
_delay_ms(500);
PORTB ^= (1<<PB0);
} // end while
} //end main

View File

@@ -0,0 +1,24 @@
clear all
%use an optimizer to find the best parameters
%for an utterance
%The encoder/decoder go into an iterative scheme to find the
%best 3 break points and 4 reconstruction values
%===================================%the Encoder
[d,r] = wavread('C:\Documents and Settings\bruce land\My Documents\Matlab\Speech\SineSynth\test4small.WAV'); %4
%scale to about unity
res = 1/(max(max(d),abs(min(d)) ));
dd = diff(d * res);
%parameters
value = [-.16, -.026 .026 .16];
brkpt1=-0.05; brkpt2=0 ; brkpt3=0.05;
%initial parameter guess
p0 = [brkpt1, brkpt2, brkpt3, ...
value(1),value(2),value(3),value(4) ];
p = fminsearch(@FindOpt,p0,[],d,dd);
%ChiMin = fmins ('chisq', density0, options, [], smat, observed,
%fixdensity);
%=================================%print parameters
p

View File

@@ -0,0 +1,16 @@
function fit = FindOpt(p,d,dd)
p
%init the code vector
ddcode = zeros(1,length(dd));
%quantize the first derivative
ddcode(find(dd<p(1)))=0;
ddcode(find(dd>=p(1) & dd<p(2)))=1;
ddcode(find(dd>=p(2) & dd<p(3)))=2;
ddcode(find(dd>=p(3)))=3;
dl = zeros(1,length(ddcode));
for i=2:length(ddcode)
dl(i) = dl(i-1)+ p(ddcode(i)+4) - .125*dl(i-1); % .* w';
end
fit = mean((d(2:end)-dl').^2);

View File

@@ -0,0 +1,186 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168
F_CPU = 8000000
BAUD = 9600
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## This is where your main() routine lives (without .c extension)
TARGET = speech_644_GCC
## If you've split your program into multiple .c / .h files,
## include the additional source here (without the .c or .h extension)
LOCAL_SOURCE =
EXTRA_SOURCE_DIR = ../../../learningAVR/
EXTRA_SOURCE_FILES = USART
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## Defined programs / locations
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
## Compilation options, type man avr-gcc if you're curious.
CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -DBAUD=$(BAUD) -Os -I. -I$(EXTRA_SOURCE_DIR)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -g -ggdb
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
CFLAGS += -std=gnu99
## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
## Lump target and extra source files together
TARGET = $(strip $(basename $(MAIN)))
SRC = $(TARGET).c
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
SRC += $(EXTRA_SOURCE)
SRC += $(LOCAL_SOURCE)
## List of all header files
HEADERS = $(SRC:.c=.h)
## For every .c file, compile an .o object file
OBJ = $(SRC:.c=.o)
## Generic Makefile targets. (Only .hex file is necessary)
all: $(TARGET).hex
%.hex: %.elf
$(OBJCOPY) -R .eeprom -O ihex $< $@
%.elf: $(SRC)
$(CC) $(CFLAGS) $(SRC) --output $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
debug:
@echo
@echo "Source files:" $(SRC)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
eeprom: $(TARGET).eeprom
%.lst: %.elf
$(OBJDUMP) -S $< > $@
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,83 @@
% Speech encoder for Mega644/GCC decoder
clear all
%===================================%the Encoder
[d,r] = wavread('Z:\EEdocs\4760\ece4760labstuff\GCCmega644\Speech\AllDigits8khz.WAV'); %4
%scale to about unity
res = 1/(max(max(d),abs(min(d)) ));
dd = diff(d * res);
%init the code vector
ddcode = zeros(1,length(dd));
% brkpt1=-0.5; brkpt2=0 ; brkpt3=0.5;
% value = [-.75, -.25 .25 .75];
%breakpoints are changeable
brkpt1=-0.05; brkpt2=0 ; brkpt3=0.05;
%quantize the first derivative
ddcode(find(dd<brkpt1))=0;
ddcode(find(dd>=brkpt1 & dd<brkpt2))=1;
ddcode(find(dd>=brkpt2 & dd<brkpt3))=2;
ddcode(find(dd>=brkpt3))=3;
%make the length of ddcode a multiple of 4
ddcode = [ddcode,zeros(1,4-mod(length(ddcode),4))];
length(ddcode)
index=1;
for i=1:4:length(ddcode)
packed(index)=ddcode(i)*64 + ddcode(i+1)*16 + ...
ddcode(i+2)*4 + ddcode(i+3) ;
index=index+1;
end
%make a textfile with GCC source code in it.
fname='DPCMAllDigits.h';
fid = fopen(fname,'w');
fprintf(fid,'const prog_uint8_t DPCMAllDigits[%d]={\r',length(packed));
for i=1:length(packed)-1
fprintf(fid,' %5d,\r',packed(i));
end
fprintf(fid,' %5d};\r',packed(end));
fclose(fid);
%===================================%the Decoder
%value based on quantizer
value = [-.16, -.026 .026 .16];
dl(1)=0;
j=2;
for i=1:length(packed)
p1 = fix(bitand(packed(i),192)/64);
p2 = fix(bitand(packed(i),48)/16);
p3 = fix(bitand(packed(i), 12)/4);
p4 = fix(bitand(packed(i),3));
%note that a bit of highpass has been added to reduce drift
dl(j) = dl(j-1)+ value(p1+1) - .125*dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p2+1) - .125*dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p3+1) - .125*dl(j-1);
j=j+1;
dl(j) = dl(j-1)+ value(p4+1) - .125*dl(j-1);
j=j+1;
end
% dl(1)=0;
% for i=1:length(ddcode)
% dl(i) = dl(i-1)+ value(ddcode(i)+1) - .125*dl(i-1); % .* w';
% end
%====================================%playback and graphing
soundsc(dl,r);
% Compare the spectrograms
figure(1);clf
subplot(211)
spectrogram(d,256,r);
colormap gray
title('Original');
subplot(212)
spectrogram(dl,256,r);
colormap gray
title('synth');

View File

@@ -0,0 +1,5 @@
clear all
%reads a file at 16kHz and outputs it a 8kHz, 8 bits
[d,r] = wavread('test6.WAV');
y = resample(d,1,2);
wavwrite(y,8000,8,'test6small.wav')

View File

@@ -0,0 +1,38 @@
## Demo python program to create sine wave
from struct import pack, unpack
from math import sin, pi
import wave
import os
import random
RATE = 44100
## GENERATE MONO FILE ##
wv = wave.open('test_mono.wav', 'w')
wv.setparams((1, 2, RATE, 0, 'NONE', 'not compressed'))
maxVol=2**15-1.0 #maximum amplitude
wvData=""
for i in range(0, RATE*3):
wvData+=pack('h', maxVol*sin(2*pi*i*440.0/RATE))
wv.writeframes(wvData)
wv.close()
os.system("mplayer test_mono.wav")
## GENERATE STEREO FILE ##
wv = wave.open('test_stereo.wav', 'w')
wv.setparams((2, 2, RATE, 0, 'NONE', 'not compressed'))
maxVol=2**15-1.0 #maximum amplitude
waveData = ""
for i in range(0, RATE*3):
t = 2*pi*i/RATE # time-step in radians*sec
waveData+=pack('h', maxVol*sin(t*440.0)) #440Hz left
waveData+=pack('h', maxVol*sin(t*220.0)) #220Hz right
wv.writeframes(waveData)
wv.close()
os.system("mplayer test_stereo.wav")

View File

@@ -0,0 +1,109 @@
// Talking Voltmeter Example
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "pinDefines.h"
#include "DPCM_rich_hello_world_8000.h"
#define TABLE_NAME DPCM_rich_hello_world_8000
volatile uint16_t sampleNumber; // sample index
volatile int8_t out, lastout; // output values
volatile uint8_t p1, p2, p3, p4; // hold 4 differentials
const int8_t PCMvalue[4] = {-20, -4, 4, 20};
ISR (TIMER2_COMPA_vect){
/* Timer 2 controls sampling speed --
ISR reads new data, loads PWM output, OCR0A */
/* Since we can decode 4 2-bit values at once, need to know where
we are in the 4-step mini-cycle. */
uint8_t cycle = sampleNumber & 0b00000011; /* our 4 steps */
uint16_t tableEntry = sampleNumber >> 2; /* 4 steps per table byte */
uint8_t packedData; /* the new byte */
switch(cycle){
case 0: // Start of the cycle, unpack next byte of samples
if (tableEntry < sizeof(TABLE_NAME)){
packedData = pgm_read_byte(&TABLE_NAME[tableEntry]) ;
p1 = (packedData>>6) & 3 ;
p2 = (packedData>>4) & 3 ;
p3 = (packedData>>2) & 3 ;
p4 = (packedData & 3);
}
/* Add in the next PCM differential value */
out = lastout + PCMvalue[p1] - (lastout>>3) ;
break;
case 1:
out = lastout + PCMvalue[p2] - (lastout>>3) ;
break;
case 2:
out = lastout + PCMvalue[p3] - (lastout>>3) ;
break;
case 3:
out = lastout + PCMvalue[p4] - (lastout>>3) ;
break;
}
/* Update PWM audio output */
OCR0A = out + 128; /* re-center for 0-255 PWM */
lastout = out; /* update last value */
sampleNumber++; /* on to next sample */
/* When done, turn off PWM, Timer0 */
if (sampleNumber == 4*sizeof(TABLE_NAME)-1) {
TCCR2B = 0; /* disable sample-playback clock */
OCR0A = 128; /* idle at mid-voltage */
lastout = 0; /* start at 0 next time */
}
} // end ISR
void initTimer0(void){
// Timer 0 Configured for free-running PWM Audio Output
TCCR0A |= (1<<WGM00) | (1<<WGM01); /* fast PWM mode */
TCCR0A |= (1<<COM0A0) | (1<<COM0A1); /* output on PD6/OC0A */
TCCR0B = (1<<CS00); /* fastest clock */
OCR0A = 128 ; /* initialize mid-value */
SPEAKER_DDR |= (1<<SPEAKER); /* output PD6 / OC0A */
}
void initTimer2(void){
// Timer 2 loads OCR0A, defines sampling frequency
// Aiming for around 8kHz
TCCR2A = (1<<WGM21); /* CTC, count to OCR2A */
OCR2A = 128; /* controls sample playback frequency */
TCCR2B = (1<<CS21); /* clock source / 8 = 1MHz */
TIMSK2 = (1<<OCIE2A); /* turn on compare interrupt */
sei();
}
void initADC(void){
// ADC for Voltmeter function
ADMUX |= (0b00001111 & PC5); /* set mux to ADC5 */
DIDR0 |= _BV(ADC5D); /* turn off digital circuitry on PC5 */
ADMUX |= (1 << REFS0); /* reference voltage is AVCC, 5V */
ADCSRA |= (1 << ADPS1) | (1 << ADPS2); /* ADC clock prescaler /64 */
ADCSRA |= (1 << ADEN); /* enable ADC */
}
int main(void){
uint8_t adcValue;
initTimer0();
initTimer2();
initADC();
while(1) {
sampleNumber = 0; /* back to start of sample table */
TCCR2B = (1<<CS21); /* start loading samples */
/* Wait until done speaking, then delay some more. */
loop_until_bit_is_clear(TCCR2B, CS21);
_delay_ms(1000);
} /* end while */
return(0);
}

View File

@@ -0,0 +1,128 @@
## Given a .wav audio file, downsamples it to 8000 Hz and writes it out
## as a ADPCM file suitable for use with AVRs.
from struct import unpack
import wave
import os
import sys
def unpackMono(waveFile):
w = wave.Wave_read(waveFile)
data = []
for i in range(w.getnframes()):
data.append(unpack("h", w.readframes(1))[0])
return(data)
def scaleData(data):
scale = max(max(data), abs(min(data))) * 1.0
return([x/scale for x in data])
def getDifferences(data):
differences = []
for i in range(len(data)-1):
differences.append(data[i+1]-data[i])
return(differences)
def quantize(data, thresholds):
quantized = []
n = len(thresholds)
thresholdRange = range(n)
for d in data:
categorized = False
for i in thresholdRange:
if d <= thresholds[i]:
quantized.append(i)
categorized = True
break
if not categorized:
quantized.append(n)
return(quantized)
def pack4(data): # for 2-bit data
packedData = []
for i in range(len(data) / 4):
thisByte = 0
thisByte += 2**6 * data[4*i]
thisByte += 2**4 * data[4*i+1]
thisByte += 2**2 * data[4*i+2]
thisByte += data[4*i+3]
packedData.append(thisByte)
return(packedData)
def pack2(data): # for 1-bit data
packedData = []
for i in range(len(data) / 8):
thisByte = 0
thisByte += 2**7 * data[8*i]
thisByte += 2**6 * data[8*i+1]
thisByte += 2**5 * data[8*i+2]
thisByte += 2**4 * data[8*i+3]
thisByte += 2**3 * data[8*i+4]
thisByte += 2**2 * data[8*i+5]
thisByte += 2**1 * data[8*i+6]
thisByte += data[8*i+7]
packedData.append(thisByte)
return(packedData)
def packOneBitDPCM(filename):
data = unpackMono(filename)
data = scaleData(data)
differences = getDifferences(data)
quantized = quantize(differences, [0])
packed = pack2(quantized)
return(packed)
def packTwoBitDPCM(filename):
data = unpackMono(filename)
data = scaleData(data)
differences = getDifferences(data)
quantized = quantize(differences, TWO_BIT_THRESHOLDS)
packed = pack4(quantized)
return(packed)
def createHeader(filename, packedData):
baseFilename = filename[:-4]
outfile = open("DPCM_" + baseFilename + ".h", "w")
outfile.write('const uint8_t DPCM_{}[] PROGMEM = {{\n'.format(baseFilename))
for byte in packedData:
outfile.write(' {:d},\n'.format(byte))
outfile.write('};\n')
outfile.close()
def testWaveFile(filename):
w = wave.Wave_read(filename)
bitrate = w.getframerate()
channels = w.getnchannels()
bits = w.getsampwidth()*8
if not bitrate==8000 or not channels==1 or not bits==16:
newFilename = filename[:-4] + "_8000.wav"
returnValue = os.system(SOXCOMMAND.format(filename, newFilename))
if returnValue:
raise(SOX_Exception("Something went wrong calling sox: SOXCOMMAND.format(filename, newFilename"))
filename = newFilename
return(filename)
class SOX_Exception(Exception):
pass
class UsageException(Exception):
pass
if __name__ == "__main__":
TWO_BIT_THRESHOLDS = [-0.05, 0, 0.05]
try:
filename = sys.argv[1]
except IndexError:
raise(UsageException("usage: python wave2DPCM.py wavefilename.wav"))
SOXCOMMAND = "sox {} -r 8000 -c 1 -b 16 {}" # for converting wave file
## install sox, or use itunes or audacity to convert
## wavefile to 8kHz, 16-bit, one-channel
filename = testWaveFile(filename)
packedData = packTwoBitDPCM(filename)
createHeader(filename, packedData)

View File

@@ -0,0 +1,4 @@
*8000.wav
DPCM*.h
muah.wav
outtakes.wav

View File

@@ -0,0 +1,136 @@
## Given a .wav audio file, downsamples it to 8000 Hz and writes it out
## as a ADPCM file suitable for use with AVRs.
from struct import unpack
import wave
import os
import sys
def unpackMono(waveFile):
w = wave.Wave_read(waveFile)
data = []
for i in range(w.getnframes()):
data.append(unpack("h", w.readframes(1))[0])
return(data)
def scaleData(data):
scale = max(max(data), abs(min(data))) * 1.0
return([x/scale for x in data])
def getDifferences(data):
differences = []
for i in range(len(data)-1):
differences.append(data[i+1]-data[i])
return(differences)
def quantize(data, thresholds):
quantized = []
n = len(thresholds)
thresholdRange = range(n)
for d in data:
categorized = False
for i in thresholdRange:
if d <= thresholds[i]:
quantized.append(i)
categorized = True
break
if not categorized:
quantized.append(n)
return(quantized)
def pack4(data): # for 2-bit data
packedData = []
for i in range(len(data) / 4):
thisByte = 0
thisByte += 2**6 * data[4*i]
thisByte += 2**4 * data[4*i+1]
thisByte += 2**2 * data[4*i+2]
thisByte += data[4*i+3]
packedData.append(thisByte)
return(packedData)
def pack2(data): # for 1-bit data
packedData = []
for i in range(len(data) / 8):
thisByte = 0
thisByte += 2**7 * data[8*i]
thisByte += 2**6 * data[8*i+1]
thisByte += 2**5 * data[8*i+2]
thisByte += 2**4 * data[8*i+3]
thisByte += 2**3 * data[8*i+4]
thisByte += 2**2 * data[8*i+5]
thisByte += 2**1 * data[8*i+6]
thisByte += data[8*i+7]
packedData.append(thisByte)
return(packedData)
def packOneBitDPCM(filename):
data = unpackMono(filename)
data = scaleData(data)
differences = getDifferences(data)
quantized = quantize(differences, [0])
packed = pack2(quantized)
return(packed)
def packTwoBitDPCM(filename):
data = unpackMono(filename)
data = scaleData(data)
differences = getDifferences(data)
quantized = quantize(differences, TWO_BIT_THRESHOLDS)
packed = pack4(quantized)
return(packed)
def createHeader(filename, packedData):
baseFilename = filename[:-4]
outfile = open("DPCM_" + baseFilename + ".h", "w")
outfile.write('uint8_t DPCM_{}[] PROGMEM = {{\n'.format(baseFilename))
for byte in packedData:
outfile.write(' {:d},\n'.format(byte))
outfile.write('};\n')
outfile.close()
def testWaveFile(filename):
w = wave.Wave_read(filename)
bitrate = w.getframerate()
channels = w.getnchannels()
bits = w.getsampwidth()*8
if not bitrate==8000 or not channels==1 or not bits==16:
newFilename = filename[:-4] + "_8000.wav"
returnValue = os.system(SOXCOMMAND.format(filename, newFilename))
if returnValue:
raise(SOX_Exception("Something went wrong calling sox: SOXCOMMAND.format(filename, newFilename"))
filename = newFilename
return(filename)
class SOX_Exception(Exception):
pass
if __name__ == "__main__":
## Default is to convert all wav files in the current directory.
TWO_BIT_THRESHOLDS = [-0.05, 0, 0.05]
SOXCOMMAND = "sox {} -r 8000 -c 1 -b 16 {}" # for converting wave file
## install sox, or use itunes or audacity to convert
## wavefile to 8kHz, 16-bit, one-channel
wavefiles = [x for x in os.walk(".").next()[2] if x.endswith(".wav")]
for filename in wavefiles:
filename = testWaveFile(filename)
packedData = packTwoBitDPCM(filename)
createHeader(filename, packedData)
## And create a digits set:
digits = ["one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "zero", "point", "volts"]
allDigits = open("allDigits.h", "w")
for digit in digits:
filename = "DPCM_" + digit + "_8000.h"
print filename
allDigits.write(open(filename).read())
allDigits.close()

View File

@@ -0,0 +1,2 @@
*8000.wav
DPCM*.h

View File

@@ -0,0 +1,125 @@
// Talking Voltmeter Example
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/power.h>
#include "pinDefines.h"
#include "USART.h"
#include "talkingVoltmeter.h"
void startSampleTimer(void) {
sampleNumber = 0; /* back to start of sample table */
TCCR2B = (1 << CS21); /* turn on timer clock */
/* Two clock options above end up ~8kHz on 8MHz system */
}
void stopSampleTimer(void) {
TCCR2B = 0; /* disable sample-playback clock */
OCR0A = 128; /* idle PWM at mid-voltage */
lastout = 0; /* start at 0 next time */
}
void speak(void) {
startSampleTimer();
loop_until_bit_is_clear(TCCR2B, CS21); /* Wait until done */
}
void updatePWMAudio(void) {
OCR0A = out + 128; /* re-center for 0-255 PWM */
lastout = out; /* update last value */
sampleNumber++; /* on to next sample */
}
void unpackByte(uint8_t dataByte) {
/* Select pairs of bits from byte, save out */
differentials[0] = (dataByte >> 6) & 0b00000011;
differentials[1] = (dataByte >> 4) & 0b00000011;
differentials[2] = (dataByte >> 2) & 0b00000011;
differentials[3] = (dataByte & 0b00000011);
}
/* Timer 2 controls sampling speed.
ISR reads new data, loads PWM values into OCR0A */
ISR(TIMER2_COMPA_vect) {
/* Since we can decode 4 2-bit values at once, need to know where
we are in the 4-step mini-cycle. */
uint8_t cycle = sampleNumber & 0b00000011; /* keep last 2 bits */
uint16_t tableEntry;
uint8_t packedData;
if (cycle == 0) { /* at first sample, re-load */
tableEntry = sampleNumber >> 2; /* where we are in table */
if (tableEntry < thisTableLength) {
/* read the next byte from the selected table */
packedData = pgm_read_byte(&thisTableP[tableEntry]);
unpackByte(packedData); /* split up byte into differentials[] */
}
else { /* at end of table, done. */
stopSampleTimer();
}
}
/* Decode the differences: current value = last + difference */
out = lastout + dpcmWeights[differentials[cycle]] - (lastout >> 4);
updatePWMAudio();
} // end ISR (TIMER2_COMPA_vect)
void printString_Progmem(const char *stringP) {
char oneLetter;
while ((oneLetter = pgm_read_byte(stringP))) {
transmitByte(oneLetter);
stringP++;
}
}
int main(void) {
uint16_t voltage;
uint8_t volts;
uint8_t tenths;
uint8_t vcc = 51; /* 10x VCC, in volts */
clock_prescale_set(clock_div_1); /* 8 MHz */
initTimer0();
initTimer2();
sei(); /* for timer2 ISR */
initADC();
initUSART();
printString_Progmem(PSTR("\r\n--=( Talking Voltmeter )=--\r\n"));
selectTable(INTRO);
speak();
while (1) {
ADCSRA |= (1 << ADSC); /* start ADC */
loop_until_bit_is_clear(ADCSRA, ADSC);
voltage = ADC * vcc + vcc / 2; /* vcc/2 to make rounding work */
voltage = voltage >> 10; /* divide by 10-bits for ADC */
/* "voltage" is now actually 10x real-world voltage */
volts = voltage / 10;
tenths = voltage % 10;
transmitByte('0' + volts); /* serial output as well */
selectTable(volts); /* 0 points to ZERO_TABLE, etc */
speak();
transmitByte('.');
selectTable(POINT);
speak();
transmitByte('0' + tenths);
selectTable(tenths);
speak();
printString_Progmem(PSTR(" volts\r\n"));
selectTable(VOLTS);
speak();
_delay_ms(SPEECH_DELAY);
} /* end while */
return 0;
}

View File

@@ -0,0 +1,91 @@
/* Include file with DPCM data in it */
#include "allDigits.h"
#include <avr/pgmspace.h>
// Now define sample-table names used in digits file
// From here on, no matter what you call the samples,
// you can refer to them as "ONE_TABLE", etc.
#define ONE_TABLE DPCM_one_8000
#define TWO_TABLE DPCM_two_8000
#define THREE_TABLE DPCM_three_8000
#define FOUR_TABLE DPCM_four_8000
#define FIVE_TABLE DPCM_five_8000
#define SIX_TABLE DPCM_six_8000
#define SEVEN_TABLE DPCM_seven_8000
#define EIGHT_TABLE DPCM_eight_8000
#define NINE_TABLE DPCM_nine_8000
#define ZERO_TABLE DPCM_zero_8000
#define POINT_TABLE DPCM_point_8000
#define VOLTS_TABLE DPCM_volts_8000
#define INTRO_TABLE DPCM_talkingvoltmeter_8000
#define SPEECH_DELAY 2000 /* milliseconds */
/* --------------- Globals used by the ISR -------------- */
volatile uint8_t* thisTableP; /* points at the current speech table */
volatile uint16_t thisTableLength; /* length of current speech table */
volatile uint16_t sampleNumber; // sample index
volatile int8_t out, lastout; // output values
volatile uint8_t differentials[4] = {0,0,0,0};
const int8_t dpcmWeights[4] = {-12, -3, 3, 12};
/* These arrays let us choose a table (and its length) numerically */
const uint16_t tableLengths[] = { /* all sample tables are 8-bit */
sizeof(ZERO_TABLE), sizeof(ONE_TABLE), sizeof(TWO_TABLE),
sizeof(THREE_TABLE), sizeof(FOUR_TABLE), sizeof(FIVE_TABLE),
sizeof(SIX_TABLE), sizeof(SEVEN_TABLE), sizeof(EIGHT_TABLE),
sizeof(NINE_TABLE), sizeof(POINT_TABLE), sizeof(VOLTS_TABLE),
sizeof(INTRO_TABLE)
};
// Create an indexing table of all of the start addresses for
// each spoken digit. And then store this index in PROGMEM.
const uint8_t* const tablePointers[] PROGMEM = {
ZERO_TABLE, ONE_TABLE, TWO_TABLE, THREE_TABLE, FOUR_TABLE,
FIVE_TABLE, SIX_TABLE, SEVEN_TABLE, EIGHT_TABLE, NINE_TABLE,
POINT_TABLE, VOLTS_TABLE, INTRO_TABLE
};
void selectTable(uint8_t whichTable){
/* Set up global table pointer, lengths */
uint16_t pointerAddress;
thisTableLength = tableLengths[whichTable];
pointerAddress = (uint16_t) &tablePointers[whichTable];
thisTableP = (uint8_t*) pgm_read_word(pointerAddress);
}
/* Extra defines for the non-numeric values */
#define POINT 10
#define VOLTS 11
#define INTRO 12
///----------------- Init functions -------------------///
void initTimer0(void){
// Timer 0 Configured for free-running PWM Audio Output
TCCR0A |= (1<<WGM00) | (1<<WGM01); /* fast PWM mode */
TCCR0A |= (1<<COM0A0) | (1<<COM0A1); /* output on PD6/OC0A */
TCCR0B = (1<<CS00); /* fastest clock */
OCR0A = 128 ; /* initialize mid-value */
SPEAKER_DDR |= (1<<SPEAKER); /* output PD6 / OC0A */
}
void initTimer2(void){
// Timer 2 loads OCR0A, provides sampling frequency
TCCR2A = (1<<WGM21); /* CTC, count to OCR2A */
TIMSK2 = (1<<OCIE2A); /* turn on compare interrupt */
OCR2A = 128; /* controls sample playback frequency */
/* note: no clock source selected yet, so won't start up */
}
void initADC(void){
// ADC for Voltmeter function
ADMUX |= (0b00001111 & PC5); /* set mux to ADC5 */
DIDR0 |= _BV(ADC5D); /* turn off digital circuitry on PC5 */
ADMUX |= (1 << REFS0); /* reference voltage is AVCC, 5V */
ADCSRA |= (1 << ADPS1) | (1 << ADPS2); /* ADC clock prescaler /64 */
ADCSRA |= (1 << ADEN); /* enable ADC */
}

View File

@@ -0,0 +1,119 @@
## Functions to convert mono, 8kHz .wav files to differential PCM
## If you've got 'sox' installed on your computer, this code calls
## 'sox' and re-codes the files for you. If not, you've got to do it.
## Finally, given a bunch of wav files with names like one.wav, two.wav
## this writes the DPCM data out to a header file for including in AVR C
from struct import unpack
import wave
import os
import sys
def unpackMono(waveFile):
w = wave.Wave_read(waveFile)
data = []
for i in range(w.getnframes()):
data.append(unpack("h", w.readframes(1))[0])
return(data)
def scaleData(data):
scale = max(max(data), abs(min(data))) * 1.0
return([x/scale for x in data])
def getDifferences(data):
differences = []
for i in range(len(data)-1):
differences.append(data[i+1]-data[i])
return(differences)
def quantize(data, thresholds):
quantized = []
n = len(thresholds)
thresholdRange = range(n)
for d in data:
categorized = False
for i in thresholdRange:
if d <= thresholds[i]:
quantized.append(i)
categorized = True
break
if not categorized:
quantized.append(n)
return(quantized)
def pack4(data): # for 2-bit data
packedData = []
for i in range(len(data) / 4):
thisByte = 0
thisByte += 2**6 * data[4*i]
thisByte += 2**4 * data[4*i+1]
thisByte += 2**2 * data[4*i+2]
thisByte += data[4*i+3]
packedData.append(thisByte)
return(packedData)
def packTwoBitDPCM(filename):
data = unpackMono(filename)
data = scaleData(data)
differences = getDifferences(data)
quantized = quantize(differences, TWO_BIT_THRESHOLDS)
packed = pack4(quantized)
return(packed)
def createHeader(filename, packedData):
baseFilename = filename[:-4]
outfile = open("DPCM_" + baseFilename + ".h", "w")
outfile.write('const uint8_t DPCM_{}[] PROGMEM = {{\n'.format(baseFilename))
for byte in packedData:
outfile.write(' {:d},\n'.format(byte))
outfile.write('};\n')
outfile.close()
def fixWaveFile(filename):
w = wave.Wave_read(filename)
bitrate = w.getframerate()
channels = w.getnchannels()
bits = w.getsampwidth()*8
if not bitrate==8000 or not channels==1 or not bits==16:
newFilename = filename[:-4] + "_8000.wav"
returnValue = os.system(SOXCOMMAND.format(filename, newFilename))
if returnValue:
raise(SOX_Exception("""Something went wrong calling sox:
SOXCOMMAND.format(filename, newFilename
Is sox installed? If not, just make sure that you've saved 8kHz mono wav files."""))
filename = newFilename
return(filename)
class SOX_Exception(Exception):
pass
if __name__ == "__main__":
## Default is to convert all wav files in the current directory.
TWO_BIT_THRESHOLDS = [-0.05, 0, 0.05]
SOXCOMMAND = "sox {} -r 8000 -c 1 -b 16 {}" # for converting wave file
## install sox, or use itunes or audacity to convert
## wavefile to 8kHz, 16-bit, one-channel
wavefiles = [x for x in os.walk(".").next()[2] if x.endswith(".wav")]
for filename in wavefiles:
filename = fixWaveFile(filename) # converts if needed, returns new filename
packedData = packTwoBitDPCM(filename)
createHeader(filename, packedData)
## And create a digits sample set for talkingVoltmeter.h:
digits = ["one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "zero",
"point", "volts", "talkingvoltmeter"]
allDigits = open("allDigits.h", "w")
for digit in digits:
filename = "DPCM_" + digit + "_8000.h"
print filename
allDigits.write(open(filename).read())
allDigits.close()