delete old firmware

This commit is contained in:
Alexander Weinhold 2015-04-19 18:06:33 +02:00
parent e8564c7a96
commit 01abdb3287
28 changed files with 0 additions and 2432 deletions

View File

@ -1,79 +0,0 @@
PROJECT=pentabug
OPTIMIZATION = -Os
MCU = atmega88pa
F_CPU = 8000000
QUARZ = 8MHZ
FUSES = lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0x01:m
#########################################################################
SRC=$(wildcard lib/*.c apps/*.c *.c)
OBJECTS= $(SRC:.c=.o)
LSTFILES= $(SRC:.c=.lst)
HEADERS=$(wildcard lib/*.h *.h)
# Compiler Options
GCFLAGS = -ffreestanding -std=gnu99 -mmcu=$(MCU) $(OPTIMIZATION) -Wl,-gc-sections -nostdlib -I.
# Warnings
GCFLAGS += -Wstrict-prototypes -Wundef -Wall -Wextra -Wunreachable-code
# Optimizazions
GCFLAGS += -fsingle-precision-constant -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -fno-builtin -ffunction-sections -fno-common -fdata-sections
# Debug stuff
GCFLAGS += -Wa,-adhlns=$(<:.c=.lst),-gstabs -g
GCFLAGS += -DF_CPU=$(F_CPU) -DQUARZ=$(QUARZ)
LDFLAGS = -mmcu=$(MCU) $(OPTIMIZATION) -gc-sections
# Paths
GCC = avr-gcc
OBJCOPY = avr-objcopy
REMOVE = rm -f
SIZE = avr-size
AVRDUDE = avrdude
#########################################################################
all: $(PROJECT).hex Makefile
@$(SIZE) --mcu=$(MCU) --format=avr $(PROJECT).elf
$(PROJECT).hex: $(PROJECT).elf Makefile
@echo " \033[1;34mOBJCOPY\033[0m $(PROJECT).elf -> $(PROJECT).hex"
@$(OBJCOPY) -O ihex -R .eeprom $(PROJECT).elf $(PROJECT).hex
$(PROJECT).elf: $(OBJECTS) Makefile
@echo " \033[1;34mLink \033[0m (\033[1;33m $(OBJECTS)\033[0m) -> $(PROJECT).elf"
@$(GCC) $(OBJECTS) $(LDFLAGS) -o $(PROJECT).elf
clean:
$(REMOVE) $(OBJECTS)
$(REMOVE) $(LSTFILES)
$(REMOVE) $(PROJECT).hex
$(REMOVE) $(PROJECT).elf
#########################################################################
%.o: %.c Makefile $(HEADERS)
@echo " \033[1;34mCompile\033[0m $<"
@$(GCC) $(GCFLAGS) -o $@ -c $<
#########################################################################
fuse:
$(AVRDUDE) -p m88 -F -c usbtiny -v -v -U $(FUSES)
flash: $(PROJECT).hex Makefile
$(AVRDUDE) -p m88 -F -c usbtiny -B 1 -U flash:w:$(PROJECT).hex
fljohn: $(PROJECT).hex Makefile
$(AVRDUDE) -p m88 -F -P /dev/serial/by-id/usb-FTDI_USB__-__Serial-if00-port0 -c stk500v2 -v -v -U flash:w:$(PROJECT).hex
flsmart: $(PROJECT).hex Makefile
$(AVRDUDE) -p m88 -F -P /dev/ttyUSB0 -c stk500v2 -v -v -U flash:w:$(PROJECT).hex
.PHONY : clean all fuse flash fljohn

View File

@ -1,24 +0,0 @@
## Firmware
This firmware is to be flashed to the atmega88 of the pentabug.
The Makefile supports 2 different ways of flashing the firmware image:
### the serial bootloader way
With the
make serflash
target of the Makefile You can flash the microcontroler via the serial bootloader that is part of the initial firmware.
### the isp way
With the
make flash
target of the Makefile you can flash the microcontroler via an isp programmer.
Adjust the avrdude settings to Your programmers needs beforehand.

View File

@ -1,55 +0,0 @@
#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include "../lib/apps.h"
#include "../lib/bughal.h"
#include "../lib/util.h"
#include "../lib/music.h"
/**
* just blink mode
* - left/right button switch motor off/on
*/
static void blink(void)
{
static timer_t mytimer;
static bool blink;
if (mode_uninitialized) {
init_leds();
mode_uninitialized = false;
music_setNote(NOTE_PAUSE, 4); //mute
set_motor(MOTOR_OFF);
timer_set(&mytimer, 10);
blink = false;
}
if (timer_expired(&mytimer)) {
if (!blink) {
/*lets blink*/
led_on(LED_L | LED_R);
timer_set(&mytimer, 1);
blink = true;
} else {
/*stop blink*/
led_off(LED_L | LED_R);
timer_set(&mytimer, 123);
blink = false;
}
}//end if timer_expired
if (btn_state(BTNST_SUP, BTN_LEFT)) {
button_clear(BTN_LEFT);
set_motor(MOTOR_OFF);
}
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
button_clear(BTN_RIGHT);
set_motor(MOTOR_ON);
}
}
REGISTER(blink)

View File

@ -1,89 +0,0 @@
#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include "../lib/apps.h"
#include "../lib/bughal.h"
#include "../lib/util.h"
#include "../lib/music.h"
#include "../lib/usart.h"
inline uint16_t biased_random(uint16_t value) {
return value / 8 * (rand() & 7);
}
static void led_sound(void)
{
static bool discharge;
static timer_t mytimer;
uint16_t led1;
if(mode_last_tick) {
led_off(LED_L | LED_R);
set_motor(MOTOR_OFF);
music_setNote(NOTE_PAUSE, 0);
return;
}
if (mode_uninitialized) {
mode_uninitialized = false;
set_motor(MOTOR_OFF);
ADMUX = (1 << REFS0); // use VCC reference
ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8
ADCSRA |= (1 << ADEN); // ADC enable - turn it on
timer_set(&mytimer, 10);
discharge = true;
}
if (timer_expired(&mytimer)) {
if (discharge) {
led_off(LED_R | LED_L);
DDRC |= (1 << PORTC0) | (1 << PORTC1); //set LED Ports to output:
/*discharge*/
PORTC = (PORTC & 0b11110000);
/*set C0 and C2 to input (disable pullups)*/
DDRC &= ~(1 << PORTC0); //set Led Ports to input
/*pull ups off*/
PORTC &= ~(1 << PORTC0);
discharge = false;
timer_set(&mytimer, 1);
} else {
/*single measurement*/
ADMUX = (ADMUX & ~(0x1F)) | 0; // select channel 0
ADCSRA |= (1 << ADSC); // start single conversion
while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end
led1 = ADCW; // read result
DDRC |= (1 << PORTC0) | (1 << PORTC1); //set LED Ports to output:
set_motor(biased_random(led1) > 0x50 ? MOTOR_ON : MOTOR_OFF);
if(biased_random(led1) > 0x20) {
led_on(LED_R);
} else {
led_off(LED_R);
}
if(biased_random(led1) > 0x20) {
led_on(LED_L);
} else {
led_off(LED_L);
}
if(biased_random(led1) > 0x90) {
uint16_t tone = (biased_random(led1) * 2) + 500;
music_setNote(tone, 0);
} else {
music_setNote(NOTE_PAUSE, 0);
}
discharge = true;
timer_set(&mytimer, 20);
}
} //end if timer_expired
} //end mode5
REGISTER(led_sound)

View File

@ -1,134 +0,0 @@
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include "../lib/freq_table.h"
#include <lib/bughal.h>
#include <lib/timer.h>
#include <lib/apps.h>
void tetris_play(void);
static uint16_t osc0;
static uint16_t osc1;
static uint16_t sample;
static uint8_t row;
static uint16_t speedtime;
void synth_init(void){
init_buzzr();
osc0 = osc1 = sample = row = 0;
speedtime = 3000;
start_timer(tetris_play);
return;
}
void synth_deinit(void) {
stop_timer();
return;
}
enum {
SONG_LENGTH = 128,
xxx = 0,
c_0 = 0, cs0 = 1, d_0 = 2, ds0 = 3, e_0 = 4, f_0 = 5,
fs0 = 6, g_0 = 7, gs0 = 8, a_0 = 9, as0 = 10, b_0 = 11,
c_1 = 12, cs1 = 13, d_1 = 14, ds1 = 15, e_1 = 16, f_1 = 17,
fs1 = 18, g_1 = 19, gs1 = 20, a_1 = 21, as1 = 22, b_1 = 23,
c_2 = 24, cs2 = 25, d_2 = 26, ds2 = 27, e_2 = 28, f_2 = 29,
fs2 = 30, g_2 = 31, gs2 = 32, a_2 = 33, as2 = 34, b_2 = 35,
c_3 = 36, cs3 = 37, d_3 = 38, ds3 = 39, e_3 = 40, f_3 = 41,
fs3 = 42, g_3 = 43, gs3 = 44, a_3 = 45, as3 = 46, b_3 = 47,
};
const char music_data[2][SONG_LENGTH] PROGMEM = {
{
e_1, xxx, e_2, xxx, e_1, xxx, e_2, xxx,
e_1, xxx, e_2, xxx, e_1, xxx, e_2, xxx,
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx,
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx,
gs0, xxx, gs1, xxx, gs0, xxx, gs1, xxx,
gs0, xxx, gs1, xxx, gs0, xxx, gs1, xxx,
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx,
a_0, xxx, a_0, xxx, b_0, xxx, c_1, xxx,
d_1, xxx, d_2, xxx, d_1, xxx, d_2, xxx,
d_1, xxx, d_2, xxx, d_1, xxx, d_2, xxx,
c_1, xxx, c_2, xxx, c_1, xxx, c_2, xxx,
c_1, xxx, c_2, xxx, c_1, xxx, c_2, xxx,
b_0, xxx, b_1, xxx, b_0, xxx, b_1, xxx,
b_0, xxx, b_1, xxx, b_0, xxx, b_1, xxx,
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx,
a_0, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
}, {
e_3, e_3, e_3, e_3, b_2, b_2, c_3, c_3,
d_3, d_3, e_3, d_3, c_3, c_3, b_2, b_2,
a_2, a_2, a_2, a_2, a_2, a_2, c_3, c_3,
e_3, e_3, e_3, e_3, d_3, d_3, c_3, c_3,
b_2, b_2, b_2, b_2, b_2, b_2, c_3, c_3,
d_3, d_3, d_3, d_3, e_3, e_3, e_3, e_3,
c_3, c_3, c_3, c_3, a_2, a_2, a_2, a_2,
a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2,
xxx, xxx, d_3, d_3, d_3, d_3, f_3, f_3,
a_3, a_3, a_3, a_3, g_3, g_3, f_3, f_3,
e_3, e_3, e_3, e_3, e_3, e_3, c_3, c_3,
e_3, e_3, e_3, e_3, d_3, d_3, c_3, c_3,
b_2, b_2, b_2, b_2, b_2, b_2, c_3, c_3,
d_3, d_3, d_3, d_3, e_3, e_3, e_3, e_3,
c_3, c_3, c_3, c_3, a_2, a_2, a_2, a_2,
a_2, a_2, a_2, a_2, xxx, xxx, xxx, xxx,
}
};
void tetris_play(void) {
osc0 += pgm_read_word(&freq_table[ pgm_read_byte(&music_data[0][row])]);
osc1 += pgm_read_word(&freq_table[ pgm_read_byte(&music_data[1][row])]);
if (++sample == speedtime ) {
sample = 0;
if (speedtime > 600) speedtime -= 4;
if (++row == SONG_LENGTH) {
row = 0;
if (speedtime <= 600) speedtime = 3000;
}
led_on(row&4 ? LED_R : LED_L);
led_off(row&4 ? LED_L : LED_R);
}
if (osc0 >= 0x8000) PORTB |= (1 << PORTB2);
else PORTB &= ~(1<< PORTB2);
if (osc1 >= 0xc000) PORTC |= (1 << PORTC5);
else PORTC &= ~(1<< PORTC5);
}
/**
* do crazy synthesizer mode
*
*/
static void crazy_synth(void)
{
/* initialisation required */
if (mode_uninitialized) {
mode_uninitialized = false;
synth_init();
}
/*deinialisation required */
if (mode_last_tick) {
synth_deinit();
}
return;
}
REGISTER(crazy_synth)

View File

@ -1,73 +0,0 @@
#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include "../lib/apps.h"
#include "../lib/bughal.h"
#include "../lib/util.h"
#include "../lib/music.h"
#include "../lib/usart.h"
static void led_sound(void)
{
static bool discharge;
static timer_t mytimer;
uint16_t led1;
uint16_t led2;
if (mode_uninitialized) {
mode_uninitialized = false;
set_motor(MOTOR_OFF);
ADMUX = (1 << REFS0); // use VCC reference
ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8
ADCSRA |= (1 << ADEN); // ADC enable - turn it on
/*do one conversion*/
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC)) {
/*wait for conversion to end */
}
uint16_t __attribute__ ((unused)) dummy = ADCW; //read once
timer_set(&mytimer, 10);
discharge = true;
}
if (timer_expired(&mytimer)) {
if (discharge) {
DDRC |= (1 << PORTC0) | (1 << PORTC1) | //set LED Ports to output:
(1 << PORTC2) | (1 << PORTC3);
/*discharge*/
PORTC = (PORTC & 0b11110000);
/*set C0 and C2 to input (disable pullups)*/
DDRC &= ~((1 << PORTC0) | (1 << PORTC2)); //set Led Ports to input
/*pull ups off*/
PORTC &= ~((1 << PORTC0) | (1 << PORTC2));
discharge = false;
} else {
/*single measurement*/
ADMUX = (ADMUX & ~(0x1F)) | 0; // select channel 0
ADCSRA |= (1 << ADSC); // start single conversion
while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end
led1 = ADCW; // read result
ADMUX = (ADMUX & ~(0x1F)) | 2; // select channel 2
ADCSRA |= (1 << ADSC); // start single conversion
while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end
led2 = ADCW; // read result
#if 0
USART0_putc('1');
USART0_putc(':');
USART0_put_uint16(led1);
USART0_crlf();
USART0_putc('2');
USART0_putc(':');
USART0_put_uint16(led2);
USART0_crlf();
#endif
music_setNote(400 +
((0x1ff - led1) + (0x1ff - led2)) * 5, 0);
discharge = true;
}
timer_set(&mytimer, 2); //relaunch timer
} //end if timer_expired
} //end mode5
REGISTER(led_sound)

View File

@ -1,65 +0,0 @@
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <lib/bughal.h>
#include <lib/freq_table.h>
#include <lib/apps.h>
static uint16_t osc;
static uint16_t sample;
static uint8_t row;
#define LENGTH(x) (sizeof(x) / sizeof(x[0]))
static const uint8_t mushroom[] = {6,1,6,10,13,18,13,1,6,8,13,8,13,18,20,25,20,3,8,11,15,11,15,20,23,27,23};
static void mariofx_ISR(void) {
if (row < LENGTH(mushroom)) {
osc += pgm_read_word(&freq_table[mushroom[row] + 18]) * 3;
if (++sample == 800 ) {
sample = 0;
row++;
}
} else {
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
button_clear(BTN_RIGHT);
row = 0;
}
}
if (osc >= 0xc000) {
PORTB |= (1 << PORTB2);
PORTC &= ~(1<< PORTC5);
}
else {
PORTB &= ~(1<< PORTB2);
PORTC |= (1 << PORTC5);
}
}
static void mariofx(void) {
/* initialisation required */
if (mode_uninitialized) {
mode_uninitialized = false;
init_buzzr();
osc = sample = row = 0;
start_timer(mariofx_ISR);
}
/*deinialisation required */
if (mode_last_tick) {
stop_timer();
}
return;
}
REGISTER(mariofx);

View File

@ -1,92 +0,0 @@
#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include "../lib/apps.h"
#include "../lib/bughal.h"
#include "../lib/util.h"
#include "../lib/music.h"
#include "../lib/usart.h"
/**
* sound detection mode
* beeps,blinks and moves when sound is detected
* - beep on/off left switch (short)
* - motor on/off right switch (short)
*/
static void sound_detection(void)
{
if(mode_last_tick) {
led_off(LED_L | LED_R);
set_motor(MOTOR_OFF);
music_setNote(NOTE_PAUSE, 0);
return;
}
static timer_t mytimer;
static uint16_t maxval; // maximum of ADC values read during the las timer interval
static uint16_t lastmaxval; // maximum of values during last timer interval
uint16_t curval; // value on D5 (pin of piezo,the other is on GND)
static bool signaling; // are we currently signaling (beeping, blinking etc...)
static bool sound_on; // should sound be on when signaling
static bool motor_on; // should motor be on when signaling
if (mode_uninitialized) { //init after mode change
maxval = 0;
lastmaxval = 0;
mode_uninitialized = false;
signaling = false;
sound_on = true;
motor_on = true;
init_mic();
init_leds();
timer_set(&mytimer, 10);
}
/*single ADC measurement*/
curval = ADCW; // read result
maxval = (curval > maxval) ? curval : maxval;
/*check for Buttons*/
if (btn_state(BTNST_SUP, BTN_LEFT)) {
button_clear(BTN_LEFT);
sound_on = !sound_on;
}
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
button_clear(BTN_RIGHT);
motor_on = !motor_on;
}
if (timer_expired(&mytimer)) {
if (signaling) {
//turn off sound
music_setNote(NOTE_PAUSE, 0); //mute
set_motor(MOTOR_OFF);
//re-init mic
init_mic();
led_off(LED_R | LED_L);
timer_set(&mytimer, 1);
signaling = false;
lastmaxval = 10000;
} else { //sound was off wer're in measuring mode
if (maxval > lastmaxval) {
USART0_put_uint16(maxval);
USART0_crlf();
led_on(LED_R | LED_L);
init_buzzr(); //buzzr to output
if (sound_on)
music_setNote(NOTE_C, 5);
if (motor_on)
set_motor(MOTOR_ON);
signaling = true;
timer_set(&mytimer, 5); //sound duration
} else {
timer_set(&mytimer, 1);
}
lastmaxval = maxval;
maxval = 0;
}//end if soundon
}//end if timer_expired
} /* end mode0 */
REGISTER(sound_detection)

View File

@ -1,32 +0,0 @@
#ifndef CHIPDEF_H
#define CHIPDEF_H
#include <avr/io.h>
#if defined (SPMCSR)
#define SPM_REG SPMCSR
#elif defined (SPMCR)
#define SPM_REG SPMCR
#else
#error "AVR processor does not provide bootloader support!"
#endif
#define APP_END (FLASHEND - (BOOTSIZE * 2))
#if (SPM_PAGESIZE > UINT8_MAX)
typedef uint16_t pagebuf_t;
#else
typedef uint8_t pagebuf_t;
#endif
#if defined(__AVR_ATmega88PA__)
#include "mega88.h"
#elif defined(__AVR_ATmega88__)
#include "mega88.h"
#else
#error "no definition for MCU available in chipdef.h"
#endif
#endif

View File

@ -1,330 +0,0 @@
/*****************************************************************************
*
* Minimal Bootloader for Atmega644(p/a)
*
*
* Based on:
*
* AVRPROG compatible boot-loader
* Version : 0.85 (Dec. 2008)
* Compiler : avr-gcc 4.1.2 / avr-libc 1.4.6
* size : depends on features and startup ( minmal features < 512 words)
* by : Martin Thomas, Kaiserslautern, Germany
* eversmith@heizung-thomas.de
* Additional code and improvements contributed by:
* - Uwe Bonnes
* - Bjoern Riemer
* - Olaf Rempel
*
* License : Copyright (c) 2006-2008 M. Thomas, U. Bonnes, O. Rempel
* Free to use. You have to mention the copyright
* owners in source-code and documentation of derived
* work. No warranty! (Yes, you can insert the BSD
* license here)
*
******************************************************************************/
/* MCU frequency */
#ifndef F_CPU
#define F_CPU 8000000
#endif
/* UART Baudrate */
#define BAUDRATE 115200
/* use "Double Speed Operation" */
#define UART_DOUBLESPEED
/* use second UART on mega128 / can128 / mega162 / mega324p / mega644p */
//#define UART_USE_SECOND
/* Device-Type:
For AVRProg the BOOT-option is prefered
which is the "correct" value for a bootloader.
avrdude may only detect the part-code for ISP */
#define DEVTYPE DEVTYPE_BOOT
// #define DEVTYPE DEVTYPE_ISP
/*
* Pin "STARTPIN" on port "STARTPORT" in this port has to grounded
* (active low) to start the bootloader
*/
#define BLPORT PORTD
#define BLDDR DDRD
#define BLPIN PIND
#define BLPNUM PIND0
/*
* Watchdog-reset is issued at exit
* define the timeout-value here (see avr-libc manual)
*/
#define EXIT_WDT_TIME WDTO_250MS
void __vector_default(void) {
;
}
/*
* define the following if the bootloader should not output
* itself at flash read (will fake an empty boot-section)
*/
#define READ_PROTECT_BOOTLOADER
#define VERSION_HIGH '0'
#define VERSION_LOW '8'
#ifdef UART_DOUBLESPEED
// #define UART_CALC_BAUDRATE(baudRate) (((F_CPU*10UL) / ((baudRate) *8UL) +5)/10 -1)
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 4UL)) / ((uint32_t)(baudRate) * 8UL) - 1)
#else
// #define UART_CALC_BAUDRATE(baudRate) (((F_CPU*10UL) / ((baudRate)*16UL) +5)/10 -1)
#define UART_CALC_BAUDRATE(baudRate) ((uint32_t)((F_CPU) + ((uint32_t)baudRate * 8UL)) / ((uint32_t)(baudRate) * 16UL) - 1)
#endif
#include <stdint.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/boot.h>
#include <avr/pgmspace.h>
//#include <avr/interrupt.h>
//#include <util/delay.h>
#include "chipdef.h"
uint8_t gBuffer[SPM_PAGESIZE];
static void sendchar(uint8_t data) {
while (!(UART_STATUS & (1 << UART_TXREADY)))
;
UART_DATA = data;
}
static uint8_t recvchar(void) {
while (!(UART_STATUS & (1 << UART_RXREADY)))
;
return UART_DATA;
}
static inline void eraseFlash(void) {
// erase only main section (bootloader protection)
uint32_t addr = 0;
while (APP_END > addr) {
boot_page_erase(addr);
// Perform page erase
boot_spm_busy_wait(); // Wait until the memory is erased.
addr += SPM_PAGESIZE;
}
boot_rww_enable();
}
static inline void recvBuffer(pagebuf_t size) {
pagebuf_t cnt;
uint8_t *tmp = gBuffer;
for (cnt = 0; cnt < sizeof(gBuffer); cnt++) {
*tmp++ = (cnt < size) ? recvchar() : 0xFF;
}
}
static inline uint16_t writeFlashPage(uint16_t waddr, pagebuf_t size) {
uint32_t pagestart = (uint32_t) waddr << 1;
uint32_t baddr = pagestart;
uint16_t data;
uint8_t *tmp = gBuffer;
do {
data = *tmp++;
data |= *tmp++ << 8;
if (baddr < APP_END) {
boot_page_fill(baddr, data);
// call asm routine.
}
baddr += 2; // Select next word in memory
size -= 2; // Reduce number of bytes to write by two
} while (size); // Loop until all bytes written
boot_page_write(pagestart);
boot_spm_busy_wait();
boot_rww_enable(); // Re-enable the RWW section
return baddr >> 1;
}
static inline uint16_t readFlashPage(uint16_t waddr, pagebuf_t size) {
uint32_t baddr = (uint32_t) waddr << 1;
uint16_t data;
do {
#ifndef READ_PROTECT_BOOTLOADER
#warning "Bootloader not read-protected"
#if defined(RAMPZ)
data = pgm_read_word_far(baddr);
#else
data = pgm_read_word_near(baddr);
#endif
#else
// don't read bootloader
if (baddr < APP_END) {
#if defined(RAMPZ)
data = pgm_read_word_far(baddr);
#else
data = pgm_read_word_near(baddr);
#endif
} else {
data = 0xFFFF; // fake empty
}
#endif
sendchar(data); // send LSB
sendchar((data >> 8)); // send MSB
baddr += 2; // Select next word in memory
size -= 2; // Subtract two bytes from number of bytes to read
} while (size); // Repeat until block has been read
return baddr >> 1;
}
static void send_boot(void) {
sendchar('A');
sendchar('V');
sendchar('R');
sendchar('B');
sendchar('O');
sendchar('O');
sendchar('T');
}
static void (*jump_to_app)(void) = 0x0000;
int main(void) {
bootloader_wdt_off();
uint16_t address = 0;
uint8_t device = 0, val;
BLDDR &= ~(1 << BLPNUM); // set as Input
BLPORT |= (1 << BLPNUM); // Enable pullup
UART_STATUS = (1 << UART_DOUBLE);
UART_BAUD_HIGH = 0;
UART_BAUD_LOW = 25;
UART_CTRL = UART_CTRL_DATA;
UART_CTRL2 = UART_CTRL2_DATA;
if (BLPIN & (1 << BLPNUM)) {
// jump to main app if pin is not grounded and GPIOR2 is zero
jump_to_app(); // Jump to application sector
}
for (;;) {
val = recvchar();
// Autoincrement?
if (val == 'a') {
sendchar('Y'); // Autoincrement is quicker
//write address
} else if (val == 'A') {
address = recvchar(); //read address 8 MSB
address = (address << 8) | recvchar();
sendchar('\r');
// Buffer load support
} else if (val == 'b') {
sendchar('Y'); // Report buffer load supported
sendchar((sizeof(gBuffer) >> 8) & 0xFF); // Report buffer size in bytes
sendchar(sizeof(gBuffer) & 0xFF);
// Start buffer load
} else if (val == 'B') {
pagebuf_t size;
size = recvchar() << 8; // Load high byte of buffersize
size |= recvchar(); // Load low byte of buffersize
val = recvchar(); // Load memory type ('E' or 'F')
recvBuffer(size);
if (device == DEVTYPE) {
if (val == 'F') {
address = writeFlashPage(address, size);
}
sendchar('\r');
} else {
sendchar(0);
}
// Block read
} else if (val == 'g') {
pagebuf_t size;
size = recvchar() << 8; // Load high byte of buffersize
size |= recvchar(); // Load low byte of buffersize
val = recvchar(); // Get memtype
if (val == 'F') {
address = readFlashPage(address, size);
}
// Chip erase
} else if (val == 'e') {
if (device == DEVTYPE) {
eraseFlash();
}
sendchar('\r');
// Exit upgrade
} else if (val == 'E') {
wdt_enable(EXIT_WDT_TIME);
// Enable Watchdog Timer to give reset
sendchar('\r');
// Enter programming mode
} else if (val == 'P') {
sendchar('\r');
// Leave programming mode
} else if (val == 'L') {
sendchar('\r');
// return programmer type
} else if (val == 'p') {
sendchar('S'); // always serial programmer
// Return device type
} else if (val == 't') {
sendchar(DEVTYPE);
sendchar(0);
// clear and set LED ignored
} else if ((val == 'x') || (val == 'y')) {
recvchar();
sendchar('\r');
// set device
} else if (val == 'T') {
device = recvchar();
sendchar('\r');
// Return software identifier
} else if (val == 'S') {
send_boot();
// Return Software Version
} else if (val == 'V') {
sendchar(VERSION_HIGH);
sendchar(VERSION_LOW);
// Return Signature Bytes (it seems that
// AVRProg expects the "Atmel-byte" 0x1E last
// but shows it first in the dialog-window)
} else if (val == 's') {
sendchar(SIG_BYTE3);
sendchar(SIG_BYTE2);
sendchar(SIG_BYTE1);
/* ESC */
} else if (val != 0x1b) {
sendchar('?');
}
}
return 0;
}

View File

@ -1,462 +0,0 @@
# MCU name
MCU = atmega88
MCU_AVRDUDE = atmega88
## MCU = atmega644
#/* Select Boot Size in Words (select one, comment out the others) */
##BOOTSIZE=512 #(will not fit)
##BOOTSIZE=1024
##BOOTSIZE=2048
BOOTSIZE=512
ifeq ($(MCU), atmega88pa)
ifeq ($(BOOTSIZE), 128)
MT_BOOTLOADER_ADDRESS = 0x1F00
FUSE_SETTINGS = - lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xfe:m
endif
ifeq ($(BOOTSIZE), 256)
MT_BOOTLOADER_ADDRESS = 0x1E00
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xfc:m
endif
ifeq ($(BOOTSIZE), 512)
MT_BOOTLOADER_ADDRESS = 0x1C00
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xfa:m
endif
ifeq ($(BOOTSIZE), 1024)
MT_BOOTLOADER_ADDRESS = 0x1800
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xf8:m
endif
endif
ifeq ($(MCU), atmega88)
ifeq ($(BOOTSIZE), 128)
MT_BOOTLOADER_ADDRESS = 0x1F00
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xfe:m
endif
ifeq ($(BOOTSIZE), 256)
MT_BOOTLOADER_ADDRESS = 0x1E00
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xfc:m
endif
ifeq ($(BOOTSIZE), 512)
MT_BOOTLOADER_ADDRESS = 0x1C00
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xfa:m
endif
ifeq ($(BOOTSIZE), 1024)
MT_BOOTLOADER_ADDRESS = 0x1800
FUSE_SETTINGS = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xf8:m
endif
endif
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
#FORMAT = srec
# Target file name (without extension).
TARGET = plbl
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS = -DBOOTSIZE=$(BOOTSIZE)
# Place -I options here
CINCS =
# Compiler flags.
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
# Assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
#Additional libraries.
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
PRINTF_LIB =
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
SCANF_LIB =
MATH_LIB = -lm
# External memory options
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
# Linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
################## BOOTLOADER ######################
# MT_BOOTLOADER_ADDRESS (=Start of Boot Loader section
# in bytes - not words) as defined above.
LDFLAGS += -Wl,--section-start=.text=$(MT_BOOTLOADER_ADDRESS)
BFD_MACH=avr5
LDFLAGS += -T./$(BFD_MACH).x
# Programming support using avrdude. Settings and variables.
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500v2
# com1 = serial port. Use lpt1 to connect to parallel port.
#AVRDUDE_PORT = /dev/ttyUSB1 # programmer connected to serial device
AVRDUDE_PORT = /dev/cu.SLAB_USBtoUART # programmer connected to serial device
#AVRDUDE_PORT = /dev/ttyS0 # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
AVRDUDE_WRITE_FUSE = $(FUSE_SETTINGS)
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU_AVRDUDE) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
# ---------------------------------------------------------------------------
# Define directories, if needed.
#DIRAVR = c:/winavr
#DIRAVRBIN = $(DIRAVR)/bin
#DIRAVRUTILS = $(DIRAVR)/utils/bin
#DIRINC = .
#DIRLIB = $(DIRAVR)/avr/lib
# Define programs and commands.
#SHELL = $(DIRAVRUTILS)/sh
#NM = $(DIRAVRBIN)/avr-nm
#CC = $(DIRAVRBIN)/avr-gcc
#OBJCOPY = $(DIRAVRBIN)/avr-objcopy
#OBJDUMP= $(DIRAVRBIN)/avr-objdump
#SIZE = $(DIRAVRBIN)/avr-size
#AVRDUDE = $(DIRAVRBIN)/avrdude.sh
#REMOVE = rm -f
#COPY = cp
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp
WINSHELL = cmd
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Compiler flags to generate dependency files.
### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
GENDEPFLAGS = -MD -MP
#GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter finished end
build: elf hex eep lss sym
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
finished:
@echo $(MSG_ERRORS_NONE)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -x -A $(TARGET).elf
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
flash: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
fuse:
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FUSE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list finished end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
# $(REMOVE) .dep/*
# Include the dependency files.
#-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program

View File

@ -1,38 +0,0 @@
#ifndef _MEGA88_H_
#define _MEGA88_H_
/* Part-Code ISP */
#define DEVTYPE_ISP 0x76
/* Part-Code BOOT */
#define DEVTYPE_BOOT 0x77
#define SIG_BYTE1 0x1E
#define SIG_BYTE2 0x93
#define SIG_BYTE3 0x0F
#define UART_BAUD_HIGH UBRR0H
#define UART_BAUD_LOW UBRR0L
#define UART_STATUS UCSR0A
#define UART_TXREADY UDRE0
#define UART_RXREADY RXC0
#define UART_DOUBLE U2X0
#define UART_CTRL UCSR0B
#define UART_CTRL_DATA ((1<<TXEN0) | (1<<RXEN0))
#define UART_CTRL2 UCSR0C
#define UART_CTRL2_DATA (1<<UCSZ00)|(1<<UCSZ01)//((1<<URSEL0) | (1<<UCSZ10) | (1<<UCSZ00))
#define UART_DATA UDR0
static inline void bootloader_wdt_off(void) {
// cli();
wdt_reset();
/* Clear WDRF in MCUSR */
MCUSR &= ~(1 << WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out */
WDTCSR |= (1 << WDCE) | (1 << WDE);
/* Turn off WDT */
WDTCSR = 0x00;
}
#endif // #ifndef _MEGA88_H_

View File

@ -1,63 +0,0 @@
#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#include "../lib/apps.h"
#include "../lib/bughal.h"
#include "../lib/util.h"
#include "../lib/music.h"
/**
* crazymoves mode
* - play random sounds and move in random fashion
*/
static void crazy(void)
{
static timer_t mytimer;
uint8_t max = 50;
uint8_t min = 5;
uint16_t maxfreq = 5000;
uint16_t minfreq = 1000;
if (mode_uninitialized) {
mode_uninitialized = false;
music_setNote(NOTE_PAUSE, 4); //mute
timer_set(&mytimer, 10);
init_leds();
led_off(LED_L | LED_R);
set_motor(MOTOR_OFF);
}
if (timer_expired(&mytimer)) {
set_motor(MOTOR_OFF);
music_setNote(NOTE_PAUSE, 0); //mute
/*set random led*/
switch (rand() % 4) {
case 0: led_on(LED_L); break;
case 1: led_on(LED_R); break;
case 2: led_on(LED_L | LED_R); break;
default: led_off(LED_L | LED_R); break;
};
/*decide if to switch motor on (40% chance)*/
if (rand() % 5 > 2)
set_motor(MOTOR_ON);
/*decide if to play sound (70% chance)*/
if (rand() % 10 > 2) {
music_setNote((rand() % (maxfreq - minfreq)) + minfreq,
0);
}
timer_set(&mytimer, (rand() % (max - min)) + min);
}//end if timer_expired
/*deinialisation */
if (mode_last_tick) {
set_motor(MOTOR_OFF);
music_setNote(NOTE_PAUSE, 0); //mute
}
}
REGISTER(crazy)

View File

@ -1,29 +0,0 @@
#ifndef APPS_H
#define APPS_H
#include <inttypes.h>
/*
* REGISTER makro exploits special avr-libc startup code voodo.
* This could be understood by reading
* http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
*
* */
#define MAX_FUNS 16
#define REGISTER(fun) static void init(void) __attribute__ ((naked, used, section (".init8"))); \
void init(void) { \
mode_funs[mode_num] = fun; \
++mode_num; \
} \
typedef void (*mode_fun)(void);
extern mode_fun mode_funs[MAX_FUNS];
extern uint8_t mode_num;
extern uint8_t mode_uninitialized;
extern uint8_t mode_last_tick;
#endif /* APPS_H */

View File

@ -1,219 +0,0 @@
#include <inttypes.h>
#include <avr/io.h>
#include "bughal.h"
#include "util.h" //for timer
/* Hardware abstraction layer for Pentabug hardware */
/*
* initialize LEDs on C0-C3
*/
static uint8_t oldinput; // button readings from last poll cycle
static uint8_t curinput; // button readings from current poll cycle
//each switch has its own state machine
static uint8_t btnstates[BTN_BUTTONS]; //array for current button states
static uint8_t btncounters[BTN_BUTTONS]; //individual counter for button state machine
static timer_t btntimers[BTN_BUTTONS]; //individiual timer for for button state machine
void init_leds(void) {
//enable LED channels as output
DDRC |= (1 << PORTC0) | (1 << PORTC1) | (1 << PORTC2) | (1 << PORTC3);
// both LEDs off
PORTC &= ~((1 << PORTC0) | (1 << PORTC1) | (1 << PORTC2) | (1 << PORTC3));
return;
}
inline void led_on(int leds) {
PORTC |= leds;
}
inline void led_off(int leds) {
PORTC &= ~leds;
}
void init_buzzr(void) {
// its on B2 and C5
DDRC |= (1 << PORTC5);
DDRB |= (1 << PORTB2);
// switch it off
buzzr_off();
return;
}
void init_mic(void) {
// buzzer is on B2 and C5, for reasons
// ... we use it as microphone
DDRC &= ~(1 << PORTC5); // switch C5 to input
DDRB |= (1 << PORTB2); // B2 as output
PORTB &= ~(1 << PORTB2); //and to GND
ADMUX = (1 << REFS1) | (1 << REFS0); // use internal 1.1V as reference
ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8
ADCSRA |= (1 << ADEN) | (1 << ADATE); // ADC enable - turn it on in free running mode
ADCSRB &= (1 << ACME); //leave only ACME as it is (others zerp for free running)
ADMUX = (ADMUX & ~(0x1F)) | 5; // select channel 5
ADCSRA |= (1 << ADSC); // start conversion
uint16_t __attribute__((unused)) dummy = ADCW; //read once
return;
}
void buzzr_up(void) {
// one pin Vcc, other GND
PORTC &= ~(1 << PORTC5);
PORTB |= (1 << PORTB2);
return;
}
;
void buzzr_down(void) {
// one pin GND,other pin Vcc
PORTC |= (1 << PORTC5);
PORTB &= ~(1 << PORTB2);
}
inline void buzzr_off(void) {
// both pins to GND
PORTC &= ~(1 << PORTC5);
PORTB &= ~(1 << PORTB2);
}
void buzzr_inv(void) {
// read and invert pin settings, make the piezo flip polarity
PORTC ^= (1 << PORTC5);
PORTB ^= (1 << PORTB2);
}
void init_switch(void) {
// init switch 1 and switch 2
DDRD &= ~((1 << PORTD1) | (1 << PORTD0)); // D0 and D1 as input
PORTD |= (1 << PORTD1) | (1 << PORTD0); // pull-ups FTW
// set predefined button states
oldinput = 0;
curinput = 0;
// initialize the state machine of each button
for (uint8_t i = 0; i < BTN_BUTTONS; i++) {
btnstates[i] = BTNST_NTRL; //init button states
btncounters[i] = 0; //init button counters
timer_set(&btntimers[i], 0x05); //50ms - init button timers
};
return;
}
bool switch_l(void) {
return !(PIND & 0b00000001);
}
bool switch_r(void) {
return !(PIND & 0b00000010);
}
void init_motor(void) {
/* vibration motor on B1, initially off: */
DDRB |= (1 << PORTB1);
PORTB &= ~(1 << PORTB1);
return;
}
void set_motor(int val) {
if (val == MOTOR_ON) {
PORTB |= 0x02;
} else {
PORTB &= ~(0x02);
}
return;
}
// reset button to neutral state
void button_clear(uint8_t button) {
btnstates[button] = BTNST_NTRL;
}
void stateswitch(uint8_t i) {
switch (btnstates[i]) {
case BTNST_NTRL: //NEUTRAL
if (curinput & (1 << i)) { //button down
btncounters[i] = 0;
btnstates[i] = BTNST_DBNC;
}
break;
case BTNST_DBNC: //intermediate state, check if button is still pressed to debounce
btnstates[i] = (curinput & (1 << i)) ? BTNST_SDN : BTNST_NTRL;
(btncounters[i])++;
break;
case BTNST_SDN:
if (curinput & (1 << i)) {
btncounters[i]++;
if (btncounters[i] > BTN_T_LONGFACT) { //500ms held
btnstates[i] = BTNST_LDN;
}
} else { //button was released
btnstates[i] = BTNST_SUP;
//signal shortclick
}
break;
case BTNST_LDN:
if (!(curinput & (1 << i))) {
//button was released
btnstates[i] = BTNST_LUP; //signal longpress
}
break;
case BTNST_SUP:
if ((curinput & (1 << i))) {
//button was pressed again or is bouncing after release
btnstates[i] = BTNST_SUPDBNC; //going in special debounce
btncounters[i] = 0;
}
break;
case BTNST_LUP:
if ((curinput & (1 << i))) {
//button was pressed again or is bouncing after release
btnstates[i] = BTNST_LUPDBNC; //going in special debounce
btncounters[i] = 0;
}
break;
case BTNST_SUPDBNC:
if ((curinput & (1 << i))) {
//button is still pressed --> going to shortpress
btncounters[i]++;
btnstates[i] = BTNST_SDN; //starting over from short pressed
} else {
btnstates[i] = BTNST_SUP; //nope, it was bouncing, back to old state
}
break;
case BTNST_LUPDBNC:
if ((curinput & (1 << i))) {
//button is still pressed --> going to shortpress
btncounters[i]++;
btnstates[i] = BTNST_SDN; //starting over from short pressed
} else {
btnstates[i] = BTNST_LUP; //nope, it was bouncing, back to old state
}
break;
default: //curently catches nothing
// do nothing yet
;
break;
}; //end switch
timer_set(&btntimers[i], BTN_T_DEBOUNCE);
}
void button_poll() {
curinput = ~(PIND & 0b00000011);
for (uint8_t i = 0; i < BTN_BUTTONS; i++) {
if (timer_expired(&btntimers[i])) {
stateswitch(i);
} //end if timer expired
} //end for
oldinput = curinput;
return;
}
bool btn_state(uint8_t btnstate, uint8_t btn) {
return (btnstates[btn] == btnstate);
}

View File

@ -1,69 +0,0 @@
#ifndef BUGHAL_H
#define BUGHAL_H
#include <stdbool.h>
/* Hardware abstraction layer for Pentabug hardware */
enum {
BUZZR_OUT, //initialize buzzer for OUTPUT mode (emmiting soundwaves)
BUZZR_IN
//initialize buzzer for INPUT mode (registering soundwaves)
};
#define LED_L (1 << PORTC0)
#define LED_R (1 << PORTC2)
#define MOTOR_ON 1
#define MOTOR_OFF 0
#define BTN_RIGHT 1
#define BTN_LEFT 0
#define BTN_BUTTONS 2 //numer of Buttons
#define BTN_T_DEBOUNCE 5 // 50ms debounce time = minimum short press time
#define BTN_T_LONGFACT 10 // after 10 * T_DEBOUNCE = 500ms button registers as long pressed
//BUTTON state machine states
#define BTNST_NTRL 0 // neutral - initial state nothing interesting, please go along
#define BTNST_DBNC 1 // debounce - pin went up, but we wait for things to stabilize and stop oscillating
#define BTNST_SDN 4 // affirmative, button is pressed,
// and it's pressed no longer than
// BTN_T_LONGFACT * BTN_T_DEBOUNCE * 10ms
#define BTNST_SUP 8 // and button went up after beeing pressed for a _short_ time
#define BTNST_LDN 16 // button is still down for more than
//BTN_T_LONGFACT * BTN_T_DEBOUNCE * 10ms
#define BTNST_LUP 32 // button came up after being pressed for a long time
#define BTNST_SUPDBNC 64 // debounce after short up
#define BTNST_LUPDBNC 128 // debounce after long up
void init_leds(void);
void led_on(int);
void led_off(int);
void init_buzzr(void);
void init_mic(void);
void buzzr_up(void);
void buzzr_down(void);
void buzzr_off(void);
void buzzr_inv(void);
// init ports and stuff for button functions
void init_switch(void);
// direct low level access to switches
bool switch_l(void); //switch pressed?
bool switch_r(void); //switch pressed?
void init_motor(void);
void set_motor(int);
// higher level functions for accessing switches
void button_poll(void); //needs to be polled in regular intervalls (lets say every 10ms)
// reset button to neutral state
void button_clear(uint8_t button);
//test if buttonstate of btn eqals btnstate, returns true if yes
bool btn_state(uint8_t btnstate, uint8_t btn);
#endif

View File

@ -1,51 +0,0 @@
#include <avr/pgmspace.h>
const uint16_t freq_table[] PROGMEM = {
/*0x00*/ 0,
/*0x01*/ 130,
/*0x02*/ 137,
/*0x03*/ 145,
/*0x04*/ 154,
/*0x05*/ 163,
/*0x06*/ 173,
/*0x07*/ 183,
/*0x08*/ 194,
/*0x09*/ 206,
/*0x0a*/ 218,
/*0x0b*/ 231,
/*0x0c*/ 245,
/*0x0d*/ 259,
/*0x0e*/ 275,
/*0x0f*/ 291,
/*0x10*/ 308,
/*0x11*/ 327,
/*0x12*/ 346,
/*0x13*/ 367,
/*0x14*/ 388,
/*0x15*/ 412,
/*0x16*/ 436,
/*0x17*/ 462,
/*0x18*/ 489,
/*0x19*/ 518,
/*0x1a*/ 549,
/*0x1b*/ 582,
/*0x1c*/ 617,
/*0x1d*/ 653,
/*0x1e*/ 692,
/*0x1f*/ 733,
/*0x20*/ 777,
/*0x21*/ 823,
/*0x22*/ 872,
/*0x23*/ 924,
/*0x24*/ 979,
/*0x25*/ 1037,
/*0x26*/ 1099,
/*0x27*/ 1164,
/*0x28*/ 1233,
/*0x29*/ 1306,
/*0x2a*/ 1384,
/*0x2b*/ 1466,
/*0x2c*/ 1554,
/*0x2d*/ 1646,
/*0x2e*/ 1744,
/*0x2f*/ 1848,
};

View File

@ -1 +0,0 @@
extern const uint16_t freq_table[] PROGMEM;

View File

@ -1,43 +0,0 @@
#include <stdint.h>
#include <math.h>
#include <avr/interrupt.h>
#include <avr/common.h>
#include <avr/io.h>
#include "util.h"
#include "bughal.h"
#include "music.h"
//static volatile uint16_t currentNote;
void music_init(void) {
TCCR1A = 0; //TIMER1, normal, no PWM
TCCR1B = (1 << WGM12) | (1 << CS11); //CTC Mode, Clear Timer on Compare, Prescaler = 8
TIMSK1 &= ~(1 << OCIE1A); //disable Output Compare Interrupt
return;
}
;
void music_setNote(uint16_t note, uint8_t octave) {
cli();
if (note != NOTE_PAUSE) {
//Play a Note
buzzr_up();
TIMSK1 |= (1 << OCIE1A); //enable Output Compare Interrupt
OCR1A = octave == 0 ? note : note / (1 << octave);
} else { // Pause (silence)
buzzr_off();
TIMSK1 &= ~(1 << OCIE1A); //disable Output Compare Interrupt
}
sei();
return;
}
/* timer interrupt function */ISR(TIMER1_COMPA_vect, ISR_NOBLOCK) {
// invert buzzer polarity
buzzr_inv();
}

View File

@ -1,23 +0,0 @@
/* small timer library, uses timer2 */
#ifndef _MUSIC_H
#define _MUSIC_H
#define NOTE_PAUSE (65000) //Pause
//Values for Octave 0
#define NOTE_C (30577) // note C
#define NOTE_Db (28862) // note C# / Db
#define NOTE_D (27242) // note D
#define NOTE_Eb (25713) // note D# / Eb
#define NOTE_E (24270) // note E
#define NOTE_F (22908) // note F
#define NOTE_Gb (21622) // note F# / Gb
#define NOTE_G (20408) // note G
#define NOTE_Ab (19263) // note G# / Ab
#define NOTE_A (18182) // note A
#define NOTE_Bb (17161) // note A# / Bb
#define NOTE_B (16198) // note B
void music_init(void);
void music_setNote(uint16_t note, uint8_t octave);
#endif

View File

@ -1,40 +0,0 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <lib/timer.h>
timer_cb cur_cb;
void start_timer(timer_cb cb) {
cur_cb = cb;
cli();
/* set timer0 to CTC & prescaler 64 → 125kHz increment */
TCCR0A = (1 << WGM01);
TCCR0B = (1 << CS00) | (1 << CS01);
OCR0A = 4; /* TOP */
TCNT0 = 0;
/*enable interrupt */
TIMSK0 |= (1 << OCIE0A);
sei();
}
void stop_timer(void) {
cli();
TIMSK0 = 0;
sei();
cur_cb = NULL;
}
ISR(TIMER0_COMPA_vect,ISR_NOBLOCK) {
if(cur_cb != NULL) {
cur_cb();
}
}

View File

@ -1,10 +0,0 @@
#ifndef TIMER_H
#define TIMER_H
typedef void (*timer_cb)(void);
void start_timer(timer_cb cb);
void stop_timer(void);
#endif /* TIMER_H */

View File

@ -1,118 +0,0 @@
/*
* PentaFnord Firmware
*
* by Alexander Lorz <bigalex@gmx.de>
*
*
* The USART control code is derived by code from the 4CHLED project
* by sebseb7: https://github.com/sebseb7/eagle/tree/master/4CHLED/firmware
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart.h"
#define UART_RXBUFSIZE 32
static volatile uint8_t rxbuf0[UART_RXBUFSIZE];
static volatile uint8_t * volatile rxhead0, * volatile rxtail0;
ISR (USART_RX_vect) {
UCSR0B &= ~(1 << RXCIE0);
asm volatile("sei");
int diff;
uint8_t c;
c = UDR0;
diff = rxhead0 - rxtail0;
if (diff < 0)
diff += UART_RXBUFSIZE;
if (diff < UART_RXBUFSIZE - 1) {
*rxhead0 = c;
++rxhead0;
if (rxhead0 == (rxbuf0 + UART_RXBUFSIZE))
rxhead0 = rxbuf0;
}
UCSR0B |= (1 << RXCIE0);
}
void USART0_Init(void) {
// set baudrate
#define BAUD_TOL 4
#undef BAUD
#define BAUD 115200
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0); // enable double speed operation
#else
UCSR0A &= ~(1 << U2X0); // disable double speed operation
#endif
// flush receive buffer
while (UCSR0A & (1 << RXC0))
UDR0;
// set 8N1
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
UCSR0B &= ~(1 << UCSZ02);
UCSR0B |= (1 << RXEN0) | (1 << TXEN0); //enable send and receive
UCSR0B |= (1 << RXCIE0); //enable receive interrup
rxhead0 = rxtail0 = rxbuf0;
}
void USART0_putc(char c) {
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
}
uint8_t USART0_Getc_nb(uint8_t *c) {
if (rxhead0 == rxtail0)
return 0;
*c = *rxtail0;
if (++rxtail0 == (rxbuf0 + UART_RXBUFSIZE))
rxtail0 = rxbuf0;
return 1;
}
void USART0_crlf(void) {
USART0_putc(0x0A); //newline
USART0_putc(0x0D); //carriage return
}
;
void USART0_put_uint8(uint8_t x) {
uint8_t highchar = ((x & 0b11110000) >> 4) + 0x30;
uint8_t lowchar = (x & 0b00001111) + 0x30;
highchar = highchar > 0x39 ? highchar + 0x07 : highchar; //chars A to F start with 0x41 not 0x3A
lowchar = lowchar > 0x39 ? lowchar + 0x07 : lowchar;
USART0_putc(highchar);
USART0_putc(lowchar);
}
void USART0_put_uint16(uint16_t x) {
USART0_put_uint8((x & 0xFF00) >> 8);
USART0_put_uint8(x & 0x00FF);
}

View File

@ -1,34 +0,0 @@
/*
* PentaFnord Firmware
*
* by Alexander Lorz <bigalex@gmx.de>
*
*
* The USART control code is derived by code from the 4CHLED project
* by sebseb7: https://github.com/sebseb7/eagle/tree/master/4CHLED/firmware
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _USART_H
#define _USART_H
void USART0_Init(void);
void USART0_putc(char c);
uint8_t USART0_Getc_nb(uint8_t*);
void USART0_put_uint8(uint8_t);
void USART0_crlf(void);
void USART0_put_uint16(uint16_t);
#endif

View File

@ -1,58 +0,0 @@
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/common.h>
#include <avr/io.h>
#include "util.h"
static volatile uint8_t internal_counter;
void timer_init(void) {
/* initialize timer2, CTC at 10ms, prescaler 1024 */
OCR2A = F_CPU / 1024 / 100;
TCCR2A = _BV(WGM21);
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
TIMSK2 = _BV(OCIE2A);
}
void timer_set(timer_t *t, uint8_t timeout) {
t->current = internal_counter;
t->timeout = timeout;
}
void timerL_set(timerL_t *t, uint16_t timeout) {
t->current = internal_counter;
t->timeout = timeout;
}
bool timer_expired(timer_t *t) {
if (t->timeout == 0)
return true;
/* attention: may fail if internal counter is incremented by more than one
* between two calls of timer_expired()! (that is if its is called less than every 10ms*/
if (t->current != internal_counter) {
t->timeout--;
t->current = internal_counter;
}
return false;
}
bool timerL_expired(timerL_t *t) {
if (t->timeout == 0)
return true;
/* attention: may fail if internal counter is incremented by more than one
* between two calls of timer_expired()! */
if (t->current != internal_counter) {
t->timeout--;
t->current = internal_counter;
}
return false;
}
/* timer interrupt function */ISR(TIMER2_COMPA_vect, ISR_NOBLOCK) {
internal_counter++;
}

View File

@ -1,27 +0,0 @@
/* small timer library, uses timer2 */
#ifndef _UTIL_H
#define _UTIL_H
#include <stdint.h>
#include <stdbool.h>
/* structures */
typedef struct {
uint8_t current;
uint8_t timeout;
} timer_t;
typedef struct {
uint16_t current;
uint16_t timeout;
} timerL_t;
/* functions */
void timer_init(void);
void timer_set(timer_t *t, uint8_t timeout);
bool timer_expired(timer_t *t);
void timerL_set(timerL_t *t, uint16_t timeout);
bool timerL_expired(timerL_t *t);
#endif

View File

@ -1,172 +0,0 @@
#include <inttypes.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <stdlib.h>
#include "main.h"
#define ever (;;) /* awesomnes++ */
#include "lib/usart.h"
#include "lib/bughal.h"
#include "lib/util.h"
#include "lib/music.h"
#include "lib/apps.h"
mode_fun mode_funs[MAX_FUNS] = { NULL };
uint8_t mode_num = 0;
/*specialmodes, not in normal mode loop*/
#define MODE_PWDN mode_num //go to sleep
uint8_t OpMode = 0;
uint8_t NextMode = 0;
uint8_t mode_uninitialized = true;
uint8_t mode_last_tick = false;
/*check if mode should be changed (one of the buttons long pressed)*/
void modeswitch_poll(void)
{
if (btn_state(BTNST_LUP, BTN_LEFT)) {
//opmode --
NextMode = OpMode <= 0 ? mode_num - 1 : OpMode - 1;
button_clear(BTN_LEFT);
}
if (btn_state(BTNST_LUP, BTN_RIGHT)) {
//opmode ++
NextMode = (OpMode +1) % mode_num;
button_clear(BTN_RIGHT);
}
if ( btn_state(BTNST_LDN, BTN_RIGHT) &&
btn_state(BTNST_LDN, BTN_LEFT) ) {
NextMode = MODE_PWDN;
}
return;
}
void do_powerDown(void)
{
static timer_t mytimer;
static uint8_t pwdn_state;
static bool ledRon;
uint8_t oldreg;
if (mode_uninitialized) {
mode_uninitialized = false;
pwdn_state = 0;
timer_set(&mytimer, 5);
set_motor(MOTOR_OFF);
ledRon = true;
};
if (timer_expired(&mytimer)) {
switch (pwdn_state) {
case 0:
if (ledRon) {
led_on(LED_L);
led_off(LED_R);
} else {
led_off(LED_L);
led_on(LED_R);
};
ledRon = !ledRon;
timer_set(&mytimer, 6);
if ((btn_state(BTNST_SUP, BTN_RIGHT)
|| btn_state(BTNST_LUP, BTN_RIGHT))
&& (btn_state(BTNST_SUP, BTN_LEFT)
|| btn_state(BTNST_LUP, BTN_LEFT))) {
//both buttons released
led_off(LED_L | LED_R);
pwdn_state = 1;
timer_set(&mytimer, 10);
}
break;
case 1:
music_setNote(NOTE_A, 4);
timer_set(&mytimer, 10);
pwdn_state++;
break;
case 2:
music_setNote(NOTE_F, 4);
timer_set(&mytimer, 5);
pwdn_state++;
break;
case 3:
music_setNote(NOTE_D, 3);
timer_set(&mytimer, 15);
pwdn_state++;
break;
case 4:
music_setNote(NOTE_PAUSE, 4);
timer_set(&mytimer, 1);
pwdn_state++;
break;
case 5: //now we can really power down
// lets switch everything off
oldreg = PCMSK2;
PCIFR = 0;
PCICR |= (1<<PCIE2);
PCMSK2 |= 3; //PCINT16 PCINT17
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei();
sleep_cpu();
PCICR &= ~(1<<PCIE2);
sleep_disable();
PCMSK2 = oldreg;
NextMode = 0;
break;
default:
break;
} //end switch
} //end timer expired
} // end do_powerDown
ISR(PCINT2_vect){ ; }
void __attribute__ ((noreturn)) main(void)
{
/* hardware initialisation: */
init_leds();
init_buzzr();
init_switch();
USART0_Init();
init_motor();
/* software initialisation */
timer_init();
music_init();
/* here the show begins: */
sei();
for ever {
//main polling loop;
button_poll();
if(OpMode < mode_num) {
modeswitch_poll();
}
if (OpMode != NextMode){
mode_last_tick = true;
}
if(OpMode < mode_num) {
mode_funs[OpMode]();
} else {
do_powerDown();
}
if (OpMode != NextMode){
mode_last_tick = false;
mode_uninitialized = true;
OpMode = NextMode;
}
}
}

View File

@ -1,2 +0,0 @@
#pragma once