2 ; Copyright (C) 2010,2015 Bernd Porr, mail@berndporr.me.uk
3 ; For usbduxsigma.c 0.5+
5 ; This program is free software; you can redistribute it and/or modify
6 ; it under the terms of the GNU General Public License as published by
7 ; the Free Software Foundation; either version 2 of the License, or
8 ; (at your option) any later version.
10 ; This program is distributed in the hope that it will be useful,
11 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ; GNU General Public License for more details.
15 ; You should have received a copy of the GNU General Public License
16 ; along with this program; if not, write to the Free Software
17 ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 ; Firmware: usbduxsigma_firmware.asm for usbduxsigma.c
21 ; Description: University of Stirling USB DAQ & INCITE Technology Limited
22 ; Devices: [ITL] USB-DUX-SIGMA (usbduxsigma.ko)
23 ; Author: Bernd Porr <mail@berndporr.me.uk>
24 ; Updated: 20 Jul 2015
33 ;;; a couple of flags in high memory
34 .equ CMD_FLAG,80h ; flag for the next in transfer
35 .equ PWMFLAG,81h ; PWM on or off?
36 .equ MAXSMPL,82H ; maximum number of samples, n channellist
37 .equ MUXSG0,83H ; content of the MUXSG0 register
38 .equ INTERVAL,88h ; uframe/frame interval
39 .equ INTCTR,89h ; interval counter
40 .equ DABUFFER,0F0h ; buffer with DA values
42 ;;; in precious low memory but accessible within one clock cycle
49 .org 0000h ; after reset the processor starts here
50 ljmp main ; jump to the main loop
53 ljmp isr0 ; external interrupt 0: /DRY
55 .org 0043h ; the IRQ2-vector
56 ljmp jmptbl ; irq service-routine
58 .org 0100h ; start of the jump table
60 jmptbl: ljmp sudav_isr
159 ;; clear the USB2 irq bit and return
184 mov dptr,#0E7C0h ; EP1in
185 mov a,IOB ; get DIO D
186 movx @dptr,a ; store it
188 mov a,IOC ; get DIO C
189 movx @dptr,a ; store it
191 mov a,IOD ; get DIO B
192 movx @dptr,a ; store it
195 movx @dptr,a ; pad it up
198 mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
200 mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
203 mov a,#00000100b ; clear the ep1in
217 ;;; this is triggered when DRY goes low
242 lcall readADCch ; read one channel
254 clr IOA.7 ; START = 0
256 ;; arm the endpoint and send off the data
257 mov DPTR,#EP6BCH ; byte count H
259 lcall syncdelaywr ; wait until we can write again
261 mov r0,#MAXSMPL ; number of samples to transmit
265 add a,#4 ; four bytes for DIO
266 mov DPTR,#EP6BCL ; byte count L
267 lcall syncdelaywr ; wait until we can write again
291 ;;; basically only initialises the processor and
292 ;;; then engages in an endless loop
294 mov DPTR,#CPUCS ; CPU control register
295 mov a,#00010000b ; 48Mhz
299 mov a,#00000011b ; allows skip
302 mov dptr,#INTSETUP ; IRQ setup register
303 mov a,#08h ; enable autovector
310 mov IP,#01H ; int0 has highest interrupt priority
311 mov EIP,#0 ; all USB interrupts have low priority
313 lcall initAD ; init the ports to the converters
315 lcall initeps ; init the isochronous data-transfer
317 ;;; main loop, rest is done as interrupts
321 mov r0,#PWMFLAG ; pwm on?
325 mov a,GPIFTRIG ; GPIF status
326 anl a,#80h ; done bit
327 jz mloop2 ; GPIF still busy
329 mov a,#01h ; WR,EP4, 01 = EP4
330 mov GPIFTRIG,a ; restart it
332 sjmp mloop2 ; loop for ever
335 ;;; initialise the ports for the AD-converter
337 mov r0,#MAXSMPL ; length of channellist
338 mov @r0,#0 ; we don't want to accumlate samples
340 mov ASYNC_ON,#0 ; async enable
345 mov OEA,#11100000b ; PortA7,A6,A5 Outputs
346 mov IOA,#01100000b ; /CS = 1 and START = 0
347 mov dptr,#IFCONFIG ; switch on clock on IFCLK pin
348 mov a,#10100000b ; gpif, 30MHz, internal IFCLK -> 15MHz for AD
351 mov SCON0,#013H ; ser rec en, TX/RX: stop, 48/12MHz=4MHz clock
354 mov a,#00001000b ; special function for port E: RXD0OUT
360 ;;; send a byte via SPI
361 ;;; content in a, dptr1 is changed
362 ;;; the lookup is done in dptr1 so that the normal dptr is not affected
363 ;;; important: /cs needs to be reset to 1 by the caller: IOA.5
368 mov dptr,#swap_lut ; lookup table
369 movc a,@a+dptr ; reverse bits
371 ;; clear interrupt flag, is used to detect
372 ;; successful transmission
373 clr SCON0.1 ; clear interrupt flag
375 ;; start transmission by writing the byte
376 ;; in the transmit buffer
377 mov SBUF0,a ; start transmission
379 ;; wait for the end of the transmission
381 mov a,SCON0 ; get transmission status
382 jnb ACC.1,sendSPIwait ; loop until transmitted
391 ;;; receive a byte via SPI
392 ;;; content in a, dptr is changed
393 ;;; the lookup is done in dptr1 so that the normal dptr is not affected
394 ;;; important: the /CS needs to be set to 1 by the caller via "setb IOA.5"
400 ;; clearning the RI bit starts reception of data
404 ;; RI goes back to 1 after the reception of the 8 bits
405 mov a,SCON0 ; get receive status
406 jnb ACC.0,recSPIwait; loop until all bits received
408 ;; read the byte from the buffer
409 mov a,SBUF0 ; get byte
411 ;; lookup: reverse the bits
412 mov dptr,#swap_lut ; lookup table
413 movc a,@a+dptr ; reverse the bits
423 ;;; register address in a
424 ;;; returns value in a
426 anl a,#00001111b ; mask out the index to the register
427 orl a,#01000000b ; 010xxxxx indicates register read
428 clr IOA.5 ; ADC /cs to 0
429 lcall sendSPI ; send the command over
430 lcall recSPI ; read the contents back
431 setb IOA.5 ; ADC /cs to 1
436 ;;; writes to a register
437 ;;; register address in a
441 anl a,#00001111b ; mask out the index to the register
442 orl a,#01100000b ; 011xxxxx indicates register write
444 clr IOA.5 ; ADC /cs to 0
450 setb IOA.5 ; ADC /cs to 1
453 lcall registerRead ; check if the data has arrived in the ADC
454 mov 0f0h,r0 ; register B
455 cjne a,0f0h,registerWrite ; something went wrong, try again
461 ;;; initilise the endpoints
465 movx @dptr,a ; reset all fifos
475 movx @dptr,a ; normal operat
478 mov a,#10010010b ; valid, out, double buff, iso
482 mov a,#00000000b ; manual
485 mov dptr,#EP2BCL ; "arm" it
487 movx @DPTR,a ; can receive data
488 lcall syncdelay ; wait to sync
489 movx @DPTR,a ; can receive data
490 lcall syncdelay ; wait to sync
491 movx @DPTR,a ; can receive data
492 lcall syncdelay ; wait to sync
495 mov a,#10100000b ; valid
498 mov dptr,#EP1OUTBC ; "arm" it
500 movx @DPTR,a ; can receive data
501 lcall syncdelay ; wait until we can write again
502 movx @dptr,a ; make shure its really empty
503 lcall syncdelay ; wait
505 mov DPTR,#EP6CFG ; ISO data from here to the host
506 mov a,#11010010b ; Valid
507 movx @DPTR,a ; ISO transfer, double buffering
509 mov DPTR,#EP8CFG ; EP8
510 mov a,#11100000b ; BULK data from here to the host
514 mov a,#1 ; interrupt on pin A0
518 mov dptr,#EPIE ; interrupt enable
519 mov a,#10001100b ; enable irq for ep1out,8,ep1in
522 mov dptr,#EPIRQ ; clear IRQs
526 mov DPTR,#USBIE ; USB int enables register
527 mov a,#2 ; enables SOF (1ms/125us interrupt)
530 setb TCON.0 ; make INT0 edge triggered, falling edge
532 mov EIE,#00000001b ; enable INT2/USBINT in the 8051's SFR
533 mov IE,#81h ; IE, enable all interrupts and INT0
538 ;;; Reads one ADC channel from the converter and stores
539 ;;; the result at dptr
541 ;; reading data is done by just dropping /CS and start reading and
542 ;; while keeping the IN signal to the ADC inactive
547 movx @dptr,a ; store the byte
548 inc dptr ; increment pointer
566 setb IOA.5 ; /cs to 1
572 ;;; interrupt-routine for SOF
590 mov r0,#INTCTR ; interval counter
591 mov a,@r0 ; get the value
593 mov @r0,a ; save it again
594 jz sof_adc ; we do ADC functions
595 ljmp epfull ; we skip all adc functions
598 mov r1,#INTERVAL ; get the interval
600 mov @r0,a ; save it in the counter
603 jnz epfull ; EP6-buffer is full
605 mov a,IOA ; conversion running?
608 ;; make sure that we are starting with the first channel
610 mov a,@r0 ; get config of MUXSG0
613 lcall registerWrite ; this resets the channel sequence
615 setb IOA.7 ; start converter, START = 1
617 mov dptr,#0f800h ; EP6 buffer
618 mov a,IOD ; get DIO D
619 movx @dptr,a ; store it
621 mov a,IOC ; get DIO C
622 movx @dptr,a ; store it
624 mov a,IOB ; get DIO B
625 movx @dptr,a ; store it
628 movx @dptr,a ; pad it up
629 inc dptr ; algin along a 32 bit word
640 ;; do the D/A conversion
643 jnz epempty ; nothing to get
645 mov dptr,#0F000H ; EP2 fifo buffer
646 lcall dalo ; conversion
648 mov dptr,#EP2BCL ; "arm" it
650 lcall syncdelaywr ; wait for the rec to sync
651 lcall syncdelaywr ; wait for the rec to sync
654 mov a,IOA ; conversion running?
661 mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
663 mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
665 mov DPTR,#USBIRQ ; points to the SOF
666 mov a,#2 ; clear the SOF
689 ;; erase all data in ep8
697 mov a,#0 ; normal operation
703 ;; throw out old data
711 mov a,#0 ; normal operation
716 ;;; configure the ADC converter
717 ;;; the dptr points to the init data:
718 ;;; CONFIG 0,1,3,4,5,6
719 ;;; note that CONFIG2 is omitted
721 clr IOA.7 ; stops ADC: START line of ADC = L
722 setb IOA.5 ; ADC /cs to 1
724 ;; just in case something has gone wrong
729 mov a,#11000000b ; reset the ADC
730 clr IOA.5 ; ADC /cs to 0
732 setb IOA.5 ; ADC /cs to 1
755 mov @r0,a ; store it for reset purposes
775 ;;; interrupt-routine for ep1out
776 ;;; receives the channel list and other commands
794 mov dptr,#0E780h ; FIFO buffer of EP1OUT
795 movx a,@dptr ; get the first byte
796 mov r0,#CMD_FLAG ; pointer to the command byte
797 mov @r0,a ; store the command byte for ep8
799 mov dptr,#ep1out_jmp; jump table for the different functions
800 rl a ; multiply by 2: sizeof sjmp
801 jmp @a+dptr ; jump to the jump table
802 ;; jump table, corresponds to the command bytes defined
807 sjmp config_digital_b; a=2
808 sjmp write_digital_b ; a=3
809 sjmp initsgADchannel ; a=4
814 sjmp startadcint ; a=9
830 mov dptr,#0e781h ; FIFO buffer of EP1OUT
831 lcall configADC ; configures the ADC esp sel the channel
833 lcall reset_ep8 ; reset FIFO: get rid of old bytes
834 ;; Save new A/D data in EP8. This is the first byte
835 ;; the host will read during an INSN. If there are
836 ;; more to come they will be handled by the ISR of
838 lcall ep8_ops ; get A/D data
843 mov dptr,#0e781h ; FIFO buffer of EP1OUT from 2nd byte
845 movx a,@dptr ; interval is the 1st byte
846 inc dptr ; data pointer
847 sjmp startadc2 ; the other paramters as with startadc
850 ;;; we write to the registers of the A/D converter
852 mov dptr,#0e781h ; FIFO buffer of EP1OUT from 2nd byte
854 mov a,#1 ; interval is 1 here all the time
856 mov r0,#INTERVAL ; set it
858 mov r0,#INTCTR ; the counter is also just one
861 movx a,@dptr ; get length of channel list
864 mov @r0,a ; length of the channel list
867 lcall configADC ; configures all registers
869 mov ASYNC_ON,#1 ; async enable
871 lcall reset_ep6 ; reset FIFO
873 ;; load new A/D data into EP6
874 ;; This must be done. Otherwise the ISR is never called.
875 ;; The ISR is only called when data has _left_ the
876 ;; ep buffer here it has to be refilled.
877 lcall ep6_arm ; fill with dummy data
881 ;;; Single DA conversion. The 2 bytes are in the FIFO buffer
883 mov dptr,#0e781h ; FIFO buffer of EP1OUT
884 lcall dalo ; conversion
887 ;;; configure the port B as input or output (bitwise)
889 mov dptr,#0e781h ; FIFO buffer of EP1OUT
890 movx a,@dptr ; get the second byte
892 mov OEB,a ; set the output enable bits
893 movx a,@dptr ; get the second byte
896 movx a,@dptr ; get the second byte
901 ;;; Write one byte to the external digital port B
902 ;;; and prepare for digital read
904 mov dptr,#0e781h ; FIFO buffer of EP1OUT
905 movx a,@dptr ; command[1]
907 mov OEB,a ; output enable
908 movx a,@dptr ; command[2]
911 movx a,@dptr ; command[3]
914 movx a,@dptr ; command[4]
917 movx a,@dptr ; command[5]
920 movx a,@dptr ; command[6]
924 lcall reset_ep8 ; reset FIFO of ep 8
926 ;; fill ep8 with new data from port B
927 ;; When the host requests the data it's already there.
928 ;; This must be so. Otherwise the ISR is not called.
929 ;; The ISR is only called when a packet has been delivered
930 ;; to the host. Thus, we need a packet here in the
932 lcall ep8_ops ; get digital data
935 ;; for all commands the same
939 lcall syncdelaywr ; arm
940 lcall syncdelaywr ; arm
941 lcall syncdelaywr ; arm
944 mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
946 mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
949 mov a,#00001000b ; clear the ep1outirq
971 ;;; save all DA channels from the endpoint buffer in a local buffer
973 movx a,@dptr ; number of bytes to send out
974 inc dptr ; pointer to the first byte
975 mov r1,#DABUFFER ; buffer for DA values
977 inc r1 ; inc pointer to local buffer
980 movx a,@dptr ; get the byte
981 inc dptr ; point to the high byte
982 mov @r1,a ; save it in the buffer
984 movx a,@dptr ; get the channel number
985 inc dptr ; get ready for the next channel
988 djnz r0,nextDAlo ; next channel
992 ;;; write to the DA converter
994 mov r1,#DABUFFER ; buffer of the DA values
995 mov a,@r1 ; get the channel count
996 jz DAret ; nothing to do
997 inc r1 ; pointer to the first byte
1000 mov a,@r1 ; get the byte
1001 inc r1 ; point to the high byte
1002 mov r3,a ; store in r3 for writeDA
1003 mov a,@r1 ; get the channel number
1004 inc r1 ; get ready for the next channel
1005 push 1 ; is modified in the subroutine
1006 lcall writeDA ; write value to the DAC
1007 pop 1 ; get the pointer back
1008 djnz r0,nextDA ; next channel
1015 ;;; channel number in a
1018 anl a,#00000011b ; 4 channels
1019 mov r1,#6 ; the channel number needs to be shifted up
1021 rl a ; bit shift to the left
1022 djnz r1,writeDA2 ; do it 6 times
1023 orl a,#00010000b ; update outputs after write
1026 anl a,#11110000b ; get the upper nibble
1027 mov r1,#4 ; shift it up to the upper nibble
1029 rr a ; shift to the upper to the lower
1031 orl a,r2 ; merge with the channel info
1032 clr IOA.6 ; /SYNC (/CS) of the DA to 0
1033 lcall sendSPI ; send it out to the SPI
1034 mov a,r3 ; get data again
1035 anl a,#00001111b ; get the lower nibble
1036 mov r1,#4 ; shift that to the upper
1040 anl a,#11110000b ; make sure that's empty
1042 setb IOA.6 ; /SYNC (/CS) of the DA to 1
1047 ;;; arm ep6: this is just a dummy arm to get things going
1049 mov DPTR,#EP6BCH ; byte count H
1051 lcall syncdelaywr ; wait until the length has arrived
1053 mov DPTR,#EP6BCL ; byte count L
1055 lcall syncdelaywr ; wait until the length has been proc
1060 ;;; converts one analog/digital channel and stores it in EP8
1061 ;;; also gets the content of the digital ports B,C and D depending on
1062 ;;; the COMMAND flag
1064 mov dptr,#0fc01h ; ep8 fifo buffer
1066 movx @dptr,a ; set H=0
1067 mov dptr,#0fc00h ; low byte
1070 movx @dptr,a ; save command byte
1072 mov dptr,#ep8_jmp ; jump table for the different functions
1073 rl a ; multiply by 2: sizeof sjmp
1074 jmp @a+dptr ; jump to the jump table
1075 ;; jump table, corresponds to the command bytes defined
1078 sjmp ep8_err ; a=0, err
1079 sjmp ep8_err ; a=1, err
1080 sjmp ep8_err ; a=2, err
1081 sjmp ep8_dio ; a=3, digital read
1082 sjmp ep8_sglchannel ; a=4, analog A/D
1083 sjmp ep8_err ; a=5, err
1084 sjmp ep8_err ; a=6, err
1086 ;; read one A/D channel
1088 setb IOA.7 ; start converter, START = 1
1089 ;; we do polling: we wait until DATA READY is zero
1091 mov a,IOA ; get /DRDY
1092 jb ACC.0,sglchwait ; wait until data ready (DRDY=0)
1093 mov DPTR,#0fc01h ; EP8 FIFO
1094 lcall readADCch ; get one reading
1095 clr IOA.7 ; stop the converter, START = 0
1097 sjmp ep8_send ; send the data
1099 ;; read the digital lines
1101 mov DPTR,#0fc01h ; store the contents of port B
1102 mov a,IOB ; in the next
1103 movx @dptr,a ; entry of the buffer
1106 movx @dptr,a ; next byte of the EP
1109 movx @dptr,a ; port D
1112 mov DPTR,#EP8BCH ; byte count H
1116 mov DPTR,#EP8BCL ; byte count L
1117 mov a,#10H ; 16 bytes, bec it's such a great number...
1118 lcall syncdelaywr ; send the data over to the host
1125 ;;; EP8 interrupt is the endpoint which sends data back after a command
1126 ;;; The actual command fills the EP buffer already
1127 ;;; but for INSNs we need to deliver more data if the count > 1
1148 mov a,EXIF ; FIRST clear the USB (INT2) interrupt request
1150 mov EXIF,a ; Note: EXIF reg is not 8051 bit-addressable
1153 mov a,#10000000b ; clear the ep8irq
1175 ;;; GPIF waveform for PWM
1177 ;; 0 1 2 3 4 5 6 7(not used)
1178 ;; len (gives 50.007Hz)
1179 .db 195, 195, 195, 195, 195, 195, 1, 1
1182 .db 002H, 006H, 002H, 002H, 002H, 002H, 002H, 002H
1185 .db 0ffH, 0ffH, 0ffH, 0ffH, 0ffH, 0ffH, 0ffH, 0ffH
1188 .db 000H, 000H, 000H, 000H, 000H, 000H, 000H, 000H
1192 mov r0,#PWMFLAG ; flag for PWM
1193 mov a,#0 ; PWM (for the main loop)
1196 mov dptr,#IFCONFIG ; switch off GPIF
1197 mov a,#10100000b ; gpif, 30MHz, internal IFCLK
1204 mov dptr,#IFCONFIG ; switch on IFCLK signal
1205 mov a,#10100010b ; gpif, 30MHz, internal IFCLK
1208 mov OEB,0FFH ; output to port B
1211 mov a,#10100000b ; valid, out, bulk
1214 ;; reset the endpoint
1218 mov a,#84h ; reset EP4 + NAK
1220 mov a,#0 ; normal op
1224 mov a,#0H ; discard packets
1225 lcall syncdelaywr ; empty FIFO buffer
1226 lcall syncdelaywr ; empty FIFO buffer
1228 ;; aborts all transfers by the GPIF
1230 mov a,#0ffh ; abort all transfers
1233 ;; wait for GPIF to finish
1235 mov a,GPIFTRIG ; GPIF status
1236 anl a,#80h ; done bit
1237 jz wait_f_abort ; GPIF busy
1239 mov dptr,#GPIFCTLCFG
1240 mov a,#10000000b ; tri state for CTRL
1243 mov dptr,#GPIFIDLECTL
1244 mov a,#11110000b ; all CTL outputs low
1247 ;; abort if FIFO is empty
1248 mov a,#00000001b ; abort if empty
1249 mov dptr,#EP4GPIFFLGSEL
1253 mov a,#00000001b ; stop if GPIF flg
1254 mov dptr,#EP4GPIFPFSTOP
1257 ;; transaction counter
1262 ;; transaction counter
1267 ;; transaction counter
1268 mov a,#0ffH ; 512 bytes
1272 ;; transaction counter
1277 ;; RDY pins. Not used here.
1279 mov dptr,#GPIFREADYCFG
1282 ;; drives the output in the IDLE state
1284 mov dptr,#GPIFIDLECS
1287 ;; direct data transfer from the EP to the GPIF
1288 mov dptr,#EP4FIFOCFG
1289 mov a,#00010000b ; autoout=1, byte-wide
1292 ;; waveform 0 is used for FIFO out
1293 mov dptr,#GPIFWFSELECT
1298 ;; transfer the delay byte from the EP to the waveform
1299 mov dptr,#0e781h ; EP1 buffer
1300 movx a,@dptr ; get the delay
1301 mov dptr,#waveform ; points to the waveform
1302 mov r2,#6 ; fill 6 bytes
1304 movx @dptr,a ; save timing in a xxx
1306 djnz r2,timloop ; fill the 6 delay bytes
1309 mov AUTOPTRH2,#0E4H ; XDATA0H
1311 mov AUTOPTRL2,#00H ; XDATA0L
1314 mov dptr,#waveform ; points to the waveform
1316 mov AUTOPTRSETUP,#7 ; autoinc and enable
1319 mov r2,#20H ; 32 bytes to transfer
1342 mov r0,#PWMFLAG ; flag for PWM
1343 mov a,#1 ; PWM (for the main loop)
1350 ;; need to delay every time the byte counters
1351 ;; for the EPs have been changed.
1372 .org 1F00h ; lookup table at the end of memory
1375 .db 0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,240,8,136
1376 .db 72,200,40,168,104,232,24,152,88,216,56,184,120,248,4,132,68,196,36,164,100
1377 .db 228,20,148,84,212,52,180,116,244,12,140,76,204,44,172,108,236,28,156,92,220
1378 .db 60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,210,50,178,114,242,10
1379 .db 138,74,202,42,170,106,234,26,154,90,218,58,186,122,250,6,134,70,198,38,166
1380 .db 102,230,22,150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,30,158,94
1381 .db 222,62,190,126,254,1,129,65,193,33,161,97,225,17,145,81,209,49,177,113,241,9
1382 .db 137,73,201,41,169,105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,165
1383 .db 101,229,21,149,85,213,53,181,117,245,13,141,77,205,45,173,109,237,29,157,93
1384 .db 221,61,189,125,253,3,131,67,195,35,163,99,227,19,147,83,211,51,179,115,243,11
1385 .db 139,75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,135,71,199,39,167
1386 .db 103,231,23,151,87,215,55,183,119,247,15,143,79,207,47,175,111,239,31,159,95
1387 .db 223,63,191,127,255