Merge branch 'master' of ghostdub.de:gg-button

master
Hannes 14 years ago
commit a113f7f64a

6
.gitignore vendored

@ -1 +1,7 @@
/*.swp /*.swp
/*.d
headeredit
/*.o
/disasm
/firmware.bin
/firmware.hex

@ -0,0 +1,77 @@
CFLAGS += -Wall -Os -I. -mmcu=attiny26 -std=c99
DEFINES += -DF_CPU=16e6
OBJECTS = gg.o mmc.o
# further optimization:
# this removes dead code and does global linker optimization
#CFLAGS += -ffunction-sections -Wl,--gc-sections -Wl,--relax
#CFLAGS += --param inline-call-cost=2
COMPILE = avr-gcc $(CFLAGS) $(DEFINES)
# symbolic targets:
all: firmware.hex
.c.o:
$(COMPILE) -c $< -o $@
.S.o:
$(COMPILE) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
.c.s:
$(COMPILE) -S $< -o $@
flash: all
avrdude -c usbasp -p t26 -U flash:w:firmware.hex
fuses:
echo TODO
# avrdude -c usbasp -p t26 -U lfuse:w:0xe4:m -U hfuse:w:0xd9:m # internal 8Mhz oscillator
## what are the source dependencies
%.d: %.c
@set -e; rm -f $@; \
$(COMPILE) -MM $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@;
# line 1: exits if anything goes wrong
# line 2a: gcc -MM outputs dependencies
# line 2b: insert the %.d into dependency list
#main.c: version.h
version.h: .svn/entries
export LANG=POSIX; (svn info 2>/dev/null || echo "Revision: unknown") | awk '/^Revision:/ {print "#define SVNVERSION \"" $$2 "\""};' >version.h
clean:
rm -f *.o *.hex *.obj *.i *.s *.d */*.i */*.s */*.o */*.d version.h
# file targets:
firmware.bin: $(OBJECTS)
$(COMPILE) -o firmware.bin $(OBJECTS)
firmware.hex: firmware.bin
rm -f firmware.hex firmware.eep.hex
avr-objcopy -j .text -j .data -O ihex firmware.bin firmware.hex
avr-size firmware.bin
# ./checksize firmware.bin 8192 960
# do the checksize script as our last action to allow successful compilation
# on Windows with WinAVR where the Unix commands will fail.
disasm: firmware.bin
avr-objdump -d firmware.bin >disasm
functionsize: disasm
python avrbuild/functionsize.py
countregs: disasm
python avrbuild/countregs.py
# for depends:
-include $(OBJECTS:.o=.d)

@ -2,10 +2,14 @@
- gehäuse finden - gehäuse finden
- programmieren - programmieren
- a-law - sdcard
- pwm - pwm
- drumherum - drumherum
- testen
- sdcard
- verstärker
- löten - löten
- microcontroller - microcontroller
- verstärker - verstärker

@ -0,0 +1,18 @@
#!/usr/bin/python
import re
import os
fd = os.popen("avr-objdump -d firmware.bin")
regcount = [0]*32
s="foo"
while s:
s=fd.readline()
m=re.findall(r"[ \n\t,;]r(\d\d?)[ \n\t,;]",s)
if m:
for i in m:
regcount[int(i)] += 1;
for i in range(16):
print "r%2d: %4d"%(i,regcount[i]),
print "\tr%2d: %4d"%(i+16,regcount[i+16])

@ -0,0 +1,50 @@
#!/usr/bin/python
import re
import os
def main():
fd = os.popen("avr-objdump -d firmware.bin")
oldaddr=0
lastfnname=""
namespacedict = {}
s="foo"
while s:
s=fd.readline()
m=re.match("([0-9a-f]+) <(\w+)>:",s)
if m:
addr,fname=m.groups()
addr=int(addr,16)
size=addr-oldaddr
oldaddr=addr
# print size,"\t",lastfnname
namespace=get_namespace(lastfnname)
try:
namespacedict[namespace].append((lastfnname, size))
except:
namespacedict[namespace] = [(lastfnname, size)]
lastfnname = fname
print "individual sizes:"
for k,v in namespacedict.items():
for a,b in sorted(v):
print "%4i %s"%(b,a)
print "namespace sizes:"
for k,v in namespacedict.items():
totalsize = sum( [ i[1] for i in v ] )
print "%4i %s*"%(totalsize,k)
def get_namespace(name):
matchlist = [
r"(^__)",
r"(^\w+?_)",
r"(\w[a-z0-9])[A-Z]"]
for i in matchlist:
m = re.match(i, name)
if m:
return m.groups()[0]
return "<nonamespace>"
if __name__=="__main__":
main()

@ -0,0 +1,43 @@
#!/usr/bin/python
import re
print "Auto-generating menu_autogen.h..."
items=set([])
fd=file("menu.c")
for line in fd:
m = re.search(r"menu_item_(\w+)\s*\(",line)
if m:
items.add( m.groups()[0])
fd.close()
items=list(items) # create clear ordering
fd=file("menu_autogen.h","wb")
fd.write("\n");
for i in range(len(items)):
fd.write("extern int8_t menu_item_%s();\n" % items[i])
fd.write("\ntypedef int8_t (*item_handler_t)();\n\n")
fd.write("item_handler_t menu_item_handlers[] = {\n")
fd.write("\t\tNULL")
for i in range(len(items)):
fd.write(",\n\t\t*menu_item_%s" % items[i])
fd.write("\n};\n\n")
for i in range(len(items)):
fd.write("#define MENU_ITEM_%s \t%s\n" % (items[i].upper(), i+1))
fd.write("\n")
fd.write("#define MENU_MAX_ITEM %s\n\n"%len(items))

@ -0,0 +1,113 @@
#!/usr/bin/python
import re
from sys import argv
startline = "/* autogenerated by update_header.py. Please check and uncomment.\n"
changedline = "// changed declarations:\n"
newline = "// new declarations:\n"
endline = "*/ // update_header.py end\n"
def parse_c(data):
l=0
while l!=len(data):
l=len(data)
data=re.sub(r"(?ms)\{[^{}]*\}",";",data)
data = re.sub(r"(?ms)/\*.*?\*/","",data)
data = re.sub(r"(?m)^#.*$","",data)
data = data.split(";")
data = map(lambda x:x.strip(), data)
data = filter(None, data) # kill empty lines
data = map(lambda x:re.sub(r"\s*=.*$","",x), data)
return data
def make_symtable(data):
symbols={}
for i in data:
symname=get_symname(i)
symbols[symname] = i
return symbols
def get_symname(line):
try:
r = re.search(r"(\w+)($|\(|\[)",line).groups()[0]
return r
except:
raise 'Could not extract symbol from "%s".'%repr(line)
def update_header(filebase):
data = file(filebase+".c").read()
data = parse_c(data)
header = file(filebase+".h").read()
header = parse_c(header)
headersyms = make_symtable(header)
changed=[]
new=[]
for i in data:
symname = get_symname(i)
if symname not in headersyms:
new.append(i)
continue
headerline = headersyms[symname]
headerline = re.sub(r"extern\s+","",headerline)
if headerline != i:
changed.append(i)
print changed
print new
if (not changed) and (not new):
return # nothing to do
fd=file(filebase+".h")
header = fd.readlines()
fd.close()
if startline in header:
try:
print "foo"
start=header.index(startline)
stop=header.index(endline)
print start, stop
header = header[:start] + header[stop+1:]
fd = file(filebase+".h","wb")
fd.write("".join(header))
fd.close()
except:
print "Error killing old entry"
fd = file(filebase+".h","ab")
fd.write("\n\n\n")
fd.write(startline)
if changed:
fd.write("\n")
fd.write(changedline)
for i in changed:
fd.write("extern "+i+";\n")
if new:
fd.write("\n")
fd.write(newline)
for i in new:
fd.write("extern "+i+";\n")
fd.write("\n")
fd.write(endline)
fd.write("\n\n\n")
fd.close()
def main():
for i in argv[1:]:
i=re.sub(".[ch]$","",i)
update_header(i)
if __name__=="__main__":
main()

50
gg.c

@ -1,44 +1,14 @@
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "mmc.h" #include "mmc.h"
void timer_init_mega16(void)
{
ICR1 = (1 << 11) - 1;/* 11 bit pwm */
OCR1A = 0;
TCCR1A = (1 << COM1A1) | (1 << CS10) | (1 << WGM11);/* fast pwm, non inverted, top in ICR1 */
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);/* fast pwm, top in ICR1, */
DDRD |= (1 << PD5);/* set pwm pin as output */
TIMSK = 1 << TOIE1;/* interrupt at top */
}
void timer_init_tiny45(void)
{
PLLCSR = 1 << PLLE;/* pll enable */
delay_us(100);
while(!(PLLCSR & (1 << PLOCK))) {;}/* wait for lock */
PLLCSR |= 1 << PCKE;/* use pll */
OCR1C = 0xff;
/* output pin: OC1A = PB1 = 6 */
OCR1A = 0;
TCCR1 = (1 << PWM1A) | (1 << COM1A1) | (1 << CS10);/* pwm enable, non inverted, no prescaler */
DDRB |= (1 << PB1);
/* output pin: OC1B = PB5 = 3 */
//OCR1B = 0;
//TCCR1 = (1 << CS10);/* no prescaler */
//GTCCR = (1 << PWM1B) | (1 << COM1B1);/* pwm enable, non inverted */
//DDRB |= (1 << PB5);
TIMSK = 1 << TOIE1;/* interrupt on overflow */
}
void timer_init_tiny26(void) void timer_init_tiny26(void)
{ {
PLLCSR = 1 << PLLE;/* pll enable */ PLLCSR = 1 << PLLE;/* pll enable */
delay_us(100); _delay_us(100);
while(!(PLLCSR & (1 << PLOCK))) {;}/* wait for lock */ while(!(PLLCSR & (1 << PLOCK))) {;}/* wait for lock */
PLLCSR |= 1 << PCKE;/* use pll */ PLLCSR |= 1 << PCKE;/* use pll */
@ -46,7 +16,7 @@ void timer_init_tiny26(void)
/* output pin: OC1A = PB1 = 1 or OC1B = PB3 = 2 */ /* output pin: OC1A = PB1 = 1 or OC1B = PB3 = 2 */
OCR1A = 0; OCR1A = 0;
TCCR1A = (1 << COM1A1) (1 << PWM1A);/* pwm enable, not inverted */ TCCR1A = (1 << COM1A1) | (1 << PWM1A);/* pwm enable, not inverted */
TCCR1B = (1 << CS10);/* fast pwm, no prescaler */ TCCR1B = (1 << CS10);/* fast pwm, no prescaler */
DDRB |= (1 << PB1); DDRB |= (1 << PB1);
@ -55,7 +25,7 @@ void timer_init_tiny26(void)
uint8_t length[4];/* remaining samples */ uint8_t length[4];/* remaining samples */
uint8_t mmc_position[4];/* current reading position on mmc */ uint32_t mmc_position;/* current reading position on mmc */
uint8_t overflows = 1;/* remaining counter overflows until next sample */ uint8_t overflows = 1;/* remaining counter overflows until next sample */
#define SAMPLE_BITS 11 #define SAMPLE_BITS 11
@ -68,7 +38,7 @@ uint8_t buffer[BUFFER_SIZE];/* buffer for mmc data */
uint8_t pos = 0;/* current playing position */ uint8_t pos = 0;/* current playing position */
uint8_t refresh_buffer = 0;/* position to start buffer refreshing */ uint8_t refresh_buffer = 0;/* position to start buffer refreshing */
timerinterrupt() ISR(TIMER1_OVF1_vect)
{ {
//if(!(TIFR & (1 << TOV1))) {continue;}/* interrupt flag polling */ //if(!(TIFR & (1 << TOV1))) {continue;}/* interrupt flag polling */
//TIFR |= (1 << TOV1);/* done by hardware */ //TIFR |= (1 << TOV1);/* done by hardware */
@ -82,13 +52,15 @@ timerinterrupt()
/* TODO: a-law decoding */ /* TODO: a-law decoding */
/* TODO: 11bit PWM emulation */ /* TODO: 11bit PWM emulation */
OCR1A = buffer[pos];/* play next sample */ OCR1A = buffer[pos];/* play sample */
} }
void main(void) int main(void) __attribute__((noreturn));
int main(void)
{ {
uint8_t ref; // TODO: what does this do?
if(mmc_init() != 0) {/* mmc fail */;} if(mmc_init() != 0) {/* mmc fail */;}
timer_init_tiny26(); timer_init_tiny26();
sei(); sei();
@ -97,7 +69,7 @@ void main(void)
{ {
if(pos == refresh_buffer)/* refresh buffer if running low */ if(pos == refresh_buffer)/* refresh buffer if running low */
{ {
mmc_read(mmc_position, buffer + (ref + REFRESH_SIZE) % BUFFER_SIZE, BUFFER_SIZE - ref, buffer, REFRESH_AMOUNT - (BUFFER_SIZE - ref)); mmc_read_sector(mmc_position, buffer + (ref + REFRESH_SIZE) % BUFFER_SIZE);//, BUFFER_SIZE - ref), buffer, REFRESH_AMOUNT - (BUFFER_SIZE - ref));
/* pos on sd , first buffer address , 1st buffer size ,2nd buf, 2nd buffer size */ /* pos on sd , first buffer address , 1st buffer size ,2nd buf, 2nd buffer size */
refresh_buffer = (refresh_buffer + REFRESH_AMOUNT) % BUFFER_SIZE; refresh_buffer = (refresh_buffer + REFRESH_AMOUNT) % BUFFER_SIZE;
} }

28
mmc.c

@ -9,15 +9,15 @@ mail@ulrichradig.de
oder im Forum meiner Web Page : www.ulrichradig.de oder im Forum meiner Web Page : www.ulrichradig.de
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
GNU General Public License, wie von der Free Software Foundation veröffentlicht, GNU General Public License, wie von der Free Software Foundation veröffentlicht,
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
(nach Ihrer Option) jeder späteren Version. (nach Ihrer Option) jeder späteren Version.
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, dass es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
Programm erhalten haben. Programm erhalten haben.
@ -115,7 +115,7 @@ unsigned char mmc_write_command (unsigned char *cmd)
mmc_write_byte(*cmd++); mmc_write_byte(*cmd++);
} }
//Wartet auf ein gültige Antwort von der MMC/SD-Karte //Wartet auf ein gültige Antwort von der MMC/SD-Karte
while (tmp == 0xff) while (tmp == 0xff)
{ {
tmp = mmc_read_byte(); tmp = mmc_read_byte();
@ -133,12 +133,12 @@ unsigned char mmc_read_byte (void)
//############################################################################ //############################################################################
{ {
unsigned char Byte = 0; unsigned char Byte = 0;
#if SPI_Mode //Routine für Hardware SPI #if SPI_Mode //Routine für Hardware SPI
SPDR = 0xff; SPDR = 0xff;
while(!(SPSR & (1<<SPIF))){}; while(!(SPSR & (1<<SPIF))){};
Byte = SPDR; Byte = SPDR;
#else //Routine für Software SPI #else //Routine für Software SPI
for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
{ {
MMC_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low) MMC_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)
@ -163,12 +163,12 @@ unsigned char mmc_read_byte (void)
void mmc_write_byte (unsigned char Byte) void mmc_write_byte (unsigned char Byte)
//############################################################################ //############################################################################
{ {
#if SPI_Mode //Routine für Hardware SPI #if SPI_Mode //Routine für Hardware SPI
SPDR = Byte; //Sendet ein Byte SPDR = Byte; //Sendet ein Byte
while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
{ {
} }
#else //Routine für Software SPI #else //Routine für Software SPI
for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
{ {
if (bit_is_set(Byte,(a-1))>0) //Ist Bit a in Byte gesetzt if (bit_is_set(Byte,(a-1))>0) //Ist Bit a in Byte gesetzt
@ -198,7 +198,7 @@ unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben, /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingefügt*/ diese in das Commando eingefügt*/
addr = addr << 9; //addr = addr * 512 addr = addr << 9; //addr = addr * 512
@ -284,7 +284,7 @@ unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben, /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
addr wird von Blocks zu Bytes umgerechnet danach werden addr wird von Blocks zu Bytes umgerechnet danach werden
diese in das Commando eingefügt*/ diese in das Commando eingefügt*/
addr = addr << 9; //addr = addr * 512 addr = addr << 9; //addr = addr * 512

19
mmc.h

@ -9,8 +9,8 @@ Copyright (C) 2004 Ulrich Radig
#include <avr/io.h> #include <avr/io.h>
#define SPI_Mode 1 //1 = Hardware SPI | 0 = Software SPI //#define SPI_Mode 1 //1 = Hardware SPI | 0 = Software SPI
//#define SPI_Mode 0 #define SPI_Mode 0
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI #define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_Read PINB #define MMC_Read PINB
@ -21,7 +21,7 @@ Copyright (C) 2004 Ulrich Radig
#define SPI_DO 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist #define SPI_DO 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) #define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist #define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
#define SPI_SS 0 //Nicht Benutz muß aber definiert werden #define SPI_SS 0 //Nicht Benutz muss aber definiert werden
#endif #endif
#if defined (__AVR_ATmega32__) #if defined (__AVR_ATmega32__)
@ -29,7 +29,7 @@ Copyright (C) 2004 Ulrich Radig
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist #define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) #define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
#define MMC_Chip_Select 3 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist #define MMC_Chip_Select 3 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
#define SPI_SS 4 //Nicht Benutz muß aber definiert werden #define SPI_SS 4 //Nicht Benutz muss aber definiert werden
#endif #endif
#if defined (__AVR_ATmega644__) #if defined (__AVR_ATmega644__)
@ -37,9 +37,18 @@ Copyright (C) 2004 Ulrich Radig
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist #define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) #define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
#define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist #define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
#define SPI_SS 4 //Nicht Benutz muß aber definiert werden #define SPI_SS 4 //Nicht Benutz muss aber definiert werden
#endif #endif
#if defined (__AVR_ATtiny26__)
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
#define MMC_Chip_Select 1 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
#define SPI_SS 4 //Nicht benutzt, muss aber definiert werden
#endif
//Prototypes //Prototypes
extern unsigned char mmc_read_byte(void); extern unsigned char mmc_read_byte(void);

@ -0,0 +1,33 @@
void timer_init_mega16(void)
{
ICR1 = (1 << 11) - 1;/* 11 bit pwm */
OCR1A = 0;
TCCR1A = (1 << COM1A1) | (1 << CS10) | (1 << WGM11);/* fast pwm, non inverted, top in ICR1 */
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);/* fast pwm, top in ICR1, */
DDRD |= (1 << PD5);/* set pwm pin as output */
TIMSK = 1 << TOIE1;/* interrupt at top */
}
void timer_init_tiny45(void)
{
PLLCSR = 1 << PLLE;/* pll enable */
delay_us(100);
while(!(PLLCSR & (1 << PLOCK))) {;}/* wait for lock */
PLLCSR |= 1 << PCKE;/* use pll */
OCR1C = 0xff;
/* output pin: OC1A = PB1 = 6 */
OCR1A = 0;
TCCR1 = (1 << PWM1A) | (1 << COM1A1) | (1 << CS10);/* pwm enable, non inverted, no prescaler */
DDRB |= (1 << PB1);
/* output pin: OC1B = PB5 = 3 */
//OCR1B = 0;
//TCCR1 = (1 << CS10);/* no prescaler */
//GTCCR = (1 << PWM1B) | (1 << COM1B1);/* pwm enable, non inverted */
//DDRB |= (1 << PB5);
TIMSK = 1 << TOIE1;/* interrupt on overflow */
}
Loading…
Cancel
Save