1DPong
|
Contents
The Goal[edit]
2012 was a really good year for the hobbyist, cheap dev. boards grown faster than mold on a forgotten sammich in a hot summer. Like (I guess) a lot of wannabe Hardware hackers the “Whoah, so cheap ! let's get this !” phenomenon hit me more than once in 2012... So goal is simple : learning about them in a kinda fun way.
The Story[edit]
I, like almost everybody, happen to have a good ole duino (clone, avr 328p based) I use for quick'n'dirty programing (eeprom dumps/reprogs of buspirate unmanaged protocols and whatnot, this sort of stuff).
Last year, for an event happening at my local HS I made a little Monodimensional pong. Really quick to do with a duino (some 595 shift registers, some leds, 2 switches, 3 resistors, a bit of perfboard, not a lot...)... unfortunately I was late because of the organization of the aforementioned event. This little game was (of course) arduino driven.
So, this program (yeah call it sketch if you want<ref name="#17" />) regroups the (I think) most common tasks needed in uC usage :
- ADC reading (to do some (bad) random)
- Timing management
- Digital Write
- Interrupts
packed in a “GLO --I'm unable to have footnotes working, see ... foot of the page--”... muuuuutch more rewarding than hello world over uart or blinking leds in both terms of things learned and rewards in the physical world (push button at the right time = LEDSs blinks in the other way or adversary scores > 1 LED blinks even if you like to dance on 1 leg, rolled in ham under the full moon).
The Things[edit]
So I happened to have this bunch of boards laying on my desk/workbench, unused, just having to go through the “learning process” for each of these :
- STM32F4 discovery (arm based)
- Stellaris Launchpad (arm based)
- MSP430 Launchpad (msp430)
- A nameless cypress cy7c68013a board (8051 based)
The Hardware[edit]
Like I said it's not really complicated,
ref | value | Item count |
---|---|---|
D1..D56 | LED | 56 |
R1,R2 | 10k | 2 |
R3 | 220 | 1 |
SW1,SW2 | momentary switch | 2 |
U2 | 74HCT595<ref name="74HCT595" /> | 1 |
U3..U8 | 74HC595 | 6 |
board in Kicad :
File:1dpong.board.tar.gz
As few licence this board needs it's licenced CERN OHL 1.11
The original prototype (and still only live exemple) is … less clean
Notes[edit]
On the following programs I didn't use the onboard SPI modules (all boards are having one in a form or another) for a simple reason, most of them doesn't support outputting 1 bit at a time ( one byte is ok ). I could have used these but the would have prevented be from being able to make the lighten led go forth with 1 simple clock cycle (the clocking being taken care of by the SPI module)... anyway there would have been ways … i'm just lazy.
What the ...duino !?![edit]
The board[edit]
Official[1], volksduino, breaduino, your call. I went with a perfboarded breaduino (328p) Won't comment on the more popular protoboard around we all love.
The Development Environment[edit]
apt-get install arduino /.
Nameless 8051 / cy7c68013a[edit]
The board[edit]
Not mutch more than the minimal dev board for the cy7c68013a[2], this is a USB dedicated enhanced 8051[3] capable of native USB2. With a little EEProm change this 12$-from-your-favorite-dirt-cheap-chinese-provider board can “become” a 150$ 24Mhz 8 channel logic analyzer with an unpronounceable name...
The Development Environment[edit]
Code for this board can be compiled with sdcc, FX2 usb dedicated functionalities can be accessed by the use of an open source lib called fx2lib (git clone [4]). The progamming tool I found to be the more flexible (because it's possible to set the VID & PID of the board, more practical if the current eeprom is set to “logic analyzer clone” mode) is CycFX2Prog[5]
Detail on usage can be found in the cypress makefile in the package.
At the moment of the writing my distro's (the one with the red swirl thingy ;) ) packaged sdcc was subject to a bug (yeah sid breaking toys... not a surprise) impacting pushing of the accumulator registry in ISR routines (interrupt management callbacks)[6].
Recommended readings :
EZ-USB® FX2 Technical Reference Manual
MSP430 Launchpad[edit]
The Board[edit]
MSP430 family is quite interresting and have a wide range of application in the low power game, spanning from watches and other wearables to aerospace. Plenty of clocks, timers, cheap chips , even have an arduino like IDE available (energia). The only thing that can be reproached to this board is the relative frailty of the usb chip (TUSB3410, seems to be related to power supply) that is driving the programmer part but at 8$ (used to be 5$) a board that's not something really important (especially given that the programmer part is sporting another msp that can be salvaged (MSP430F1612 but in a not so practical smd package) to make a goodfet or something else.
The Development Environment[edit]
Apt-get install gcc-msp430 mspdebug
Stellaris Launchpad[edit]
The board[edit]
This board1 hosts an ARM LM4F120 a TI implementation of the ARM architecture, more precisely the Cortex M4 Variant, a nice 32bit processor running at 80MHz. As with almost all ARM processor (since ARM is a fabless company, ie. They only sell the “plans” for their architecture, leaving making the chips themselves to other companies) the making company usually stuff these with peripheral to address a particular market and distinguish from the other companies implementing the same architecture. After release the chip have been rename to TIVA by TI, go figure, this is purely a re-branding thing ,the chips are the same. This µC[7] have : Analog comparator,multi step ADC,CAN,eeprom & flash inside,hardware fpu, ethernet, i2c, spi, NVIC (neat ARM interrupt manager), PWM, UART, USB client & OTG (this particular variant doesn't support host),Temperature sensor, 35+ GPIO & more The bord comes with : secondary micro USB port, an RGB led, 2 switches So, TI's implementation (in addition to be a cheapo one) have quite a bit of added peripherals and also a really practical library to use them that is embedded into the silicon itself. Incidentally TI also provide a really neat series of video courses to learn to use their processor.
The Development Environment[edit]
A really neat thing from ARM is that, since they provide the architecture they also provide the compiler[8]. TI also provides a library to use their processor, sadly it's not really neatly packed for use with gcc (but entirely compatible, just not packed in a practical way). It can be downloaded on the TI website[9] To flash it I use lm4flash[10] This board is compatible with openocd : $Openocd --file /usr/local/share/openocd/scripts/board/ek-lm4f120xl.cfg & Then connect to the stub in arm-none-eabi-gdb
STM32F4 Discovery[edit]
The board[edit]
This board hosts an STM32F407VGT6, a ST Microelectronics implementation... blah blah, same thing as the stellaris board, “just” even faster (168MHz) with plenty of peripherals This µC[11] have : hardware FPU,ADC,DAC with speaker driver, SPI,I²C,UART,CAN,up to 17 timers, DMA, Host/client/OTG USB,Ethernet, RNG, CRC, hardware RTC, integrated flash & SRAM, audio dedicated peripherals, SDIO, Temperature sensor, 50+ GPIO & more... The board comes with : secondary micro USB port, mini jack, DAC, 3 axis accelerometer, 4 leds, microphone, 2 switches
The Development Environment[edit]
A really neat thing from ARM is that, since they... blah blah, same thing as the stellaris board, ARM provides you with the compiler. The peripheral libraries are even more poorly packaged for GCC than TI ones, but Jeremy Herbert did a great job a repackaging these cleanly[12] for arm gcc. The programmer, STLink was implemented under linux by texane[13]
This board is compatible with openocd :
$Openocd --file /usr/local/share/openocd/scripts/board/stm32f4discovery.cfg &
Then connect to the stub in arm-none-eabi-gdb
Plug me up scotty...[edit]
Arduino[edit]
Seriously no, continue reading a bit, you get to the duino code look at the numbers... yeah that's it.
Nameless 8051 / cy7c68013a[edit]
MSP430 Launchpad[edit]
Stellaris Launchpad[edit]
STM32F4 Discovery[edit]
guess you got the idea...
But... where's the beef ?[edit]
I'm still working on the makefile
>> >> File:1dpong.makefiles.tar.gz
but the portable c source is here
>> File:1dpong.portable.c.tar.gz >>
and i still have problems with the duino makefile and "portabilization" but here is the code :
#include <avr/io.h> #include <avr/interrupt.h> //Pin connected to latch pin (ST_CP) of 74HC595 const int latchPin = 10; //Pin connected to clock pin (SH_CP) of 74HC595 const int clockPin = 11; ////Pin connected to Data in (DS) of 74HC595 const int dataPin = 13; const int int0pin=2; const int int1pin=3; int CurrentGameState; int scorep1,scorep2,lastscore,globpause; enum gamestate { NEW_GAME, DISPLAY_SCORE, FORTH, BACK, PRESSP1, PRESSP2, P1SCORED, P2SCORED, WINP1, WINP2, }; int dec2bin(int dec){ int ret = 0; while(dec){ ret<<=1; ret|=1; dec--; } return ret; } void cleanLed( int i){ digitalWrite(dataPin,LOW); while(i--){ digitalWrite(clockPin,HIGH); digitalWrite(clockPin,LOW); } } void setup() { //set pins to output because they are addressed in the main loop MCUCR |= ( 1 << ISC00); MCUCR |= ( 0 << ISC01); pinMode(latchPin, OUTPUT); pinMode(dataPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(int0pin, INPUT); pinMode(int1pin, INPUT); /*digitalWrite(int1pin,HIGH); digitalWrite(int0pin,HIGH);*/ cleanLed(56); randomSeed(analogRead(0)); scorep1=scorep2=0; CurrentGameState=NEW_GAME; } void ledforth(int pause){ int i=0; digitalWrite(latchPin,LOW); digitalWrite(dataPin,HIGH); digitalWrite(clockPin,LOW); digitalWrite(clockPin,HIGH); digitalWrite(latchPin,HIGH); delay(pause); digitalWrite(latchPin,LOW); digitalWrite(dataPin,LOW); for(i=0;i<57;i++){ if(i==54){ EIMSK |= ( 1 << INT1); Serial.println("SET INT1"); } digitalWrite(latchPin,LOW); digitalWrite(clockPin,HIGH); digitalWrite(clockPin,LOW); digitalWrite(latchPin,HIGH); delay(pause); } EIMSK &= ~( 1 << INT1); if(CurrentGameState==FORTH) CurrentGameState=P1SCORED; } void ledback(int pause){ int i,j,k; for(j=56;j>=0;j--){ digitalWrite(latchPin,LOW); for(k=56-j;k>=0;k--){ digitalWrite(clockPin,HIGH); digitalWrite(clockPin,LOW); } i=0; if(j==4){ EIMSK |= ( 1 << INT0); Serial.println("SET INT0"); } digitalWrite(dataPin,HIGH); digitalWrite(clockPin,LOW); digitalWrite(clockPin,HIGH); digitalWrite(dataPin,LOW); for(i=0;i<j;i++){ digitalWrite(clockPin,LOW); digitalWrite(clockPin,HIGH); } digitalWrite(latchPin,HIGH); delay(pause); } EIMSK &= ~( 1 << INT0); if(CurrentGameState==BACK) CurrentGameState=P2SCORED; } ISR(INT0_vect) { // digital2 CurrentGameState=PRESSP1; } ISR(INT1_vect) { // digital 3 CurrentGameState=PRESSP2; } void nextglobpause(){ globpause *=0.9; if(globpause < 10){ globpause = 10; } } int displayscore(int locscorep1,int locscorep2){ int clocked = 0; int binscorep1 = dec2bin(locscorep1); int binscorep2 = dec2bin(locscorep2); digitalWrite(latchPin,LOW); digitalWrite(dataPin,HIGH); while(binscorep2){ binscorep2>>=1; digitalWrite(clockPin,LOW); digitalWrite(clockPin,HIGH); clocked++; } digitalWrite(dataPin,LOW); while(clocked+scorep1<56){ digitalWrite(clockPin,LOW); digitalWrite(clockPin,HIGH); clocked++; } digitalWrite(dataPin,HIGH); while(clocked<56){ digitalWrite(clockPin,LOW); digitalWrite(clockPin,HIGH); clocked++; } digitalWrite(latchPin,HIGH); return 1; } void loop() { switch (CurrentGameState) { case NEW_GAME: if(random(2)){ CurrentGameState = FORTH; }else{ CurrentGameState = BACK; } globpause = 120; break; case FORTH: nextglobpause(); ledforth(globpause); break; nextglobpause(); case BACK: nextglobpause(); ledback(globpause); cleanLed(57); break; case PRESSP1: CurrentGameState=FORTH; break; case PRESSP2: CurrentGameState=BACK; break; case P1SCORED: scorep1++; lastscore=0; CurrentGameState=DISPLAY_SCORE; break; case P2SCORED: scorep2++; lastscore=1; CurrentGameState=DISPLAY_SCORE; break; case WINP1: while(1){ displayscore(scorep1,scorep2); delay(300); displayscore(scorep1,0); delay(300); } break; case WINP2: while(1){ displayscore(scorep1,scorep2); delay(300); displayscore(0,scorep2); delay(300); } break; case DISPLAY_SCORE: cleanLed(57); displayscore(scorep1,scorep2); delay(1000); cleanLed(57); if(lastscore){ CurrentGameState=FORTH; }else{ CurrentGameState=BACK; } if(scorep1+scorep2>10){ if(scorep1>scorep2){ CurrentGameState=WINP1; }else{ CurrentGameState=WINP2; } } break; } }
References[edit]
<references> <ref name="GLO">Game Like Object</ref> <ref name="#17">Rule of Programing #17: ap rogram is a program is a program... but just between programers </ref> <ref name="74HCT595">The HCT accepts CMOS & TTL input voltage (hence the T) and outputs CMOS, HC is CMOS only. Doing this makes the boards agnostic in term of logic input.</ref> </references>