Ладно, рукавами все же лучше меряться, чем пиписьками :) Вот код на фрейм ПРОИЗВОЛЬНОЙ длины - хоть до 64КБ, с указателем ессно. 118 bytes of code, 2504 cycles/156.5 uS @16MHZ per 256 output bytes. Си давай! :)) Куски
fillram и
filltab к делу не относятся - это для проверки в симуляторе. Для профилирования подставляем требуемое значение в
buflen Целый час писал, минут 45 - только на комменты ушло :))
.nolist
#include "m2561def.inc"
.list
.equ packlen = 7 ;Packed bitstream length, bits
.equ unplen = 8 ;Unpacked bitstream length, bits
.equ buflen = 2048 ;Unpacked buffer size, up to (RAMSIZE-STACK) bytes
.equ stack = 64 ;Stack size, bytes
.dseg
.org SRAM_START+stack
buf: .byte buflen
.cseg
ldi r24,low(buf-1) ;Stack initialization
ldi r25,high(buf-1) ;
out spl,r24
out sph,r25
rcall fillram ;Fill BUFLEN RAM locations with repeating packed 7-byte test pattern
;
;
;
;Useful stuff starts here:
ldi ZL,low (buf+buflen) ;Load unpacked destination pointer
ldi ZH,high(buf+buflen) ;
ldi r24,low(buflen/8) ;Load repeat counter LSB
ldi r25,high(buflen/8) ;Load repeat counter MSB
;Reset cycle counter & stopwatch here
rcall unpack
;RAM @buf[(BUFLEN)] from now on is filled with unpacked pattern -
;ASCII "Keyboard" string repeated (BUFLEN/8) times
foo:
rjmp foo
;--------------------------------------------------------------------
unpack:
;Unpacks (BUFLEN*7/8) 7-bit packed bytes to BUFLEN unpacked bytes in RAM [buf]
;Code length = 118 bytes
; 86 cycles/5.4 uS @16MHZ per 8 output bytes
; 2504 cycles/156.5 uS @16MHZ per 256 output bytes
; 19976 cycles/1248.5 uS @16MHZ per 256 output bytes
; 79880 cycles/4992.5 uS @16MHZ per 8192 output bytes
ldi XL,low (buf+buflen*7/8) ;Load packed source pointer
ldi XH,high(buf+buflen*7/8) ;
unp_loop:
ld r6,-X ;Load last 7 packed bytes from RAM
ld r5,-X ;
ld r4,-X ;
ld r3,-X ;
ld r2,-X ;
ld r1,-X ;
ld r0,-X ;
rcall unpack_inline
st -Z,r7 ;Save last 8 unpacked bytes to RAM
st -Z,r6 ;
st -Z,r5 ;
st -Z,r4 ;
st -Z,r3 ;
st -Z,r2 ;
st -Z,r1 ;
st -Z,r0 ;
sbiw r24:r25,1 ;Repeat BUFLEN times
brne unp_loop
ret
;--------------------------------------------------------------------
;--------------------------------------------------------------------
unpack_inline:
;Input = 0:aaaaaaab 1:bbbbbbcc 2:cccccddd 3:ddddeeee 4:eeefffff 5:ffgggggg 6:ghhhhhhh
;Output = 0:0aaaaaaa 1:0bbbbbbb 2:0ccccccc 3:0ddddddd 4:0eeeeeee 5:0fffffff 6:0ggggggg 7:0hhhhhhh
;76 bytes, 41 cycles (2.5625 uS @16 MHZ)
; Iter.1
clr r7 ;To get CY = 0 from "ror r7"
lsr r0 ;0aaaaaaa
ror r1 ;bbbbbbbc
ror r2 ;ccccccdd
ror r3 ;dddddeee
ror r4 ;eeeeffff
ror r5 ;fffggggg
ror r6 ;gghhhhhh
ror r7 ;h0000000
; Iter.2
lsr r1 ;0bbbbbbb
ror r2 ;cccccccd
ror r3 ;ddddddee
ror r4 ;eeeeefff
ror r5 ;ffffgggg
ror r6 ;ggghhhhh
ror r7 ;hh000000
; Iter.3
lsr r2 ;0ccccccc
ror r3 ;ddddddde
ror r4 ;eeeeeeff
ror r5 ;fffffggg
ror r6 ;gggghhhh
ror r7 ;hhh00000
; Iter.4
lsr r3 ;0ddddddd
ror r4 ;eeeeeeef
ror r5 ;ffffffgg
ror r6 ;ggggghhh
ror r7 ;hhhh0000
; Iter.5
lsr r4 ;0eeeeeee
ror r5 ;fffffffg
ror r6 ;gggggghh
ror r7 ;hhhhh000
; Iter.6
lsr r5 ;0fffffff
ror r6 ;gggggggh
ror r7 ;hhhhhh00
; Iter.7
lsr r6 ;0ggggggg
ror r7 ;hhhhhhh0
; Iter.8
lsr r7 ;0hhhhhhh
ret
;--------------------------------------------------------------------
;--------------------------------------------------------------------
fillram:
;Fills (BUFLEN*PACKLEN/UNPLEN) RAM locations @buf[(BUFLEN*PACKLEN/UNPLEN)]
;with repeating packed 7-byte test pattern @filltab from code memory
ldi ZL,low (filltab*2) ;Load buffer fill pattern address pointer
ldi ZH,high(filltab*2) ;(7-byte table in Flash)
ldi XH,high(buf) ;Load RAM buffer pointer
ldi XL,low (buf) ;
ldi r24,low(buflen/unplen) ;# of 7-byte patterns to copy LSB
ldi r25,high(buflen/unplen) ;# of 7-byte patterns to copy MSB
fillp:
ldi r16,packlen ;Set pattern byte counter
fill7:
lpm r0,Z+ ;Read byte from Flash
st X+,r0 ;Copy to RAM buffer
dec r16 ;Repeat 7 times
brne fill7 ;
sbiw ZH:ZL,packlen ;Rewind pattern ptr
sbiw r24:r25,1 ;Repeat (BUFLEN/UNPLEN) times
brne fillp ;
ret
;--------------------------------------------------------------------
filltab:
.db $FF&('K' << 1)|('e' >> 6),\
$FF&('e' << 2)|('y' >> 5),\
$FF&('y' << 3)|('b' >> 4),\
$FF&('b' << 4)|('o' >> 3),\
$FF&('o' << 5)|('a' >> 2),\
$FF&('a' << 6)|('r' >> 1),\
$FF&('r' << 7)|('d' >> 0),0
.exit