Övning 6 Parallellport, timer
6.1 de2_pio_toggles18 Memory-Mapped addresses LEDG8 LEDR17 LEDR16 LEDR15 LEDR14 LEDR13 LEDR12 LEDR11 LEDR10 LEDR9 LEDR8 LEDR7 LEDR6 LEDR5 LEDR4 LEDR3 LEDR2 LEDR1 LEDR0 LEDG7 LEDG6 LEDG5 LEDG4 LEDG3 LEDG2 LEDG1 LEDG0 SW17 SW16 SW15 SW14 SW13 SW12 SW11 SW10 SW9 SW8 SW7 SW6 SW5 SW4 SW3 SW2 SW1 SW0 KEY3 KEY2 KEY1 KEY0 SW14 SW15 SW16 SW17... SW3 SW2 SW1 SW0 0x850 0x854 0x858 0x85C 31 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
6.1 Inmatning från toggles18.equ toggles18,0x850 # toggles18 address.text # program code follows.align 2.global Get_Data # make name globally known Get_Data: movia r8,toggles18 # set address ldw r2,0(r8) # read toggles18 device movia r8,0x3ffff # set bit-mask (18 bits) and r2,r2,r8 # clear unused bits ret # return to caller
6.1 Inmatning från toggles18: C volatile int * const toggles18 = ( (volatile int *) 0x850 ); int Get_Data( void ) { int tmp = *toggles18; return( tmp & 0x3ffff ); } Skapar en pekarvariabel Tydligt, lätt att debugga
6.1 Inmatning från toggles18: C #define TOGGLES18 ( (int *) 0x850 ) int Get_Data( void ) { volatile int * toggles18 = TOGGLES18; int tmp = *toggles18; return( tmp & 0x3ffff ); } Skapar en lokal pekarvariabel Tydligt, ganska lätt att debugga
6.1 Inmatning från toggles18: C #define TOGGLES18 ( (volatile int *) 0x850 ) int Get_Data( void ) { return( *TOGGLES18 & 0x3ffff ); } Ingen pekarvariabel #define-konstanten är pekarkonstant Svårbegriplig programkod
6.8 de2_pio_keys4 Memory-Mapped addresses LEDG8 LEDR17 LEDR16 LEDR15 LEDR14 LEDR13 LEDR12 LEDR11 LEDR10 LEDR9 LEDR8 LEDR7 LEDR6 LEDR5 LEDR4 LEDR3 LEDR2 LEDR1 LEDR0 LEDG7 LEDG6 LEDG5 LEDG4 LEDG3 LEDG2 LEDG1 LEDG0 SW17 SW16 SW15 SW14 SW13 SW12 SW11 SW10 SW9 SW8 SW7 SW6 SW5 SW4 SW3 SW2 SW1 SW0 KEY3 KEY2 KEY1 KEY0 KEY3 KEY2 KEY1 KEY0 0x840 0x844 0x848 0x84C 31 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
6.2 de2_pio_greenled9 Memory-Mapped addresses LEDG8 LEDR17 LEDR16 LEDR15 LEDR14 LEDR13 LEDR12 LEDR11 LEDR10 LEDR9 LEDR8 LEDR7 LEDR6 LEDR5 LEDR4 LEDR3 LEDR2 LEDR1 LEDR0 LEDG7 LEDG6 LEDG5 LEDG4 LEDG3 LEDG2 LEDG1 LEDG0 SW17 SW16 SW15 SW14 SW13 SW12 SW11 SW10 SW9 SW8 SW7 SW6 SW5 SW4 SW3 SW2 SW1 SW0 KEY3 KEY2 KEY1 KEY0 LEDG4 LEDG5 LEDG6 LEDG7 LEDG8 LEDG3 LEDG2 LEDG1 LEDG0 0xA10 0xA14 0xA18 0xA1C 31 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
6.2 Utmatning till greenled9.equ greenled9,0xa10 # address to greenled9.text # program code follows.align 2.global Green_Light # make name globally known Green_Light: andi r4,r4,0x01ff # zero out unused bits movia r8,greenled9 # set address to LEDs stw r4,0(r8) # write to LED device mov r2,r4 # set up return value ret # return to caller
6.2 Utmatning till greenled9: C #define GREENLED9 ( (volatile int *) 0xa10 ) int Green_Light( int lightbits ) { volatile int * greenled9 = GREENLED9; int tmp = lightbits & 0x1ff; *greenled9 = tmp; return( tmp ); }
6.2 Utmatning till greenled9: C volatile int * const greenled9 = ( (int *) 0xa10 ); int Green_Light( int lightbits ) { int tmp = lightbits & 0x1ff; *greenled9 = tmp; return( tmp ); }
de2_pio_redled18 Memory-Mapped addresses LEDG8 LEDR17 LEDR16 LEDR15 LEDR14 LEDR13 LEDR12 LEDR11 LEDR10 LEDR9 LEDR8 LEDR7 LEDR6 LEDR5 LEDR4 LEDR3 LEDR2 LEDR1 LEDR0 LEDG7 LEDG6 LEDG5 LEDG4 LEDG3 LEDG2 LEDG1 LEDG0 SW17 SW16 SW15 SW14 SW13 SW12 SW11 SW10 SW9 SW8 SW7 SW6 SW5 SW4 SW3 SW2 SW1 SW0 KEY3 KEY2 KEY1 KEY0 LEDR14 LEDR15 LEDR16 LEDR17... LEDR3 LEDR2 LEDR1 LEDR0 0x810 0x814 0x818 0x81C 31 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
6.3 Sjusegmentsdisplay Memory-Mapped addresses LEDG8 0xA00 31 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 de2_pio_hex_high28 0x9F0 31 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 de2_pio_hex_low28
6.3 Sjusegmentsdisplay Segmentöversikt bit index 0 = segment on (lights up) 1 = segment off (dark) 0 5 1 6 4 2 3 0 0 0 0 0 0 0
6.3 Sjusegmentsdisplay Teckenöversikt 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
6.3 Sjusegmentsdisplay Siffran 0 0 = segment on (lights up) 1 = segment off (dark) 1 0 0 0 0 0 0 = 0x40
6.3 Sjusegmentsdisplay Siffran 1 0 = segment on (lights up) 1 = segment off (dark) 1 1 1 1 0 0 1 = 0x79
6.3 Sjusegmentsdisplay (en sifferposition) int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e }; int hex7seg( int digit ) { } int tmp = digit & 0xf; return( trantab[ tmp ] );
6.4 Sjusegmentsdisplay, utmatning.equ hex_low28,0x9f0 # hex_low28 address.text # program code follows.align 2.global PutLoSegVal # be globally available PutLoSegVal: movia r8,hex_low28 # set address stw r4,0(r8) # write output data mov r2,r4 # setup return value ret # return to caller
6.4 Sjusegmentsutmatning: C #define HEX_LOW28 ( (int *) 0x9f0 ) void PutLoSegVal( int hexlowbits ) { volatile int * hex_low28 = HEX_LOW28; *hex_low28 = hexlowbits; }
6.5 Helt program main: call GetData # hämta från toggles mov r16,r2 # spara värdet mov r4,r2 # kopiera värdet call hex27seg # omvandla 1 siffra mov r17,r2 # spara resultat srli r4,r16,4 # ta fram nästa siffra call hex27seg # omvandla 1 siffra igen slli r8,r2, 7 # skifta 7 bitar vänster or r17,r17,r8 # lägg in i resultatet # fortsättning följer
6.6 Helt program, forts srli r4,r16,8 # ta fram nästa siffra call hex27seg # omvandla 1 siffra igen slli r8,r2,14 # skifta 2x7 bitar vänster or r17,r17,r8 # addera till resultat srli r4,r16,12 # ta fram nästa siffra call hex27seg # omvandla 1 siffra igen slli r8,r2,21 # skifta 3x7 bitar vänster or r17,r17,r8 # addera till resultat mov r4,r17 # kopiera till parameterregister call PutLoSegVal # mata ut resultat br main # repetera alltihop
6.6 Helt program: C (del 1) int main() { unsigned int tmp; while( 1 ) { tmp = Get_Data(); (void) Green_Light( tmp ); fixandshow( tmp ); } }
6.6 Helt program: C (del 2) void fixandshow( unsigned int bitstoshow ) { unsigned int hexresult; hexresult = hex7seg( bitstoshow ); hexresult = hexresult ( hex7seg( bitstoshow >> 4 ) << 7 ); hexresult = hexresult ( hex7seg( bitstoshow >> 8 ) << 14 ); hexresult = hexresult ( hex7seg( bitstoshow >> 12 ) << 21 ); PutLoSegVal( hexresult ); }
6.6 Nios Timer Memory Mapped Addresses Läs/skriv hela 32-bits ord med ldw och stw...men bara 16 bitar används 0x920 0x924 0x928 0x92C 0x930 0x934 0x938 0x93C 31 16 15 0 31 16 15 0
6.6 timer_1 Memory-Mapped addresses 0x920 status 0x924 control 0x928 periodl 0x92C periodh 0x930 snapl 0x934 snaph 15 0 Run TO (Time-Out) ITO cont start stop
6.7 Problem med enkel delay Klockan går inte exakt Programmet har slumpmässig reaktionstid tid från Time-Out tills programmet hinner läsa Time-Out-biten och reagera, denna tid varierar slumpmässigt starta timer Time-Out starta timer igen t
6.6 Lösning: continuous mode Timern startar om sig själv direkt vid Time-Out Så länge programmet hinner läsa Time-Out-biten och nollställa den innan nästa Time-Out så får vi perfekt tidmätning bit 1 i control (adress 0x924) väljer continuous mode
6.6 Körning i continuous mode Klockan går exakt Programmet har slumpmässig reaktionstid tid från Time-Out tills programmet hinner läsa Time-Out-biten och reagera, denna tid varierar slumpmässigt starta timer Time-Out, och starta timer igen... t
6.6 inittimer Ska skriva startvärde 49999 (ger tid 1 ms) Ska ettställa continuous-biten Ska ettställa start-biten 0x920 status 0x924 control 0x928 periodl 0x92C periodh 0x930 snapl 0x934 snaph 15 0 Run TO (Time-Out) ITO cont start stop
6.6 inittimer.equ timer,0x920.equ timercount,49999 # 1 ms i exemplet.text.align 2.global inittimer inittimer: movia r8,timer # ställ in adress movia r9,timercount # startvärde srli r10,r9,16 # flytta höga bitar till högerkant stw r10,0xc(r8) # skriv periodh andi r9,r9,0xffff # städa höga bitarna stw r9,8(r8) # skriv periodl movi r9,6 # continuous och start ettställda stw r9,4(r8) # skriv control ret
6.6 inittimer: C #define TIMER1BASE ( (unsigned int *) 0x920) #define TIMER1PERIOD (49999) void inittimer( void ) { volatile unsigned int * timer1 = TIMER1BASE; timer1[2] = TIMER1PERIOD & 0xffff; timer1[3] = TIMER1PERIOD >> 16; timer1[1] = 6; }
6.6 delayt.equ timer,0x920.global delayt # så att delayt kan vara i egen fil delayt: beq r4,r0,delayklar # klart när r4 är noll delayloop: movia r8,timer # adress ldw r9,0(r8) # läs status andi r9,r9,1 # undersök bit 0 beq r9,r0,delayloop # loopa om ej Time-Out stw r8,0(r8) # återställ Time-Out subi r4,r4,1 # räkna ner millisekunder br delayt # hoppa upp till testet delayklar: ret
6.6 delayt: C #define TIMER1BASE ( (unsigned int *) 0x920) #define TIMER1PERIOD (49999) void delayt( int milliseconds ) { volatile unsigned int * timer1 = TIMER1BASE; while( milliseconds ) { while( (timer1[0] & 1) == 0 ) { /* loopa om ej TimeOut */ } timer1[0] = 0; /* återställ Time-Out */ milliseconds = milliseconds - 1; } }
7.6 timer_1 Memory-Mapped addresses 0x920 status 0x924 control 0x928 periodl 0x92C periodh 0x930 snapl 0x934 snaph 15 0 Run TO (Time-Out) ITO cont start stop
timer_1 start D Q cl Q run stop 50 MHz clock write from program load -1 copy period copy counter snap-shot read from program zero D cl set Q Q clear from program read from program time-out
snaptime volatile int * const timer_1_base = ( (volatile int *) 0x920 ); unsigned int snaptime( void ) { unsigned int snaphigh; unsigned int snaplow; unsigned int snap; } timer_1_base[ 4 ] = 0; snaphigh = timer_1_base[ 5 ] & 0xffff; snaplow = timer_1_base[ 4 ] & 0xffff; snap = (snaphigh << 16) snaplow; return( snap );