Compare commits
16 Commits
Author | SHA1 | Date |
---|---|---|
Neale Pickett | dbd4efcdb7 | |
Neale Pickett | bc7c8bb732 | |
Neale Pickett | d2aea85388 | |
Neale Pickett | b8f09108d2 | |
Neale Pickett | e3404275bb | |
Neale Pickett | 01fa654c45 | |
Neale Pickett | 9e0282b792 | |
Neale Pickett | 83d4fdeb70 | |
Neale Pickett | 3022774491 | |
Neale Pickett | bbd0cf2c62 | |
Neale Pickett | cdd491da86 | |
Neale Pickett | 5ff1f4b925 | |
Neale Pickett | b443503e3c | |
Neale Pickett | 97a5c2cebe | |
Neale Pickett | ce4c886008 | |
Neale Pickett | 323d3dddec |
|
@ -0,0 +1,4 @@
|
||||||
|
release
|
||||||
|
*.hex
|
||||||
|
*.elf
|
||||||
|
GNUmakefile
|
|
@ -0,0 +1,17 @@
|
||||||
|
Outstanding
|
||||||
|
-----------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Fixed
|
||||||
|
-----
|
||||||
|
|
||||||
|
1. Scores should not go negative
|
||||||
|
2. Konami Code position doesn't reset on non-sequence button
|
||||||
|
3. It is too easy to mess up scores when adjusting period clock time
|
||||||
|
4. Period clock adjustments take forever
|
||||||
|
5. Make setup mode less confusing
|
||||||
|
6. Allow jam clock adjustments in setup
|
||||||
|
7. Unified build with multiple firmware targets
|
||||||
|
8. Debounce buttons
|
||||||
|
9. Pull-up NES data to prevent going apeshit when you unplug the controller
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright © 2014 Neale Pickett <neale@woozle.org>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
The software is provided "as is", without warranty of any kind, express or
|
||||||
|
implied, including but not limited to the warranties of merchantability,
|
||||||
|
fitness for a particular purpose and noninfringement. In no event shall the
|
||||||
|
authors or copyright holders be liable for any claim, damages or other
|
||||||
|
liability, whether in an action of contract, tort or otherwise, arising from,
|
||||||
|
out of or in connection with the software or the use or other dealings in
|
||||||
|
the software.
|
49
Makefile
49
Makefile
|
@ -1,4 +1,7 @@
|
||||||
PROG = main
|
TARGETS += scoreboard-neale.hex
|
||||||
|
TARGETS += scoreboard-susan1.hex
|
||||||
|
TARGETS += scoreboard-susan2.hex
|
||||||
|
TARGETS += scoreboard-std.hex
|
||||||
|
|
||||||
MCU = attiny84
|
MCU = attiny84
|
||||||
|
|
||||||
|
@ -9,34 +12,34 @@ CFLAGS += -w
|
||||||
|
|
||||||
LDFLAGS += -mmcu=$(MCU)
|
LDFLAGS += -mmcu=$(MCU)
|
||||||
|
|
||||||
AVDFLAGS += -p $(MCU)
|
all: $(TARGETS)
|
||||||
AVDFLAGS += -c usbtiny
|
|
||||||
|
|
||||||
FUSES += -U lfuse:w:0x7f:m
|
scoreboard-%.elf: main.c avr.c config.h avr.h
|
||||||
FUSES += -U hfuse:w:0xdd:m
|
$(CC) $(CFLAGS) -DVARIANT=$* $(LDFLAGS) -o $@ avr.c main.c
|
||||||
FUSES += -U efuse:w:0xff:m
|
|
||||||
|
|
||||||
upload: .upload
|
%.hex: %.elf
|
||||||
|
|
||||||
.upload: $(PROG).hex
|
|
||||||
avrdude $(AVDFLAGS) -U flash:w:$<
|
|
||||||
touch $@
|
|
||||||
|
|
||||||
fuses:
|
|
||||||
avrdude $(AVDFLAGS) $(FUSES)
|
|
||||||
|
|
||||||
main: main.o avr.o
|
|
||||||
|
|
||||||
blink: blink.o avr.o
|
|
||||||
|
|
||||||
avr.o: avr.c config.h
|
|
||||||
|
|
||||||
%.hex: %
|
|
||||||
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $< $@
|
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $< $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(PROG) *.o *.hex .upload
|
rm -f *.elf *.o *.hex .upload
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Helpful targets for development
|
||||||
|
##
|
||||||
|
|
||||||
|
VARIANT = neale
|
||||||
|
|
||||||
|
AVDFLAGS += -p $(MCU)
|
||||||
|
AVDFLAGS += -c usbtiny
|
||||||
|
|
||||||
|
upload: scoreboard-$(VARIANT).hex
|
||||||
|
avrdude $(AVDFLAGS) -U flash:w:$<
|
||||||
|
|
||||||
|
fuses: FUSES += -U lfuse:w:0x7f:m
|
||||||
|
fuses: FUSES += -U hfuse:w:0xdd:m
|
||||||
|
fuses: FUSES += -U efuse:w:0xff:m
|
||||||
|
fuses:
|
||||||
|
avrdude $(AVDFLAGS) $(FUSES)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
LED Roller Derby Scoreboard
|
||||||
|
===========================
|
||||||
|
|
||||||
|
A do-it-yourself LED Roller Derby scoreboard.
|
||||||
|
It's visible in full sunlight,
|
||||||
|
doesn't use a computer at all,
|
||||||
|
and can be easily operated by an 8-year-old.
|
||||||
|
|
||||||
|
If you're looking for a software scoreboard (using a projector)
|
||||||
|
this [list of free derby scoreboard software](http://woozle.org/scoreboard/others.html) will help.
|
||||||
|
|
||||||
|
This scoreboard is operated with a Nintendo controller,
|
||||||
|
and runs on an XBox 360 power supply.
|
||||||
|
The rest of the parts need to be ordered from various sources online.
|
||||||
|
The total should come out to around $200,
|
||||||
|
with plenty of options for upgrades.
|
||||||
|
|
||||||
|
It will take about 6 weeks of work,
|
||||||
|
and requires basic electronics understanding and
|
||||||
|
elementary soldering skills.
|
||||||
|
I provide updated firmware,
|
||||||
|
so unless you feel like modifying the MIT-licensed source code,
|
||||||
|
you don't need to do any programming.
|
||||||
|
|
||||||
|
![Original Build](https://lh3.googleusercontent.com/-xKiVBp0bv70/UuafY7lZxeI/AAAAAAAAd1g/6TlMNSDp9xc/s1600/IMG_20140125_094136.jpg)
|
||||||
|
|
||||||
|
![First duplicate](https://lh5.googleusercontent.com/-Mm23bx2F-wQ/Uip4SGmmzWI/AAAAAAAAMKI/48zmiHN6v6U/s1600/13%2B-%2B1)
|
||||||
|
|
||||||
|
![Second duplicate](https://lh6.googleusercontent.com/-hOKmDB5JRYY/UtXPLuY2bDI/AAAAAAAAdpE/PYxeqHQGxTA/s1600/2014-01-14)
|
||||||
|
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---------
|
||||||
|
|
||||||
|
* [Discussion Group](https://groups.google.com/forum/#!forum/scoreboard-builders) for help from others who've built or are building one.
|
||||||
|
* [Google Drive Folder](https://drive.google.com/folderview?id=0BzovkpI6mzWQNFc4eGN0aGoyTGM&usp=sharing) with
|
||||||
|
schematics, documentation, and firmware releases.
|
||||||
|
* [Firmware Source Code](https://woozle.org/neale/g.cgi/derby/hw-scoreboard)
|
||||||
|
|
||||||
|
|
||||||
|
About Me
|
||||||
|
--------
|
||||||
|
|
||||||
|
I'm Neale Pickett,
|
||||||
|
also known as "Q" in the Derby world.
|
||||||
|
Feel free to [email me](mailto:neale@woozle.org),
|
||||||
|
but the group would be more appropriate for email relating to this scoreboard.
|
||||||
|
|
||||||
|
I've done a lot of [other derby stuff](/derby/)
|
||||||
|
that you may be interested in.
|
8
avr.c
8
avr.c
|
@ -23,7 +23,7 @@ ISR(TIM1_COMPA_vect)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
init(void)
|
avr_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -39,7 +39,13 @@ init(void)
|
||||||
TCCR1B |= _BV(CS11) | _BV(CS10); // prescale: clk_io / 64
|
TCCR1B |= _BV(CS11) | _BV(CS10); // prescale: clk_io / 64
|
||||||
TIMSK1 |= _BV(OCIE1A);
|
TIMSK1 |= _BV(OCIE1A);
|
||||||
|
|
||||||
|
// Pull-up NES data line
|
||||||
|
bit(PORTA, _BV(NESOUT), true);
|
||||||
|
|
||||||
|
// Turn on Power Supply
|
||||||
bit(PORTA, _BV(7), true);
|
bit(PORTA, _BV(7), true);
|
||||||
|
|
||||||
|
PORTB = 0xff;
|
||||||
|
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
2
avr.h
2
avr.h
|
@ -15,6 +15,6 @@
|
||||||
#define nesltch(on) bit(PORTA, _BV(NESLTCH), on)
|
#define nesltch(on) bit(PORTA, _BV(NESLTCH), on)
|
||||||
#define nesout() ((PINA & _BV(NESOUT)) << NESOUT)
|
#define nesout() ((PINA & _BV(NESOUT)) << NESOUT)
|
||||||
|
|
||||||
void init(void);
|
void avr_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
89
config.h
89
config.h
|
@ -4,14 +4,13 @@
|
||||||
#define CLOCK_MHZ 16
|
#define CLOCK_MHZ 16
|
||||||
#define CLOCK_HZ (CLOCK_MHZ * 1000000)
|
#define CLOCK_HZ (CLOCK_MHZ * 1000000)
|
||||||
|
|
||||||
#define SCORE_DIGITS 2
|
#define LINEUP_DEFAULT (-30 * 10)
|
||||||
#define JAM_DIGITS 3
|
#define JAM_DEFAULT (-2 * 60 * 10)
|
||||||
|
#define PERIOD_DEFAULT (-30 * 60 * 10)
|
||||||
|
|
||||||
// Show an indicator (J/L/t) to the left of the jam clock
|
// TPIC uses weird pin names
|
||||||
//#define JAM_INDICATOR
|
#define SRCK SCLK
|
||||||
|
#define RCK SLTCH
|
||||||
// The jam clock is split across the period clock (easier folding, harder wiring)
|
|
||||||
//#define JAM_SPLIT
|
|
||||||
|
|
||||||
// Set these to the PORTA pins you use
|
// Set these to the PORTA pins you use
|
||||||
#define NESCLK 0
|
#define NESCLK 0
|
||||||
|
@ -21,4 +20,80 @@
|
||||||
#define SCLK 4
|
#define SCLK 4
|
||||||
#define SLTCH 5
|
#define SLTCH 5
|
||||||
|
|
||||||
|
#define JAM_DIGITS 3
|
||||||
|
|
||||||
|
#define std 0
|
||||||
|
#define neale 1
|
||||||
|
#define susan1 2
|
||||||
|
#define susan2 3
|
||||||
|
#define robbie 3
|
||||||
|
|
||||||
|
#if VARIANT == neale
|
||||||
|
//
|
||||||
|
// Neale variant
|
||||||
|
//
|
||||||
|
// With Jam indicator, split jam clock, and only 2 score digits.
|
||||||
|
// Also featuring goofy brain wiring.
|
||||||
|
//
|
||||||
|
|
||||||
|
#define SCORE_DIGITS 2
|
||||||
|
#define JAM_INDICATOR
|
||||||
|
#define JAM_SPLIT
|
||||||
|
|
||||||
|
// I wired mine differently and I'm too lazy to fix it.
|
||||||
|
#undef NESCLK
|
||||||
|
#undef NESLTCH
|
||||||
|
#undef NESOUT
|
||||||
|
#undef SIN
|
||||||
|
#undef SCLK
|
||||||
|
#undef SLTCH
|
||||||
|
|
||||||
|
#define SIN 0
|
||||||
|
#define SCLK 1
|
||||||
|
#define SLTCH 2
|
||||||
|
#define NESCLK 3
|
||||||
|
#define NESLTCH 4
|
||||||
|
#define NESOUT 5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#elif VARIANT == susan1
|
||||||
|
//
|
||||||
|
// Susan 1 variant
|
||||||
|
//
|
||||||
|
// Like the neale variant but with correct brain wiring
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#define SCORE_DIGITS 2
|
||||||
|
#define JAM_INDICATOR
|
||||||
|
#define JAM_SPLIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#elif VARIANT == susan2
|
||||||
|
//
|
||||||
|
// Susan 2 variant
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#define SCORE_DIGITS 3
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
//
|
||||||
|
// Default variant
|
||||||
|
//
|
||||||
|
// Nobody has built this yet!
|
||||||
|
// But it's the one described by the instructions.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#define SCORE_DIGITS 3
|
||||||
|
#define JAM_SPLIT
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="129.57692"
|
||||||
|
height="209.82599"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.4 r9939"
|
||||||
|
sodipodi:docname="controller-conn.svg">
|
||||||
|
<defs
|
||||||
|
id="defs4" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.83718329"
|
||||||
|
inkscape:cx="49.790255"
|
||||||
|
inkscape:cy="119.40543"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1259"
|
||||||
|
inkscape:window-height="839"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-298.3437,-356.56045)">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
d="m 308.43035,525.01817 c 0.0224,12.61936 10.90299,30.79285 29.01664,31.18674 18.11366,0.3939 46.59996,0.14703 57.65053,-1.01178 12.80286,-1.34256 22.45738,-21.53441 22.52553,-31.36944 0,0 0.64469,-87.18796 0,-91.56654 -0.64469,-4.37857 -13.29505,-15.39673 -28.53212,-31.75759 -15.23706,-16.36086 -25.30565,-33.68303 -48.51772,-33.94468 -17.74986,-0.20008 -31.03771,23.34467 -31.76769,28.18425 -0.72997,4.83959 -0.37517,130.27904 -0.37517,130.27904 z"
|
||||||
|
id="path3050"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="szsszsszs" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3820"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-114.92672,-134.95682)" />
|
||||||
|
<path
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-114.6281,-95.538929)"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
id="path3822"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3824"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-114.92672,-55.523797)" />
|
||||||
|
<path
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-114.6281,-15.508665)"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
id="path3826"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3828"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-74.314347,-94.344447)" />
|
||||||
|
<path
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-74.612967,-54.329315)"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
id="path3830"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3832"
|
||||||
|
sodipodi:cx="342.81619"
|
||||||
|
sodipodi:cy="402.56421"
|
||||||
|
sodipodi:rx="8.361371"
|
||||||
|
sodipodi:ry="8.6599913"
|
||||||
|
d="m 351.17756,402.56421 c 0,4.78278 -3.74351,8.65999 -8.36137,8.65999 -4.61786,0 -8.36137,-3.87721 -8.36137,-8.65999 0,-4.78278 3.74351,-8.65999 8.36137,-8.65999 4.61786,0 8.36137,3.87721 8.36137,8.65999 z"
|
||||||
|
transform="matrix(1.335243,0,0,1.335243,-74.314347,-14.314183)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.5 KiB |
|
@ -0,0 +1,217 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="744.09448819"
|
||||||
|
height="1052.3622047"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.4 r9939"
|
||||||
|
sodipodi:docname="New document 1">
|
||||||
|
<defs
|
||||||
|
id="defs4" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4"
|
||||||
|
inkscape:cx="418.97372"
|
||||||
|
inkscape:cy="520"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1436"
|
||||||
|
inkscape:window-height="882"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="14"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#e0cece;fill-opacity:1;fill-rule:nonzero;"
|
||||||
|
id="rect3050"
|
||||||
|
width="600"
|
||||||
|
height="259.28571"
|
||||||
|
x="67.14286"
|
||||||
|
y="400.93362"
|
||||||
|
ry="1.9140695" />
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3052"
|
||||||
|
width="561.42859"
|
||||||
|
height="199.28572"
|
||||||
|
x="85.714287"
|
||||||
|
y="442.36218"
|
||||||
|
ry="1.9140695" />
|
||||||
|
<rect
|
||||||
|
style="fill:#e0cece;fill-opacity:1;fill-rule:nonzero;"
|
||||||
|
id="rect3084"
|
||||||
|
width="169.28572"
|
||||||
|
height="58.57143"
|
||||||
|
x="262.14285"
|
||||||
|
y="556.64789"
|
||||||
|
ry="1.9140695" />
|
||||||
|
<g
|
||||||
|
id="g3094">
|
||||||
|
<rect
|
||||||
|
ry="1.9140695"
|
||||||
|
y="497.36218"
|
||||||
|
x="150"
|
||||||
|
height="115"
|
||||||
|
width="45.714287"
|
||||||
|
id="rect3090"
|
||||||
|
style="fill:#e0cece;fill-opacity:1;fill-rule:nonzero" />
|
||||||
|
<rect
|
||||||
|
transform="matrix(0,1,-1,0,0,0)"
|
||||||
|
style="fill:#e0cece;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3092"
|
||||||
|
width="45.714287"
|
||||||
|
height="115"
|
||||||
|
x="532.00507"
|
||||||
|
y="-230.35715"
|
||||||
|
ry="1.9140695" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3072">
|
||||||
|
<rect
|
||||||
|
ry="1.9140695"
|
||||||
|
y="548.79077"
|
||||||
|
x="457.85715"
|
||||||
|
height="65.714287"
|
||||||
|
width="65"
|
||||||
|
id="rect3054"
|
||||||
|
style="fill:#e0cece;fill-opacity:1;fill-rule:nonzero" />
|
||||||
|
<path
|
||||||
|
transform="translate(-75,0)"
|
||||||
|
d="m 592.14287,582.36218 a 26.428572,26.428572 0 1 1 -52.85715,0 26.428572,26.428572 0 1 1 52.85715,0 z"
|
||||||
|
sodipodi:ry="26.428572"
|
||||||
|
sodipodi:rx="26.428572"
|
||||||
|
sodipodi:cy="582.36218"
|
||||||
|
sodipodi:cx="565.71429"
|
||||||
|
id="path3060"
|
||||||
|
style="fill:#d40000;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
sodipodi:type="arc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3076"
|
||||||
|
transform="translate(75,0)">
|
||||||
|
<rect
|
||||||
|
style="fill:#e0cece;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3078"
|
||||||
|
width="65"
|
||||||
|
height="65.714287"
|
||||||
|
x="457.85715"
|
||||||
|
y="548.79077"
|
||||||
|
ry="1.9140695" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#d40000;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="path3080"
|
||||||
|
sodipodi:cx="565.71429"
|
||||||
|
sodipodi:cy="582.36218"
|
||||||
|
sodipodi:rx="26.428572"
|
||||||
|
sodipodi:ry="26.428572"
|
||||||
|
d="m 592.14287,582.36218 c 0,14.5961 -11.83248,26.42857 -26.42858,26.42857 -14.59609,0 -26.42857,-11.83247 -26.42857,-26.42857 0,-14.59609 11.83248,-26.42857 26.42857,-26.42857 14.5961,0 26.42858,11.83248 26.42858,26.42857 z"
|
||||||
|
transform="translate(-75,0)" />
|
||||||
|
</g>
|
||||||
|
<rect
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3086"
|
||||||
|
width="49.285713"
|
||||||
|
height="18.571428"
|
||||||
|
x="286.42856"
|
||||||
|
y="577.36218"
|
||||||
|
ry="1.9140695"
|
||||||
|
rx="7" />
|
||||||
|
<rect
|
||||||
|
rx="7"
|
||||||
|
ry="1.9140695"
|
||||||
|
y="577.36218"
|
||||||
|
x="358.57141"
|
||||||
|
height="18.571428"
|
||||||
|
width="49.285713"
|
||||||
|
id="rect3088"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero" />
|
||||||
|
<g
|
||||||
|
id="g3102"
|
||||||
|
transform="translate(-0.35713959,-1.0714188)">
|
||||||
|
<rect
|
||||||
|
ry="1.9140695"
|
||||||
|
y="501.64789"
|
||||||
|
x="152.85715"
|
||||||
|
height="108.57143"
|
||||||
|
width="40.714287"
|
||||||
|
id="rect3098"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero" />
|
||||||
|
<rect
|
||||||
|
transform="matrix(0,1,-1,0,0,0)"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3100"
|
||||||
|
width="40.714287"
|
||||||
|
height="108.57143"
|
||||||
|
x="535.57648"
|
||||||
|
y="-227.5"
|
||||||
|
ry="1.9140695" />
|
||||||
|
</g>
|
||||||
|
<rect
|
||||||
|
style="fill:#76745b;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3106"
|
||||||
|
width="170.71428"
|
||||||
|
height="28.571428"
|
||||||
|
x="261.42856"
|
||||||
|
y="515.93365"
|
||||||
|
ry="1.9140695"
|
||||||
|
rx="2" />
|
||||||
|
<rect
|
||||||
|
rx="2"
|
||||||
|
ry="1.9140695"
|
||||||
|
y="442.36221"
|
||||||
|
x="261.42856"
|
||||||
|
height="28.571428"
|
||||||
|
width="170.71428"
|
||||||
|
id="rect3108"
|
||||||
|
style="fill:#76745b;fill-opacity:1;fill-rule:nonzero" />
|
||||||
|
<rect
|
||||||
|
style="fill:#76745b;fill-opacity:1;fill-rule:nonzero"
|
||||||
|
id="rect3110"
|
||||||
|
width="170.71428"
|
||||||
|
height="28.571428"
|
||||||
|
x="261.42856"
|
||||||
|
y="478.79077"
|
||||||
|
ry="1.9140695"
|
||||||
|
rx="2" />
|
||||||
|
<rect
|
||||||
|
rx="2"
|
||||||
|
ry="1.9140695"
|
||||||
|
y="623.79077"
|
||||||
|
x="261.42856"
|
||||||
|
height="17.857143"
|
||||||
|
width="170.71428"
|
||||||
|
id="rect3112"
|
||||||
|
style="fill:#76745b;fill-opacity:1;fill-rule:nonzero" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.0 KiB |
139
main.c
139
main.c
|
@ -21,21 +21,20 @@
|
||||||
volatile uint32_t jiffies = 0; // Elapsed time in deciseconds (tenths of a second)
|
volatile uint32_t jiffies = 0; // Elapsed time in deciseconds (tenths of a second)
|
||||||
volatile bool tick = false; // Set high when jiffy clock ticks
|
volatile bool tick = false; // Set high when jiffy clock ticks
|
||||||
|
|
||||||
|
|
||||||
// Clocks are in deciseconds
|
// Clocks are in deciseconds
|
||||||
uint16_t score_a = 0;
|
int16_t score_a = 0;
|
||||||
uint16_t score_b = 0;
|
int16_t score_b = 0;
|
||||||
int16_t period_clock = -(30 * 60 * 10);
|
int16_t period_clock = PERIOD_DEFAULT;
|
||||||
int16_t jam_duration = -(2 * 60 * 10);
|
int16_t jam_duration = JAM_DEFAULT;
|
||||||
int16_t lineup_duration = (-30 * 10);
|
int16_t lineup_duration = LINEUP_DEFAULT;
|
||||||
int16_t jam_clock = 0;
|
int16_t jam_clock = JAM_DEFAULT;
|
||||||
enum {
|
enum {
|
||||||
SETUP = 0,
|
TIMEOUT = 0,
|
||||||
JAM,
|
JAM,
|
||||||
LINEUP,
|
LINEUP,
|
||||||
TIMEOUT,
|
|
||||||
KONAMI
|
KONAMI
|
||||||
} state = SETUP;
|
} state = TIMEOUT;
|
||||||
|
bool setup = true;
|
||||||
|
|
||||||
|
|
||||||
// NES Controller buttons
|
// NES Controller buttons
|
||||||
|
@ -65,17 +64,17 @@ const uint8_t seven_segment_digits[] = {
|
||||||
0x7b, 0x60, 0x37, 0x76, 0x6c, 0x5e, 0x5f, 0x70, 0x7f, 0x7e
|
0x7b, 0x60, 0x37, 0x76, 0x6c, 0x5e, 0x5f, 0x70, 0x7f, 0x7e
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t setup_digits[] = {
|
|
||||||
// [ = ]
|
|
||||||
0x1b, 0x12, 0x72
|
|
||||||
};
|
|
||||||
|
|
||||||
// keyed by state
|
// keyed by state
|
||||||
const uint8_t indicator[] = {
|
const uint8_t indicator[] = {
|
||||||
// '' J L T -
|
// t, J, L, -
|
||||||
0x00, 0x63, 0x0b, 0x0f, 0x04
|
0x0f, 0x63, 0x0b, 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define max(a, b) ((a)>(b)?(a):(b))
|
||||||
|
#define min(a, b) ((a)<(b)?(a):(b))
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
latch()
|
latch()
|
||||||
{
|
{
|
||||||
|
@ -154,11 +153,6 @@ write_pclock()
|
||||||
write(0);
|
write(0);
|
||||||
write(0);
|
write(0);
|
||||||
write(0);
|
write(0);
|
||||||
} else if (state == SETUP) {
|
|
||||||
write(setup_digits[2]);
|
|
||||||
write(setup_digits[1]);
|
|
||||||
write(setup_digits[1]);
|
|
||||||
write(setup_digits[0]);
|
|
||||||
} else {
|
} else {
|
||||||
write_num(pclk, 4);
|
write_num(pclk, 4);
|
||||||
}
|
}
|
||||||
|
@ -238,20 +232,40 @@ nesprobe()
|
||||||
void
|
void
|
||||||
update_controller()
|
update_controller()
|
||||||
{
|
{
|
||||||
static uint8_t last_val = 0;
|
static uint8_t last_held = 0;
|
||||||
static uint32_t last_change = 0;
|
static uint32_t last_change = 0;
|
||||||
static uint32_t last_typematic = 0;
|
static uint32_t last_typematic = 0;
|
||||||
uint8_t cur;
|
uint8_t held;
|
||||||
uint8_t pressed;
|
uint8_t pressed;
|
||||||
|
int typematic = 0;
|
||||||
int inc = 1;
|
int inc = 1;
|
||||||
|
|
||||||
cur = nesprobe();
|
held = nesprobe();
|
||||||
pressed = (last_val ^ cur) & cur;
|
pressed = (last_held ^ held) & held;
|
||||||
if (last_val != cur) {
|
|
||||||
last_change = jiffies;
|
|
||||||
last_val = cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Set up typematic acceleration
|
||||||
|
if (last_held != held) {
|
||||||
|
// Debounce
|
||||||
|
if (last_change == jiffies) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
last_change = jiffies;
|
||||||
|
last_typematic = jiffies;
|
||||||
|
last_held = held;
|
||||||
|
typematic = 1;
|
||||||
|
} else if (jiffies > last_typematic) {
|
||||||
|
last_typematic = jiffies;
|
||||||
|
if (jiffies - last_change < 6) {
|
||||||
|
typematic = 0;
|
||||||
|
} else if (jiffies - last_change < 40) {
|
||||||
|
typematic = 1;
|
||||||
|
} else if (jiffies - last_change < 80) {
|
||||||
|
typematic = 10;
|
||||||
|
} else {
|
||||||
|
typematic = 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pressed == konami_code[konami_pos]) {
|
if (pressed == konami_code[konami_pos]) {
|
||||||
konami_pos += 1;
|
konami_pos += 1;
|
||||||
|
|
||||||
|
@ -262,11 +276,21 @@ update_controller()
|
||||||
} else if (konami_pos > 3) {
|
} else if (konami_pos > 3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (pressed) {
|
||||||
|
konami_pos = 0;
|
||||||
}
|
}
|
||||||
// Select means subtract
|
// Select means subtract
|
||||||
if (cur & BTN_SELECT) {
|
if (held & BTN_SELECT) {
|
||||||
inc = -1;
|
inc = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (setup && (held & BTN_START) && (pressed & BTN_SELECT)) {
|
||||||
|
jam_duration += 30 * 10;
|
||||||
|
if (jam_duration > -60 * 10) {
|
||||||
|
jam_duration = -120 * 10;
|
||||||
|
}
|
||||||
|
jam_clock = jam_duration;
|
||||||
|
}
|
||||||
|
|
||||||
if ((pressed & BTN_A) && ((state != JAM) || (jam_clock == 0))) {
|
if ((pressed & BTN_A) && ((state != JAM) || (jam_clock == 0))) {
|
||||||
state = JAM;
|
state = JAM;
|
||||||
|
@ -283,27 +307,31 @@ update_controller()
|
||||||
jam_clock = 1;
|
jam_clock = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((state == TIMEOUT) || (state == SETUP)) {
|
if ((held & BTN_START) && (state == TIMEOUT)) {
|
||||||
uint8_t v = pressed;
|
if (held & BTN_UP) {
|
||||||
|
period_clock -= typematic * 10;
|
||||||
if ((jiffies - last_change > 10) && (last_typematic < jiffies)) {
|
|
||||||
v = cur;
|
|
||||||
last_typematic = jiffies;
|
|
||||||
}
|
}
|
||||||
if (v & BTN_UP) {
|
if (held & BTN_DOWN) {
|
||||||
period_clock -= 10;
|
period_clock += typematic * 10;
|
||||||
}
|
}
|
||||||
if (v & BTN_DOWN) {
|
|
||||||
period_clock += 10;
|
period_clock = min(period_clock, 0);
|
||||||
|
period_clock = max(period_clock, -90 * 30 * 10);
|
||||||
|
} else {
|
||||||
|
// Score adjustment and clock adjustment are mutually exclusive
|
||||||
|
if (held & BTN_LEFT) {
|
||||||
|
score_a += typematic * inc;
|
||||||
|
score_a = max(score_a, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (held & BTN_RIGHT) {
|
||||||
|
score_b += typematic * inc;
|
||||||
|
score_b = max(score_b, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressed & BTN_LEFT) {
|
if (state != TIMEOUT) {
|
||||||
score_a += inc;
|
setup = false;
|
||||||
}
|
|
||||||
|
|
||||||
if (pressed & BTN_RIGHT) {
|
|
||||||
score_b += inc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,16 +342,6 @@ update_controller()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
setup()
|
|
||||||
{
|
|
||||||
// The TLC5941 required some setup.
|
|
||||||
// The TPIC doesn't.
|
|
||||||
// Hooray.
|
|
||||||
|
|
||||||
PORTB = 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
loop()
|
loop()
|
||||||
{
|
{
|
||||||
|
@ -337,8 +355,6 @@ loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case SETUP:
|
|
||||||
break;
|
|
||||||
case JAM:
|
case JAM:
|
||||||
case LINEUP:
|
case LINEUP:
|
||||||
if (period_clock) {
|
if (period_clock) {
|
||||||
|
@ -346,7 +362,7 @@ loop()
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case TIMEOUT:
|
case TIMEOUT:
|
||||||
if (jam_clock) {
|
if (jam_clock && !setup) {
|
||||||
jam_clock += 1;
|
jam_clock += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,8 +374,7 @@ loop()
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
init();
|
avr_init();
|
||||||
setup();
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue