Cleanup, reorganization

This commit is contained in:
2014-12-23 01:12:21 +01:00
parent e78d91a900
commit dbdcefea38
223 changed files with 1260 additions and 660 deletions
+437
View File
@@ -0,0 +1,437 @@
//Imitace casovane bomby, Ondrej Hruska (c) 2010-2012
//-------------------------------------------------
// Zapojeni:
// +------u------+
// reset --+ /RST Vcc +-- napajeni +5V
// Anoda jednotek --+ PD0 PB7 +-- segment D
// Anoda desitek --+ PD1 PB6 +-- sedment E
// (nezapojeno) --+ XT2 PB5 +-- segment C
// (nezapojeno) --+ XT1 PB4 +-- segment H
// drat --+ PD2 PB3 +-- segment G
// drat --+ PD3 PB2 +-- segment A
// drat --+ PD4 PB1 +-- segment F
// drat --+ PD5 PB0 +-- segment B
// GND --+ GND PD6 +-- output signal (vybuch)
// +-------------+
//
// Nazvy segmentu na displeji:
// ---A---
// | |
// F B
// | |
// ---G---
// | |
// E C
// | |
// ---D--- H
//
/*
Ports:
PORTB - segments
PD0 anode L
PD1 anode H
PD2 w0
PD3 w1
PD4 w2
PD5 w3
PD6 BOMB
PD7 -nc-
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdlib.h>
#include <util/delay_basic.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
void updateDisplayBuffer();
void ports_init();
void timer_init();
void multiplex(uint8_t times);
void boom();
void halt();
void init_animation();
/*FUSES =
{
.low = 0xE4,
.high = 0xDF
};*/
/** initial number of intervals */
#define INIT_MINS 60
/** seconds in one interval */
#define INIT_MAX 60
/** seconds in one interval */
#define RAPID_MAX 8
/** seconds in one interval */
#define RAPID_COUNT 5
/* MACROS */
/** set one hertz interrupt */
#define timer_enable() TIMSK=(1<<OCIE1A)
/** disable timer interrupt */
#define timer_disable() TIMSK=0
// segments DEChGAFB
#define B (1<<0)
#define F (1<<1)
#define A (1<<2)
#define G (1<<3)
#define H (1<<4)
#define C (1<<5)
#define E (1<<6)
#define D (1<<7)
// anodes
#define AL 1
#define AH 0
// wires
#define W0 2
#define W1 3
#define W2 4
#define W3 5
//bomb pin
#define BM 6
// pin groups
#define WIRES ((1<<W0)|(1<<W1)|(1<<W2)|(1<<W3))
#define ANODES ((1<<AL)|(1<<AH))
#define BOMB (1<<BM)
#define SEGMENTS 0xFF
uint8_t num2seg[10]; // array for num -> 7seg translation
#define BLANK 0
/* VARIABLES */
uint8_t EEMEM wireset;
uint8_t volatile cnt; // time counter (countdown)
uint8_t volatile cnt_interval; // current interval counter in seconds
uint8_t volatile cnt_interval_max; // length of current interval in seconds
uint8_t disp_H; // display buffer - ones
uint8_t disp_L; // tens
uint8_t volatile wires;
uint8_t volatile last_wires;
uint8_t is_one_digit;
uint8_t wire_shutdown; //absolute mask
uint8_t wire_boom;
//remaining two are for RAPID COUNTDOWN (30 s)
/* INTERRUPT VECTORS */
/** one second interrupt */
ISR(TIMER1_COMPA_vect){
cnt_interval++;
if(!is_one_digit) disp_H ^= H;
disp_L ^= H;
if(cnt_interval >= cnt_interval_max){
cnt_interval=0;
cnt--;
//to tens and ones
updateDisplayBuffer();
}
//time over?
if(cnt==0){
boom();
}
}
/** MAIN */
int main()
{
cnt = INIT_MINS;
cnt_interval = 0;
cnt_interval_max = INIT_MAX;
is_one_digit = 0;
disp_H = 0;
disp_L = 0;
last_wires = WIRES;
num2seg[0] = A|B|C|D|E|F;
num2seg[1] = B|C;
num2seg[2] = A|B|G|E|D;
num2seg[3] = A|B|G|C|D;
num2seg[4] = F|G|B|C;
num2seg[5] = A|F|G|C|D;
num2seg[6] = A|C|D|E|F|G;
num2seg[7] = A|B|C;
num2seg[8] = A|B|C|D|E|F|G;
num2seg[9] = A|B|C|D|F|G;
timer_disable();
timer_init();
timer_reset();
ports_init();
init_animation();
last_wires = ~(PIND & WIRES);
//wire set
//read wireset number
uint8_t wireset_r = eeprom_read_byte((uint8_t*)&wireset);
//go to next one, reset if >11
wireset_r++;
if(wireset_r>=12) wireset_r=0;
//store new value
eeprom_write_byte((uint8_t*)&wireset,wireset_r);
//select wires for wireset
uint8_t ws_boom[12] = {(1<<W1), (1<<W0), (1<<W2), (1<<W0), (1<<W3), (1<<W0), (1<<W1), (1<<W1), (1<<W3), (1<<W2), (1<<W2), (1<<W3)};
uint8_t ws_shutdown[12] = {(1<<W0), (1<<W3), (1<<W1), (1<<W2), (1<<W2), (1<<W1), (1<<W3), (1<<W2), (1<<W1), (1<<W0), (1<<W3), (1<<W0)};
wire_boom = ws_boom[wireset_r];
wire_shutdown = ws_shutdown[wireset_r];
updateDisplayBuffer();
timer_enable();
sei();
uint8_t diff;
while(1){
multiplex(50);
//check wire
wires = ~(PIND & WIRES);
diff = wires ^ last_wires;
//wire changed
if(diff != 0){
//shutdown wire was connected last time
if( (last_wires & wire_shutdown) != 0 && (diff & wire_shutdown) != 0){
//shutdown wire!
halt();
exit(0);
}else if( (last_wires & wire_boom) != 0 && (diff & wire_boom) != 0){
//bomb launched!
boom();
exit(0);
}else{
//rapid
if(cnt_interval_max > RAPID_MAX){
cnt_interval_max = RAPID_MAX;
if(cnt>RAPID_COUNT){
cnt = RAPID_COUNT;
cnt_interval = 0;
timer_reset();
updateDisplayBuffer();
}
}
}
}
last_wires = wires;
}
cli();
return 0;
}
/** put corrent segments into display buffer (from cnt) */
void updateDisplayBuffer(){
div_t foo = div((int)cnt,10);
//keep decimal dots
disp_H = (disp_L & H) | num2seg[foo.quot];
disp_L = (disp_L & H) | num2seg[foo.rem];
if(foo.quot == 0){
disp_H = 0;
is_one_digit = 1;
}else{
is_one_digit = 0;
}
}
/** show display, repeat "times" x */
void multiplex(uint8_t times){
for(; times>0; times--){
PORTB = ~disp_L; // TENS segments; common anode, needs invert
PORTD &= ~ANODES; // reset anodes
PORTD |= (1<<AL); // turn TENS anode on
_delay_loop_1(255); // wait
PORTB = ~disp_H; // ONES segments; common anode, needs invert
PORTD &= ~ANODES; // reset anodes
PORTD |= (1<<AH); // turn ONES anode on
_delay_loop_1(255); // wait
}
PORTB = ~BLANK; //display off
}
void multiplex_pwm(uint8_t times, uint8_t delay){
for(; times>0; times--){
PORTB = ~disp_L; // TENS segments; common anode, needs invert
PORTD &= ~ANODES; // reset anodes
PORTD |= (1<<AL); // turn TENS anode on
_delay_loop_1(255-delay); // wait
PORTD &= ~(1<<AL);
_delay_loop_1(delay);
PORTB = ~disp_H; // ONES segments; common anode, needs invert
PORTD &= ~ANODES; // reset anodes
PORTD |= (1<<AH); // turn ONES anode on
_delay_loop_1(255-delay); // wait
PORTD &= ~(1<<AH);
_delay_loop_1(delay);
}
PORTB = ~BLANK; //display off
}
/** the boom */
void boom(){
cli();
PORTD |= BOMB; //activate bomb
PORTD &= ~WIRES; // turn off wire pullups
disp_H = 0b01010101;
disp_L = 0b10101010;
while(1){
disp_H ^= 0xff;
disp_L ^= 0xff;
longmpx();
}
// PORTD |= ANODES; // turn both anodes on
// PORTB = 0x00; // all segments on
// __asm__("cli");
exit(0);
}
/** the boom */
void halt(){
PORTD &= ~WIRES;
for(uint8_t volatile pause=0; pause < 0xff; pause++){
multiplex_pwm(40,pause);
}
//animation
PORTD = (1<<AL); // higher part
PORTB = ~H; // show one dot
timer_disable();
cli();
for(;;){}
exit(0);
}
/** set up ports */
void ports_init(){
DDRB = SEGMENTS; // segments to output
PORTB = SEGMENTS; // turned off (cathodes!)
DDRD = ANODES|BOMB; // set outputs
PORTD = WIRES; // enable wire pullups
}
/** set timer1 to one hertz */
void timer_init(){
TCCR1A = 0;
TCCR1B=(1<<WGM12)|(1<<CS12);
OCR1AH=0b01111010;
OCR1AL=0b00010010;
}
/** clear timer */
void timer_reset(){
TCNT0 = 0;
}
void longmpx(){
for(uint8_t i=2; i>0; i--){
multiplex(250);
}
}
/** animation on startup */
void init_animation(){
disp_H = BLANK;
disp_L = BLANK;
for(uint8_t i=0; i<10; i++){
disp_H ^= 0xff;
disp_L ^= 0xff;
longmpx();
}
disp_H = BLANK;
disp_L = BLANK;
_delay_loop_1(255);
}
+74
View File
@@ -0,0 +1,74 @@
PRG = main
MCU_TARGET = attiny2313
OPTIMIZE = 2
LFUSE = 0xE4
HFUSE = 0xDF
DEFS =-std=gnu99 -funsigned-char -funsigned-bitfields -ffunction-sections -fpack-struct -fshort-enums -ffreestanding --combine -fwhole-program -fno-inline-small-functions -fno-split-wide-types -fno-tree-scev-cprop -Wl,--relax,--gc-sections
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
OBJ = $(PRG).o
override CFLAGS = -g2 -Wall -O$(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
# program: $(PRG).elf lst hex
#
all: $(PRG).elf lst eeprom
$(PRG).elf: $(OBJ)
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
avr-size -C -d --mcu=$(MCU_TARGET) $(PRG).elf
lst: $(PRG).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
hex: $(PRG).hex lst
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
install: wflash wfuses
install_ee: weeprom
install_fl: wflash
install_fu: wfuses
wflash: $(PRG).hex
avrdude -P usb -c dragon_isp -p $(MCU_TARGET) -B 16 -U flash:w:$(PRG).hex
wfuses:
avrdude -P usb -c dragon_isp -p $(MCU_TARGET) -B 16 -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m
weeprom: ehex
avrdude -P usb -c dragon_isp -p $(MCU_TARGET) -B 16 -U lfuse:w:$(LFUSE):m -U eeprom:w:$(PRG)_eeprom.hex
ee: ehex
eeprom: ehex
ehex: $(PRG)_eeprom.hex
%_eeprom.hex: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
clean:
rm -f *.o $(PRG).elf *.hex *.lst *~
term:
avrdude -P usb -c dragon_isp -p $(MCU_TARGET) -B 16 -t