Snake InstitutionenförElektro2ochinformationsteknikvidLundsTekniskaHögskola EITF11DigitalaProjekt Handledare:BertilLindvall Författare:FredrikWegelidochSvantePagels,I13 2016205223
Abstract ThisreportisapartofthecourseDigitalSystems,ProjectLaboratory(EITF11),atthe FacultyofEngineering(LTH)atLundUniversity.Theaimofthecourseistoillustratehow developingworkcanbedoneintheindustry.theauthorshavedesigned,developed,build, debuggedanddocumentedasystemforplayingthegamesnake.theresultoftheprojectis aphysicalconstruction,completewithdocumentation,wheretheplayerisabletoenjoythis classicgame.
Innehållsförteckning0 Inledning( 1( Teori( 2( Kravspecifikation/ 2/ Funktionella+krav+ 2+ Kvalitetskrav+ 2+ Hårdvara/ 3/ Komponenter+ 3+ Kopplingsschema+ 3+ Metod( 4( Resultat( 5( Diskussion( 6( Appendix(A(<(Kopplingsschema( 7( Appendix(B(<(Källkod( 8(
Inledning Dennarapportärendokumentationavettprojektsomgenomförtsundervåren2016ikursen Digitalaprojekt(EITF11)vidLundsTekniskaHögskola.Syftetmedkursenärattillustrera industrielltutvecklingsarbete.huvuddelenavkursenbeståriattkonstruera,byggaochtestaen konstruktion.författarnaavdennarapportharvaltenkonstruktionförattspeladatorspelet Snake. Snakeärettklassisktspelfrån1976,tillstordelkäntförsittframträdandepåNokiatelefoner. Speletgårutpåattstyraenormsomständigtrörsigframåt.Påspelplanenfinnsdetalltidett äppleochmåletmedspeletärattsamlasåmångaavdessasommöjligt,därinsamladeäpplen motsvararspelarenspoäng.speletfortsättertilldessattormenkrockarmedsigsjälveller väggen. Rapportenäruppbyggdifyrahuvudsakligadelar.Denförstadelen,teoridelen,behandlar kravspecifikationförsystemsamtvilkakomponentersomingår.därefterkommerendelom projektetsgenomförandedärdetförklarashurprocessengåtttill.rapportenssistadelärresultat ochdiskussiondärkonstruktionenpresenterasochprojektetdiskuteras.bifogatfinnsäven appendixmedkopplingsschemaförkonstruktionensamtkällkodenförsystemet. 1
Teori Kravspecifikation ArbetetinleddesmedattattdefinieravilkakravsombehövdeuppfyllasavbådehårdToch mjukvara.kravendeladesuppifunktionellaochkvalitetskravochdefunktionellakravendelades isinturuppikravförmjukvaraochförhårdvara.syftetmedkravspecifikationenärattlägga grundenförkopplingsschemaochförattkontinuerligtkunnaföljaattutvecklingavhårdvaraoch mjukvarauppfyllerdekravsomställspåprototypen.nedanföljerkravensomställtspå snakespelet. Funktionellakrav Hårdvara Detskafinnasendisplay Ormenochäppletskavisaspådisplayen Ormenskabefinnasigienbana,representeradavenfyrkant Antalpoäng(insamladeäpplen)skavisaspådisplayen Detskafinnasenfyraknapparförattstyraormen Varjeknappmotsvararenriktning Omspelarentryckerpåenavdessaknapparskaormenvridasigidenriktningen Omormenredanrörsigidenriktningenhänderingenting Mjukvara Ormenskaständigtrörasigframåt Omormenkörinisinegenkroppelleriväggenärspeletslut Speletskakunnastartasigengenomatttryckapåvalfriknapp Omormenköriniettäppleska: Ormenskroppblienenhetlängre Antaletinsamladeäpplenuppdateras Ettnyttäppleskapas Kvalitetskrav Fördröjningmellanknapptryckningochresponspåskärmenskaintevaraförlång Dengrafiskadisplayenskavarauppbyggdav128x64punkter. 2
Hårdvara Komponenter Processor ProcessornsomanväntstillprototypenärenAtmelATmega32.Detären8Tbitars mikrokontrollermed32kbflashminne,6kbstatiskramoch40olikapinsvarav32ärindeladei fyraolikaportarochfyratillförmikrokontrollernmedström.portbbeståravpins1t8ochär databustilllcd.portdbeståravpins14t21ochärkoppladetillknapparochlogik.portc beståravpins22t29ochärkoppladetilljtag.portabeståravpins33t40ochanvändsföratt skickainstuktionertilllcd.förmerinformationkringkopplingseappendixa. LCD SkärmensomanvändsärenbakgrundsbelystLCD,GDM12864HLCM.Skärmenhar128x64 pixlaruppdelatpåtvåskärmhalvor.viadatabus(portbpåmikrokontrollern)ändrasregisterom 8bitaritaget. Knappar Förattstyraormenispeletanvändsfyraknappar.KnapparnaärkoppladetillPortBhos mikrokontrollern. Logik TillinteruptpinsiPortB,INT0ochINT1äräventvådisjunkta(OR)logiskagrindarinkopplade (seappendixa). JTAG FörattprogrammeramikrokontrollernviaprogrammetAtmelStudiosanvändesenJTAG. Resistorer Femstyckenresistoreranvändesäveniprototypen.Fyrastyckenresistorerpå10kΩvardera användestillvarochenavknapparnaochenvariabelresistoranvändesförattjusterakontrast pålcd. Kopplingsschema SeappendixA. 3
Metod Arbetetpåbörjadesmedattbrytanerproblemetibeståndsdelar.Enförstakravspecifikation skrevsochlämnadesintillhandledarenförprojektet.efterattdennakravspecifikationgodkänts ritadesettkopplingsschemasomocksågodkändesavprojekthandledaren.kravspecifikation ochkopplingsschemauppdateradeskontinuerligtunderprojektetsgångidefalldådetvar nödvändigt. Material,komponenterochverktygslådakvitteradesdärefterutochdetriktigaarbetetkunde påbörjas.kopplingsschematföljdesochkomponenterakoppladesochlöddessammantillen prototyp.medhjälpavjtagochatmelstudio6.2kundeprocessorntestasochvia felsökningsfunktionen(engelska:debugger)erhöllsenstörreinsiktihurdeolikaportarna reagerademedvarandra.underdettastegiprojektetanvändesdatabladfördeolika komponenternaistorutsträckningförattförståhurprocessornskullekommuniceramedövriga komponenter. Närskärmenkundestartasviafelsökningsfunktionenpåbörjadeskodandetochsimplametoder skrevsförattstartaochsläckaskärmen.efteratthaförståtthurpixlartändsochsläckspå skärmenskrevsävenmetoderförattritaellersuddaenvisspixel.dåskärmenkräverattåtta pixlarskrivssamtidigtbehövdesenvirtuellskärm,detvillsägaattinformationsparasövervilka pixlarsomärtändaochvilkasomärsläckta.detinsågsdåattdenursprungligaprocessorninte hadetillräckligtarbetsminneförattsparaalldennainformation.efteröverläggningmed projekthandledarenuppgraderadesprocessornfrånatmega16tillatmega32. Närmetoderfannsförattritapåskärmenviaettkoordinatsystempåbörjadesarbetetmedattfå knapparnaattgeresponstillprocessorn.häranvändespåfelsökningsfunktionenochdatablad flitigtförattförstahursåkalladeinterruptsfungerarikodskrivandet. EfteratthårdvaranfungeradesomtänktkundesjälvaprogrammetförSnakeskrivas.Idettasteg användeskravspecifikationenförattsetillattsamtligakravsomställdespåspeletuppfylldes. Dettavareniterativprocessmedmyckettestningpådenfaktiskahårdvaranförattförsäkrasig omattspeletfungeradesomtänkt.allteftersomkundeflerfunktionerläggastill.exempelpå dessaärpoängräknareochkontrollavsjälvkollision. Detsistastegetiprojektetvaratttestaspeletistorutsträckningförattsetillattsamtligakravvar uppfylldaochattdetvartillfredsställandeattspela. 4
Resultat Projektetresulteradeienkonstruktionsomuppfyllersamtligakravikravspecifikationen.Spelet fungerarvälochsvårighetsgradenärenligtförfattarnapåenlagomnivå.nedanfinnstvåbilder påkonstruktionenianvändning. 5
Diskussion TrotsbegränsadekunskaperinombådeCTprogrammeringochelektronik,gickprojektetutmärkt. Svårgihetersomuppkommitlängsvägenhartillstordelbeståttavsvårigheterattförstå,alltfrån databladtilluppläggochstrukturinomctprogrammeringochatmelstudios.varjemotgånghar däremotletttilllärdomochmotslutetavperiodenflötarbetetpåbra. Ettavproblemensomuppkommitunderarbetetvarattmikrokontrollernsursprungliga arbetsminnepå16kbinteräcktetillförattsparaenvirtuellbildavskärmensomanvändesvid uppdateringavskärmen.dettavarettsvåridentifieratproblemdärlärdomendrogsattmanalltid börhållaredapåvadmansparariapplikationendåmanarbetarmedettbegränsatram. Iövrigtinsågsviktenganskaomgåendeattförståelseavdatabladenvaravstörstavikt.Många timmarspenderadesiatmelstudiospågrundavotillräckligförståelseavdatabladoch framföralltlcdochmikrokontrollensfunktioner. Överlagansesändåenfungerandeprototypvaraettgottresultatochprojektgruppenärmycket nöjdamedinsatsen. EttstorttackskaävengestillhandledareBertilLindvallsomståttutmedbådedummafrågor ochdåligaskämtunderprojektperioden,tack 6
AppendixATKopplingsschema 7
AppendixBTKällkod /* *snake.c * *Created:2016T04T1116:01:11 *Author:SvantePagelsochFredrikWegelid */ #include<avr/io.h> #include<util/delay.h> #include<stdlib.h> #include<avr/interrupt.h> charvirtualdisplay[8][128]o charapplelocation[2]o charsnakelocation[2][200]o charsnakelengtho charsnakedirectiono charsnakealiveo charpointso chargamestarted=0o charcollision(charx,chary)o intmain(void){ setdatadirection()o startdisplay()o cleardisplay()o setupboard()o setupsnake()o enableinterrupt()o while(1){ while(gamestarted==0){} points=0o writepoints()o 8
erasesnake()o setupsnake()o newapple()o while(snakealive==1){ _delay_ms(35)o movesnake()o } } } voidsetupboard(){ writesnake(2,2)o drawboard()o drawslytherin(15,7)o writepoints()o } voidnewapple(){ erase(applelocation[0],applelocation[1])o charxo charyo do{ x=2+rand()%60o y=33+rand()%93o }while(collision(x,y))o applelocation[0]=xo applelocation[1]=yo draw(applelocation[0],applelocation[1])o } voidmovesnake(){ charnewxo charnewyo switch(snakedirection){ case1: newx=snakelocation[0][0]o newy=snakelocation[1][0]+1o breako case2: newx=snakelocation[0][0]t1o newy=snakelocation[1][0]o 9
breako case3: newx=snakelocation[0][0]o newy=snakelocation[1][0]t1o breako case4: newx=snakelocation[0][0]+1o newy=snakelocation[1][0]o breako } if(newx>=62 newx<=0 newy>=127 newy<=32 collision(newx,newy)==1) { _delay_ms(500)o snakealive=0o gamestarted=0o }else{ erase(snakelocation[0][snakelengtht1],snakelocation[1][snakelengtht1])o for(chari=snakelengtht1oi>0oitt){ snakelocation[0][i]=snakelocation[0][it1]o snakelocation[1][i]=snakelocation[1][it1]o } snakelocation[0][0]=newxo snakelocation[1][0]=newyo drawsnake()o if(newx==applelocation[0]&&newy==applelocation[1]){ points++o snakelength++o newapple()o writepoints()o drawsnake()o } } } charcollision(charx,chary){ for(chari=0oi<snakelengthoi++){ if(snakelocation[0][i]==x&&snakelocation[1][i]==y){ return1o } } 10
return0o } voidsetupsnake(){ snakelength=15o snakedirection=4o snakealive=1o for(chari=0oi<15oi++){ snakelocation[0][i]=32tio snakelocation[1][i]=80o } drawsnake()o } voiddrawsnake(){ for(chari=0oi<snakelengthoi++){ draw(snakelocation[0][i],snakelocation[1][i])o } } voiderasesnake(){ for(chari=0oi<snakelengthoi++){ erase(snakelocation[0][i],snakelocation[1][i])o } } voidcleardisplay(){ for(chary=0oy<128oy++){ for(charx=0ox<64ox++){ erase(x,y)o } } } voiddraw(charx,chary){ virtualdisplay[x/8][y] =(1<<(x%8))o charnewyo if(y<64){ cs2high()o cs1low()o newy=yo }else{ 11
cs1high()o cs2low()o newy=yt64o } setx(x/8)o sety(newy)o writedata(x,y)o } voiderase(charx,chary){ virtualdisplay[x/8][y]&=~(1<<(x%8))o charnewyo if(y<64){ cs2high()o cs1low()o newy=yo }else{ cs1high()o cs2low()o newy=yt64o } setx(x/8)o sety(newy)o erasedata(x,y)o } voidwritedata(charx,chary){ rshigh()o rwlow()o PORTB=virtualDisplay[x/8][y]o ehigh()o elow()o } voiderasedata(charx,chary){ 12
rshigh()o rwlow()o PORTB=virtualDisplay[x/8][y]o ehigh()o elow()o } voidsetx(charx){ rslow()o rwlow()o PORTB=0b10111000 xo ehigh()o elow()o } voidsety(chary){ rslow()o rwlow()o PORTB=0b01000000 yo ehigh()o elow()o } voidsetdatadirection(){ DDRA=0b11111111o DDRB=0b11111111o } ISR(INT0_vect){ if(gamestarted==0){ gamestarted=1o _delay_ms(500)o }else{ switch(pind){ case0b00010110: turnup()o breako case0b00100110: 13
turnleft()o breako } } } ISR(INT1_vect){ if(gamestarted==0){ gamestarted=1o _delay_ms(500)o }else{ switch(pind){ case0b10001000: turndown()o breako case0b01001000: turnright()o breako } } } voidturnright(){ if(snakedirection=3){ snakedirection=1o } } voidturnleft(){ if(snakedirection=1){ snakedirection=3o } } voidturnup(){ if(snakedirection=4){ snakedirection=2o } } voidturndown(){ if(snakedirection=2){ snakedirection=4o } 14
} voidstartdisplay(){ PORTB=0b00111111o cs1low()o cs2low()o resethigh()o rwlow()o rslow()o ehigh()o cs1high()o cs2high()o elow()o ehigh()o } voidstopdisplay(){ PORTB=0b00111110o cs1low()o cs2low()o resethigh()o rwlow()o rslow()o ehigh()o cs1high()o cs2high()o elow()o ehigh()o } voidenableinterrupt(){ PIND=0b00000000o DDRD=0b00000000o MCUCR =0b00001111o GICR =0b11000000o sei()o 15
} voidcs2high(){ PORTA =0b00000001o } voidcs2low(){ PORTA&=0b11111110o } voidcs1high(){ PORTA =0b00000010o } voidcs1low(){ PORTA&=0b11111101o } voidresethigh(){ PORTA =0b00000100o } voidresetlow(){ PORTA&=0b11111011o } voidrwhigh(){ PORTA =0b00001000o } voidrwlow(){ PORTA&=0b11110111o } voidrshigh(){ PORTA =0b00010000o } voidrslow(){ PORTA&=0b11101111o } voidehigh(){ PORTA =0b00100000o 16
} voidelow(){ PORTA&=0b11011111o } voidwritepoints(){ for(charx=56ox<64ox++){ for(chary=20oy<31oy++){ erase(x,y)o } } switch(points%10){ case1: draw1(56,26)o breako case2: draw2(56,26)o breako case3: draw3(56,26)o breako case4: draw4(56,26)o breako case5: draw5(56,26)o breako case6: draw6(56,26)o breako case7: draw7(56,26)o breako case8: draw8(56,26)o breako case9: draw9(56,26)o breako case0: draw0(56,26)o breako 17
} switch(points/10){ case1: draw1(56,20)o breako case2: draw2(56,20)o breako case3: draw3(56,20)o breako case4: draw4(56,20)o breako case5: draw5(56,20)o breako case6: draw6(56,20)o breako case7: draw7(56,20)o breako case8: draw8(56,20)o breako case9: draw9(56,20)o breako } } voiddraw1(charx,chary){ for(chari=0oi<7oi++){ draw(x+i,y+2)o } draw(x+1,y+1)o draw(x+6,y+1)o draw(x+6,y+3)o } voiddraw2(charx,chary){ draw(x,y+1)o 18
draw(x,y+2)o draw(x,y+3)o draw(x+1,y)o draw(x+1,y+4)o draw(x+2,y+4)o draw(x+3,y+3)o draw(x+4,y+2)o draw(x+5,y+1)o for(chari=0oi<5oi++){ draw(x+6,y+i)o } } voiddraw3(charx,chary){ for(chari=0oi<5oi++){ draw(x,y+i)o } draw(x+1,y+3)o draw(x+2,y+2)o draw(x+3,y+3)o draw(x+4,y+4)o draw(x+5,y)o draw(x+5,y+4)o draw(x+6,y+1)o draw(x+6,y+2)o draw(x+6,y+3)o } voiddraw4(charx,chary){ for(chari=0oi<5oi++){ draw(x+4,y+i)o } for(chari=0oi<7oi++){ draw(x+i,y+3)o } draw(x+3,y)o draw(x+2,y+1)o 19
draw(x+1,y+2)o } voiddraw5(charx,chary){ for(chari=0oi<5oi++){ draw(x,y+i)o } draw(x+1,y)o for(chari=0oi<4oi++){ draw(x+2,y+i)o } draw(x+3,y+4)o draw(x+4,y+4)o draw(x+5,y)o draw(x+5,y+4)o draw(x+6,y+1)o draw(x+6,y+2)o draw(x+6,y+3)o } voiddraw6(charx,chary){ draw(x,y+2)o draw(x,y+3)o draw(x+1,y+1)o draw(x+2,y)o for(chari=0oi<4oi++){ draw(x+3,y+i)o } draw(x+4,y)o draw(x+4,y+4)o draw(x+5,y)o draw(x+5,y+4)o draw(x+6,y+1)o draw(x+6,y+2)o 20
draw(x+6,y+3)o } voiddraw7(charx,chary){ for(chari=0oi<5oi++){ draw(x,y+i)o } draw(x+1,y+4)o draw(x+2,y+3)o draw(x+3,y+2)o draw(x+4,y+1)o draw(x+5,y+1)o draw(x+6,y+1)o } voiddraw8(charx,chary){ for(chari=1oi<4oi++){ draw(x,y+i)o draw(x+3,y+i)o draw(x+6,y+i)o } for(chari=1oi<3oi++){ draw(x+i,y)o draw(x+i,y+4)o draw(x+3+i,y)o draw(x+3+i,y+4)o } } voiddraw9(charx,chary){ draw(x+6,y+1)o draw(x+6,y+2)o draw(x+5,y+3)o draw(x+4,y+4)o for(chari=1oi<5oi++){ draw(x+3,y+i)o } draw(x+2,y)o 21
draw(x+2,y+4)o draw(x+1,y)o draw(x+1,y+4)o draw(x,y+1)o draw(x,y+2)o draw(x,y+3)o } voiddraw0(charx,chary){ for(chari=1oi<6oi++){ draw(x+i,y)o draw(x+i,y+4)o } for(chari=1oi<4oi++){ draw(x,y+i)o draw(x+6,y+i)o } draw(x+4,y+1)o draw(x+3,y+2)o draw(x+2,y+3)o } voidwritesnake(charx,chary){ draws(x,y)o drawn(x,y+6)o drawa(x,y+12)o drawk(x,y+18)o drawe(x,y+24)o } voiddrawboard(){ for(chary=32oy<128oy++){ draw(0,y)o draw(62,y)o } for(charx=0ox<63ox++){ draw(x,32)o draw(x,127)o } } 22
voiddrawslytherin(charx,chary){ //rad0 for(chari=4oi<9oi++){ draw(x,y+i)o } //rad1 for(chari=3oi<10oi++){ draw(x+1,y+i)o } draw(x+1,y+13)o erase(x+1,y+4)o //rad2 for(chari=2oi<10oi++){ draw(x+2,y+i)o } erase(x+2,y+7)o draw(x+2,y+12)o //rad3 for(chari=1oi<10oi++){ draw(x+3,y+i)o } erase(x+3,y+6)o erase(x+3,y+7)o draw(x+3,y+12)o //rad4 draw(x+4,y+2)o draw(x+4,y+3)o draw(x+4,y+8)o draw(x+4,y+9)o draw(x+4,y+12)o draw(x+4,y+13)o //rad5 draw(x+5,y+1)o draw(x+5,y+7)o draw(x+5,y+8)o draw(x+5,y+9)o draw(x+5,y+13)o 23
draw(x+5,y+14)o //rad6 draw(x+6,y+0)o draw(x+6,y+6)o draw(x+6,y+7)o draw(x+6,y+8)o draw(x+6,y+13)o draw(x+6,y+14)o //rad7 draw(x+7,y+5)o draw(x+7,y+6)o draw(x+7,y+7)o draw(x+7,y+14)o draw(x+7,y+15)o //rad8 draw(x+8,y+4)o draw(x+8,y+5)o draw(x+8,y+6)o draw(x+8,y+7)o draw(x+8,y+10)o draw(x+8,y+11)o draw(x+8,y+12)o draw(x+8,y+14)o draw(x+8,y+15)o //rad9t19ifyllnad for(chardx=9odx<19odx++){ for(chardy=2ody<18ody++){ draw(x+dx,y+dy)o } } //rad9 erase(x+9,y+2)o erase(x+9,y+7)o erase(x+9,y+17)o //rad10 erase(x+10,y+2)o erase(x+10,y+6)o erase(x+10,y+11)o 24
erase(x+10,y+12)o //rad11 erase(x+11,y+6)o erase(x+11,y+10)o erase(x+11,y+11)o //rad12 erase(x+12,y+5)o erase(x+12,y+6)o //rad13 erase(x+13,y+5)o erase(x+13,y+6)o erase(x+13,y+7)o erase(x+13,y+14)o erase(x+13,y+15)o //rad14 for(chari=5oi<15oi++){ erase(x+14,y+i)o } draw(x+14,y+11)o draw(x+14,y+12)o //rad15 for(chari=6oi<14oi++){ erase(x+15,y+i)o } //rad16 erase(x+16,y+2)o erase(x+16,y+8)o erase(x+16,y+9)o erase(x+16,y+10)o erase(x+16,y+11)o erase(x+16,y+17)o //rad17 erase(x+17,y+2)o erase(x+17,y+3)o erase(x+17,y+16)o erase(x+17,y+17)o 25
//rad18 erase(x+18,y+2)o erase(x+18,y+3)o erase(x+18,y+15)o erase(x+18,y+16)o erase(x+18,y+17)o //rad19 erase(x+19,y+2)o erase(x+19,y+3)o erase(x+19,y+4)o erase(x+19,y+5)o erase(x+19,y+6)o erase(x+19,y+13)o erase(x+19,y+14)o erase(x+19,y+15)o erase(x+19,y+16)o erase(x+19,y+17)o } voiddraws(charx,chary){ for(chari=1oi<5oi++){ draw(x,y+i)o } draw(x+1,y)o draw(x+2,y)o for(chari=1oi<4oi++){ draw(x+3,y+i)o } draw(x+4,y+4)o draw(x+5,y+4)o for(chari=0oi<4oi++){ draw(x+6,y+i)o } } voiddrawn(charx,chary){ for(chari=0oi<7oi++){ draw(x+i,y)o 26
draw(x+i,y+4)o } draw(x+2,y+1)o draw(x+3,y+2)o draw(x+4,y+3)o } voiddrawa(charx,chary){ for(chari=1oi<4oi++){ draw(x,y+i)o draw(x+3,y+i)o } for(chari=1oi<7oi++){ draw(x+i,y)o draw(x+i,y+4)o } } voiddrawk(charx,chary){ for(chari=0oi<7oi++){ draw(x+i,y)o } for(chari=0oi<4oi++){ draw(x+3+i,y+1+i)o draw(x+3ti,y+1+i)o } } voiddrawe(charx,chary){ for(chari=0oi<7oi++){ draw(x+i,y)o } for(chari=1oi<5oi++){ draw(x,y+i)o draw(x+3,y+it1)o draw(x+6,y+i)o } } 27
28