                   ; LED Blink Example program, for use with the PJRC 8051
                   ; Development Circuit Board, Rev 4.
                   ;
                   ;  http://www.pjrc.com/tech/8051/board4/blink_as31.html
                   
                   
                   ;This line configures where the program will go into memory.
                   ;2000 to 7FFF is RAM, which is the best place to download
                   ;while testing your code.  Memory from 8000 to F7FF is Flash
                   ;ROM, which is non-volatile.  You MUST ERASE the flash rom
                   ;if the area you will use already has data in it.  Unlike
                   ;easily re-writable RAM, writing to flash rom can only chang
                   ;1's into 0's.  To change the 0's back into 1's, you must
                   ;erase the flash (which turns a section or all of it into
                   ;0xFFs to all you to download again).
                   
0000:              .equ    locat, 0x2000           ;Location for this program
                   
                   
                   
                   ;82C55 memory locations, Rev 4
0000:              .equ    port_a, 0xF800           ;access port A
0000:              .equ    port_b, 0xF801           ;access port B
0000:              .equ    port_c, 0xF802           ;access port C
0000:              .equ    port_abc_pgm, 0xF803     ;configure in/out of all th
0000:              .equ    port_d, 0xF900           ;access port D
0000:              .equ    port_e, 0xF901           ;access port E
0000:              .equ    port_f, 0xF902           ;access port F
0000:              .equ    port_def_pgm, 0xF903     ;configure in/out of all th
                   
                   
                   ; Useful routines in PAULMON2 that you can call.  When you
                   ; later want a stand-alone application, you can copy them
                   ; from the PAULMON2 source code (or write you own if you lik
0000:              .equ    cout, 0x0030             ;print byte in acc to seria
0000:              .equ    cin, 0x0032              ;get byte from serial port 
0000:              .equ    phex, 0x0034             ;print acc in hex (2 digits
0000:              .equ    phex16, 0x0036           ;print dptr in hex (4 digit
0000:              .equ    pstr, 0x0038             ;print a string @dptr
0000:              .equ     esc, 0x003E             ;paulmon2's check for esc k
0000:              .equ    newline, 0x0048          ;print a newline (CR and LF
0000:              .equ    pint8u, 0x004D           ;print acc as unsigned int 
0000:              .equ    pint16u, 0x0053          ;print dptr as unsigned int
                   
                   
                   ;Program Header.  This is what PAULMON2 looks for to display
                   ;program in its memory usage and run menus.  You would norma
                   ;run this program with 'R', but you can also jump to 2040 (o
2000:              .org    locat
2000: A5 E5 E0 A5 
                   .db     0xA5,0xE5,0xE0,0xA5     ;signiture bytes
2004: 23 FF 00 00 
                   .db     35,255,0,0              ;id (35=prog)
2008: 00 00 00 00 
                   .db     0,0,0,0                 ;prompt code vector
200C: 00 00 00 00 
                   .db     0,0,0,0                 ;reserved
2010: 00 00 00 00 
                   .db     0,0,0,0                 ;reserved
2014: 00 00 00 00 
                   .db     0,0,0,0                 ;reserved
2018: 00 00 00 00 
                   .db     0,0,0,0                 ;user defined
201C: FF FF FF FF 
                   .db     255,255,255,255         ;length and checksum (255=un
2020: 42 6C 69 6E 
      6B 20 4C 45 
      44 73 00     .db     "Blink LEDs",0          ;max 31 characters, plus the
2040:              .org    locat+64                ;executable code begins here
                   
                   
                   
                   ;Finally, the actual code.... much shorter than all these co
                   ;that try to explain how to set everything up!
                   startup:
2040: 90 F9 03              mov     dptr, #port_def_pgm
2043: 74 80                 mov     a, #128
2045: F0                    movx    @dptr, a        ;make all D-E-F port pins o
                   
                   begin:
2046: 90 20 7A              mov     dptr, #table    ;DPTR will keep track of wh
                                                    ;the table we will do next
                   loop:
2049: E4                    clr     a
204A: 93                    movc    a, @a+dptr      ;get pattern to display
204B: 11 5F                 acall   update
204D: A3                    inc     dptr
204E: 12 00 3E              lcall   esc             ;abort if the user presses 
2051: 40 09                 jc      exit
2053: E4                    clr     a
2054: 93                    movc    a, @a+dptr      ;get time to display this p
2055: 60 EF                 jz      begin           ;restart when we hit the en
2057: 11 6C                 acall   delay
2059: A3                    inc     dptr
205A: 80 ED                 sjmp    loop            ;keep doing the animation..
                   
205C: 02 00 00     exit:    ljmp    0
                   
                   
                   
                   
                            ;write the bit pattern in Acc to port E.  We need t
                            ;save DPTR (holding our position in the table) befo
                            ;using DPTR to access the 82C55 chip.
                   update:
205F: C0 83                 push    dph
2061: C0 82                 push    dpl
2063: 90 F9 01              mov     dptr, #port_e
2066: F0                    movx    @dptr, a
2067: D0 82                 pop     dpl
2069: D0 83                 pop     dph
206B: 22                    ret
                   
                   
                   
                            ;delay for a number of ms (specified by acc)
                   delay:
206C: F8                    mov     r0, a
206D: 79 E6        dly2:    mov     r1, #230
206F: 00           dly3:    nop
2070: 00                    nop
2071: 00                    nop                     ;6 NOPs + DJNZ is 4.34 us
2072: 00                    nop                     ;with the 22.1184 MHz cryst
2073: 00                    nop
2074: 00                    nop
2075: D9 F8                 djnz    r1, dly3        ;repeat 230 times for 1 ms
2077: D8 F4                 djnz    r0, dly2        ;repeat for specified # of 
2079: 22                    ret
                   
                   
                   
                            ;The data table that is read by the MOVC instructio
207A: 7F 5A        table:   .db     01111111b, 90
207C: 3F 46                 .db     00111111b, 70
207E: 1F 32                 .db     00011111b, 50
2080: 8F 28                 .db     10001111b, 40
2082: C7 28                 .db     11000111b, 40
2084: E3 28                 .db     11100011b, 40
2086: F1 28                 .db     11110001b, 40
2088: F8 32                 .db     11111000b, 50
208A: FC 46                 .db     11111100b, 70
208C: FE 5A                 .db     11111110b, 90
208E: FC 46                 .db     11111100b, 70
2090: F8 32                 .db     11111000b, 50
2092: F1 28                 .db     11110001b, 40
2094: E3 28                 .db     11100011b, 40
2096: C7 28                 .db     11000111b, 40
2098: 8F 28                 .db     10001111b, 40
209A: 1F 32                 .db     00011111b, 50
209C: 3F 46                 .db     00111111b, 70
209E: FF 00                 .db     255,0           ;zero marks end of table
                   
                   
                   
