basic loading and saving
This commit is contained in:
+339
-173
@@ -4616,6 +4616,14 @@ FULLSETTOP:
|
||||
FULLMSG:
|
||||
.BYTE "[FULL MEMORY]",CR,LF,0,0
|
||||
|
||||
; Every tape block starts with a type byte followed by 128 data bytes.
|
||||
; Header data contains a little-endian block count, byte length and filename.
|
||||
TAPE_TYPE_RAW .equ 0
|
||||
TAPE_TYPE_BINARY .equ 1
|
||||
TAPE_TYPE_BAS_PROG .equ 2
|
||||
TAPE_TYPE_BAS_ARR .equ 3
|
||||
TAPE_DATA_SIZE .equ 128
|
||||
|
||||
CLOAD: ld a,(hl) ; get byte after "CLOAD"
|
||||
cp ZTIMES ; "*" token? ("CLOAD*")
|
||||
jp z,FCERR ; yes - array load (ARRLD1)
|
||||
@@ -4624,8 +4632,54 @@ CLOAD: ld a,(hl) ; get byte after "CLOAD"
|
||||
cp '#' ; 'cload#'?
|
||||
jp z,CLOADB ; yes - load binary
|
||||
; just cload - load basic
|
||||
jp FCERR
|
||||
|
||||
or a ; no arguments allowed
|
||||
jp nz,FCERR
|
||||
ld hl,CLSTARTMSG ; ask the user to start the tape
|
||||
call PRS ; print the prompt
|
||||
ld b,TAPE_TYPE_BAS_PROG ; expect a BASIC program header
|
||||
call CLREADHEADER ; bc = blocks, de = length, hl = filename
|
||||
call CLPRINTHEADER ; print block count and filename
|
||||
ld b,d ; move exact length to bc
|
||||
ld c,e ; bc = exact program length
|
||||
ld a,b ; check the high byte of the length
|
||||
or a ; 256 bytes or more is always valid here
|
||||
jr nz,1$ ; skip the minimum-length check
|
||||
ld a,c ; check a short program's low byte
|
||||
cp 2 ; an empty program still has its end marker
|
||||
jp c,FCERR ; less than two bytes is not a program
|
||||
1$: ld hl,(BASTXT) ; get the program load address
|
||||
add hl,bc ; calculate the exact program end
|
||||
jp c,OMERR ; reject a wrapped end address
|
||||
ld de,40 ; keep BASIC's minimum working space free
|
||||
add hl,de ; include the working-space margin
|
||||
jp c,OMERR ; reject a wrapped limit address
|
||||
ld de,(STRSPC) ; get the bottom of string/stack space
|
||||
call CPDEHL ; compare required memory with available RAM
|
||||
jp nc,OMERR ; program would enter BASIC's working area
|
||||
ld hl,(BASTXT) ; calculate the exact end once more
|
||||
add hl,bc ; hl = address following the program
|
||||
push hl ; preserve exact program end
|
||||
ld de,(BASTXT) ; load the program at the BASIC text area
|
||||
call CLLOADBLOCKS ; copy only the exact number of bytes
|
||||
pop hl ; restore the exact program end
|
||||
dec hl ; point to the last program byte
|
||||
ld a,(hl) ; get the last end-marker byte
|
||||
or a ; it must be zero
|
||||
jp nz,FCERR ; reject an invalid program terminator
|
||||
dec hl ; point to the first end-marker byte
|
||||
ld a,(hl) ; get the first end-marker byte
|
||||
or a ; it must also be zero
|
||||
jp nz,FCERR ; reject an invalid program terminator
|
||||
push hl
|
||||
ld hl,CLCLRF ; print newline
|
||||
call PRS
|
||||
ld hl,OKMSG
|
||||
call PRS ; print ok message
|
||||
pop hl
|
||||
inc hl ; restore the address after the program
|
||||
inc hl
|
||||
ld (PROGND),hl ; install the new program end
|
||||
jp SETPTR ; clear variables, relink and return to prompt
|
||||
CLOADB: inc hl ; skip #
|
||||
call GETNUM ; evaluate numeric expression
|
||||
call DEINT ; convert FPREG to de
|
||||
@@ -4634,71 +4688,124 @@ CLOADB: inc hl ; skip #
|
||||
push hl
|
||||
push bc
|
||||
push de
|
||||
|
||||
ld hl,CLSTARTMSG
|
||||
call PRS
|
||||
|
||||
; Load block
|
||||
call CLREADBLOCK
|
||||
; hl contains block, check block type
|
||||
ld a,(hl)
|
||||
cp 1 ; first block needs to be a header
|
||||
jp nz,CLNOHDR ; First block is not a header
|
||||
; first block is a header, get nr of blocks
|
||||
inc hl
|
||||
ld de,(hl)
|
||||
; print number of blocks to load
|
||||
push de
|
||||
push hl
|
||||
ex de,hl
|
||||
call PRNTHL
|
||||
ld hl,CLBLOCKSMSG
|
||||
call PRS
|
||||
pop hl
|
||||
inc hl
|
||||
inc hl ; get filename
|
||||
; TODO filename always null terminated?
|
||||
call PRS ; print filename
|
||||
; de contains the nr of blocks to load
|
||||
; TODO check de>0
|
||||
pop de
|
||||
1$: push de ; save repeat counter
|
||||
call CLREADBLOCK ; hl = new data
|
||||
; TODO check block type
|
||||
inc hl ; goto start of data
|
||||
pop de ; get repeat counter
|
||||
push hl ; save stored data
|
||||
exx
|
||||
pop hl ; get stored data back
|
||||
pop de ; get destination
|
||||
ld bc,128 ; block size
|
||||
ldir ; copy data to memory
|
||||
push de ; store destination address
|
||||
exx
|
||||
dec de
|
||||
ld a,e
|
||||
cp 0
|
||||
jr nz,1$ ; repeat if not done yet
|
||||
ld a,d
|
||||
cp 0
|
||||
jr nz,1$ ; repeat if not done yet
|
||||
pop de
|
||||
ld b,TAPE_TYPE_BINARY
|
||||
call CLREADHEADER ; bc = blocks, de = length, hl = filename
|
||||
call CLPRINTHEADER
|
||||
ld b,d
|
||||
ld c,e ; bc = exact file length
|
||||
pop de ; destination address
|
||||
call CLLOADBLOCKS
|
||||
pop bc
|
||||
pop hl
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Read and decode a tape header
|
||||
; needs b (type of header to expect)
|
||||
; returns bc (number of following blocks), de (byte length), hl (filename)
|
||||
; errors do not return
|
||||
; uses a
|
||||
; -------------------------------------------------------
|
||||
CLREADHEADER:
|
||||
push bc
|
||||
call CLREADBLOCK
|
||||
ld a,(hl)
|
||||
pop bc
|
||||
cp b
|
||||
jp nz,CLNOHDR
|
||||
inc hl
|
||||
ld c,(hl) ; block count is little-endian
|
||||
inc hl
|
||||
ld b,(hl)
|
||||
inc hl
|
||||
ld e,(hl) ; byte length is little-endian
|
||||
inc hl
|
||||
ld d,(hl)
|
||||
inc hl ; point to filename
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Print the block count and filename from a tape header
|
||||
; needs bc (number of blocks), hl (filename)
|
||||
; preserves bc,de
|
||||
; uses a,h,l
|
||||
; -------------------------------------------------------
|
||||
CLPRINTHEADER:
|
||||
push bc
|
||||
push de
|
||||
push hl
|
||||
ld h,b
|
||||
ld l,c
|
||||
call PRNTHL
|
||||
ld hl,CLBLOCKSMSG
|
||||
call PRS
|
||||
pop hl
|
||||
call PRS
|
||||
pop de
|
||||
pop bc
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Load tape data into memory, including a partial final block
|
||||
; needs bc (file length in bytes), de (destination address)
|
||||
; returns de (first address after loaded data)
|
||||
; returns bc (zero)
|
||||
; uses a,h,l
|
||||
; -------------------------------------------------------
|
||||
CLLOADBLOCKS:
|
||||
ld a,b
|
||||
or c
|
||||
ret z
|
||||
1$: push bc
|
||||
push de
|
||||
call CLREADBLOCK
|
||||
inc hl ; skip block type
|
||||
pop de
|
||||
pop bc ; remaining byte count
|
||||
ld a,b
|
||||
or a
|
||||
jr nz,2$ ; at least 256 bytes remain
|
||||
ld a,c
|
||||
cp TAPE_DATA_SIZE
|
||||
jr nc,2$
|
||||
ldir ; copy the partial final block
|
||||
ret
|
||||
2$: push bc
|
||||
ld bc,TAPE_DATA_SIZE
|
||||
ldir
|
||||
pop bc
|
||||
ld a,c ; subtract one full block
|
||||
sub TAPE_DATA_SIZE
|
||||
ld c,a
|
||||
ld a,b
|
||||
sbc a,0
|
||||
ld b,a
|
||||
jr 1$
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Read one of two redundant copies of a tape block
|
||||
; returns hl (block buffer)
|
||||
; errors do not return
|
||||
; uses a,b,c,d,e,h,l
|
||||
; -------------------------------------------------------
|
||||
CLREADBLOCK:
|
||||
call BIOS_CAS_READ_BLOCK
|
||||
jr c,3$
|
||||
push hl ; preserve the first copy
|
||||
ld a,'.' ; block read correctly
|
||||
call OUTC
|
||||
jr 1$
|
||||
ld a,'o' ; skip redundant copy
|
||||
call OUTC
|
||||
call BIOS_CAS_READ_BLOCK_DRY
|
||||
jr 2$
|
||||
3$: ld a,'x' ; block failed, try redundant block
|
||||
call OUTC
|
||||
call BIOS_CAS_WAIT_SILENCE
|
||||
call BIOS_CAS_READ_BLOCK
|
||||
push hl
|
||||
jr c,4$
|
||||
push hl ; preserve the redundant copy
|
||||
ld a,'.' ; redundant block read correctly
|
||||
call OUTC
|
||||
jr 2$
|
||||
@@ -4710,12 +4817,7 @@ CLREADBLOCK:
|
||||
call BIOS_CAS_WAIT_SILENCE
|
||||
pop bc
|
||||
pop af
|
||||
jr CLERR
|
||||
1$: push hl ; save hl
|
||||
ld a,'o' ; skip redundant block
|
||||
call OUTC
|
||||
call BIOS_CAS_READ_BLOCK_DRY
|
||||
; Ignore errors on this block
|
||||
jp CLERR
|
||||
2$: ; but make sure it is silent again
|
||||
call BIOS_CAS_WAIT_SILENCE
|
||||
pop hl
|
||||
@@ -4731,20 +4833,17 @@ CLERR: cp 1
|
||||
cp 4
|
||||
jr z,CLECHS
|
||||
jp FCERR ; Unknown error
|
||||
CLECAL: ld h,0
|
||||
ld l,b ; get specific error code
|
||||
call PRNTHL ; print specific error code
|
||||
ld hl, CLECALMSG
|
||||
jr CLEPRINT
|
||||
CLESYN: ld h,0
|
||||
ld l,b ; get specific error code
|
||||
call PRNTHL ; print specific error code
|
||||
ld hl, CLESYNMSG
|
||||
jr CLEPRINT
|
||||
CLERED: ld h,0
|
||||
ld l,b ; get specific error code
|
||||
call PRNTHL ; print specific error code
|
||||
ld hl, CLEREDMSG
|
||||
CLECAL: ld hl,CLECALMSG
|
||||
jr CLDETAIL
|
||||
CLESYN: ld hl,CLESYNMSG
|
||||
jr CLDETAIL
|
||||
CLERED: ld hl,CLEREDMSG
|
||||
CLDETAIL:
|
||||
push hl
|
||||
ld h,0
|
||||
ld l,b ; print specific error code
|
||||
call PRNTHL
|
||||
pop hl
|
||||
jr CLEPRINT
|
||||
CLECHS: ld hl,CLECHSMSG
|
||||
jr CLEPRINT
|
||||
@@ -4752,9 +4851,6 @@ CLNOHDR:
|
||||
ld hl,CLNOHDRMSG
|
||||
CLEPRINT:
|
||||
call PRS
|
||||
pop de
|
||||
pop bc
|
||||
pop hl
|
||||
jp FCERR
|
||||
|
||||
CLSTARTMSG: .db "Play tape...",0ah,0dh,00h
|
||||
@@ -4768,123 +4864,193 @@ CLCLRF: .db 0ah,0dh,00h
|
||||
|
||||
CSAVE: ld a,(hl) ; get byte after "CSAVE"
|
||||
cp ZTIMES ; "*" token? ("CSAVE*")
|
||||
jp z,FCERR ; yes - array load (ARRLD1)
|
||||
jp z,FCERR ; yes - array save
|
||||
cp ZPRINT ; "?" ("PRINT token") verify
|
||||
jp z,FCERR ; yes - flag "verify"
|
||||
cp '#' ; 'csave#'?
|
||||
jp z,CSAVEB ; yes - save binary
|
||||
; just cload - load basic
|
||||
jp FCERR
|
||||
|
||||
CSAVEB: inc hl ; skip #
|
||||
push bc ; save bc
|
||||
push de ; save de
|
||||
CALL GETNUM ; Get start address
|
||||
CALL DEINT ; Convert it to 16 bits
|
||||
PUSH DE ; Save start address
|
||||
CALL CHKSYN ; Make sure "," follows
|
||||
.BYTE ','
|
||||
CALL GETNUM ; Get length
|
||||
CALL DEINT ; Convert it to 16 bits
|
||||
PUSH DE ; Save length
|
||||
CALL CHKSYN ; Make sure "," follows
|
||||
.BYTE ','
|
||||
; hl points to the first character of the string expression
|
||||
call EVAL
|
||||
push hl ; save command buffer pos
|
||||
; just csave - save basic program
|
||||
CSAVE1: call EVAL ; evaluate filename expression
|
||||
push bc
|
||||
push de ; preserve bc and de
|
||||
push hl ; preserve command buffer position
|
||||
exx
|
||||
call GETSTR
|
||||
call LOADFP ; bc' = addr, e' = length
|
||||
call LOADFP ; bc' = filename, e'=length
|
||||
exx
|
||||
pop hl ; get back command buffer pos
|
||||
pop bc ; get length
|
||||
pop de ; get start address
|
||||
push hl
|
||||
; get the program length
|
||||
ld de,(BASTXT) ; program source address
|
||||
ld hl,(PROGND) ; address after prog mem
|
||||
or a ; clear carry
|
||||
sbc hl,de ; hl = prog length
|
||||
ld b,h
|
||||
ld c,l ; prog length in bc
|
||||
ld a,TAPE_TYPE_BAS_PROG
|
||||
jp CSOUT ; Write the file to tape
|
||||
CSAVEB: inc hl ; skip #
|
||||
push bc ; save BASIC registers
|
||||
push de
|
||||
call BIOS_CAS_GET_BUFFER
|
||||
; hl=buffer, bc=lenght, de=start address
|
||||
; Write header block
|
||||
ld a,1 ; block type header
|
||||
ld (hl),a
|
||||
inc hl
|
||||
call GETNUM ; get start address
|
||||
call DEINT ; convert FPREG to de
|
||||
push de ; save start address
|
||||
call CHKSYN ; require a comma
|
||||
.BYTE ','
|
||||
call GETNUM ; get length
|
||||
call DEINT ; convert FPREG to de
|
||||
push de ; save length
|
||||
call CHKSYN ; require a comma
|
||||
.BYTE ','
|
||||
call EVAL ; evaluate filename expression
|
||||
push hl ; preserve command buffer position
|
||||
exx
|
||||
call GETSTR
|
||||
call LOADFP ; bc' = filename, e' = length
|
||||
exx
|
||||
pop hl
|
||||
pop bc ; length in bytes
|
||||
pop de ; start address
|
||||
push hl
|
||||
ld a,TAPE_TYPE_BINARY
|
||||
CSOUT: call CSWRITEHEADER ; bc = block count, preserves de
|
||||
call CSWRITEBLOCKS
|
||||
ld hl,CLCLRF
|
||||
call PRS
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Build and write a header and its redundant copy
|
||||
; needs bc (file length in bytes)
|
||||
; needs bc' (filename address), e' (filename length)
|
||||
; returns bc (number of data blocks)
|
||||
; preserves de
|
||||
; uses a,h,l and the alternate register set
|
||||
; -------------------------------------------------------
|
||||
CSWRITEHEADER:
|
||||
push de
|
||||
push af ; preserve header type
|
||||
push bc ; preserve exact byte length
|
||||
call BYTESTOBLOCKS
|
||||
push bc
|
||||
ld a,c ; nr of blocks low byte
|
||||
ld (hl),a
|
||||
inc hl
|
||||
ld a,b ; nr of blocks high byte
|
||||
ld (hl),a
|
||||
inc hl
|
||||
push hl
|
||||
exx
|
||||
1$: push bc
|
||||
pop hl ; get str addr to hl
|
||||
ld a,(hl)
|
||||
inc hl
|
||||
push hl
|
||||
pop bc ; get str addr+1 back into bc
|
||||
pop hl ; get hl to hl'
|
||||
ld (hl),a ; save character to buffer
|
||||
inc hl
|
||||
push hl
|
||||
dec e ; count down str len
|
||||
ld a,e
|
||||
cp 0
|
||||
jr nz,1$ ; repeat for the whole string
|
||||
exx
|
||||
pop hl ; get back buffer addr
|
||||
ld a,0 ; NULL terminate string
|
||||
ld (hl),a
|
||||
inc hl
|
||||
; Header block complete (rest of block is accepted garbage)
|
||||
call BIOS_CAS_WRITE_BLOCK
|
||||
ld a,'.'
|
||||
call OUTC
|
||||
call BIOS_CAS_WRITE_BLOCK
|
||||
ld a,'.'
|
||||
call OUTC
|
||||
ld a,250
|
||||
call BIOS_DELAY_MS
|
||||
ld a,250
|
||||
call BIOS_DELAY_MS
|
||||
ld a,250
|
||||
call BIOS_DELAY_MS ; add a 750ms delay
|
||||
pop bc ; get back block count
|
||||
pop de ; get back start address
|
||||
pop hl ; exact byte length for the header
|
||||
pop af
|
||||
call CSMAKEHEADER
|
||||
push bc ; preserve block count over delay
|
||||
call CSWRITEPAIR
|
||||
call CSHEADERGAP
|
||||
pop bc
|
||||
pop de
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Write consecutive raw data blocks
|
||||
; needs bc (number of blocks), de (source address)
|
||||
; returns bc (zero), de (first address after written data)
|
||||
; uses a,h,l
|
||||
; -------------------------------------------------------
|
||||
CSWRITEBLOCKS:
|
||||
ld a,b
|
||||
or c
|
||||
jr z,3$ ; no data blocks for a zero length
|
||||
2$:
|
||||
; load data into buffer
|
||||
push bc
|
||||
call BIOS_CAS_GET_BUFFER
|
||||
ld bc,128 ; block size
|
||||
ld a,0 ; raw type
|
||||
ld (hl),a
|
||||
inc hl
|
||||
ex de,hl ; hl=src,de=dest
|
||||
ldir ; copy the bytes
|
||||
ex de,hl ; de back to being the src addr
|
||||
call BIOS_CAS_WRITE_BLOCK
|
||||
ld a,'.'
|
||||
call OUTC
|
||||
call BIOS_CAS_WRITE_BLOCK
|
||||
ld a,'.'
|
||||
call OUTC
|
||||
ret z
|
||||
1$: push bc
|
||||
ld a,TAPE_TYPE_RAW
|
||||
call CSWRITEDATA
|
||||
pop bc
|
||||
dec bc
|
||||
ld a,b
|
||||
or c
|
||||
jr nz,2$ ; repeat if not done
|
||||
3$:
|
||||
; All blocks are written
|
||||
jr nz,1$
|
||||
ret
|
||||
|
||||
ld hl,CLCLRF
|
||||
call PRS
|
||||
; -------------------------------------------------------
|
||||
; Build a header in the tape block buffer
|
||||
; needs bc (number of data blocks)
|
||||
; needs hl (file length in bytes)
|
||||
; needs bc' (filename address), e' (filename length)
|
||||
; needs a (type of header)
|
||||
; preserves bc,de
|
||||
; uses a,h,l and the alternate register set
|
||||
; -------------------------------------------------------
|
||||
CSMAKEHEADER:
|
||||
push de ; preserve data source address
|
||||
push hl ; preserve byte length
|
||||
push af
|
||||
call BIOS_CAS_GET_BUFFER
|
||||
pop af
|
||||
ld (hl),a ; store header type
|
||||
inc hl
|
||||
ld (hl),c ; block count is little-endian
|
||||
inc hl
|
||||
ld (hl),b
|
||||
inc hl
|
||||
pop de ; byte length
|
||||
ld (hl),e ; byte length is little-endian
|
||||
inc hl
|
||||
ld (hl),d
|
||||
inc hl ; filename destination
|
||||
|
||||
pop hl
|
||||
pop de
|
||||
push bc ; preserve block count
|
||||
push hl
|
||||
exx
|
||||
ld h,b ; hl = filename source
|
||||
ld l,c
|
||||
ld c,e ; bc = filename length
|
||||
ld b,0
|
||||
pop de ; de = filename destination
|
||||
ld a,b
|
||||
or c
|
||||
jr z,1$
|
||||
ldir
|
||||
1$: xor a
|
||||
ld (de),a ; terminate filename
|
||||
exx
|
||||
pop bc
|
||||
pop de ; restore data source address
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Copy and write one 128-byte data block
|
||||
; needs a (block type), de (source address)
|
||||
; returns de (source address advanced by 128 bytes)
|
||||
; uses a,b,c,h,l
|
||||
; -------------------------------------------------------
|
||||
CSWRITEDATA:
|
||||
call BIOS_CAS_GET_BUFFER
|
||||
ld (hl),a
|
||||
inc hl
|
||||
ld bc,TAPE_DATA_SIZE
|
||||
ex de,hl ; hl = source, de = buffer
|
||||
ldir
|
||||
ex de,hl ; de = next source address
|
||||
call CSWRITEPAIR
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Write the current tape buffer twice and show progress
|
||||
; preserves bc,de,hl
|
||||
; uses a
|
||||
; -------------------------------------------------------
|
||||
CSWRITEPAIR:
|
||||
call BIOS_CAS_WRITE_BLOCK
|
||||
ld a,'.'
|
||||
call OUTC
|
||||
call BIOS_CAS_WRITE_BLOCK
|
||||
ld a,'.'
|
||||
call OUTC
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
; Leave 750 ms between a header pair and its data
|
||||
; uses a,b,c
|
||||
; -------------------------------------------------------
|
||||
CSHEADERGAP:
|
||||
ld a,250
|
||||
call BIOS_DELAY_MS
|
||||
ld a,250
|
||||
call BIOS_DELAY_MS
|
||||
ld a,250
|
||||
call BIOS_DELAY_MS
|
||||
ret
|
||||
|
||||
; -------------------------------------------------------
|
||||
|
||||
+9
-4
@@ -10,7 +10,9 @@ from pathlib import Path
|
||||
|
||||
BLOCK_SIZE = 128
|
||||
TYPE_RAW = 0
|
||||
TYPE_HEADER = 1
|
||||
TYPE_BINARY = 1
|
||||
TYPE_BAS_PROG = 2
|
||||
TYPE_BAS_ARR = 3
|
||||
|
||||
def crc16(data: bytes) -> int:
|
||||
"""Calculate CRC-16/CCITT-FALSE."""
|
||||
@@ -107,9 +109,12 @@ class PulseWriter:
|
||||
def header(pulses: PulseWriter, path:Path) -> None:
|
||||
fname = path.name
|
||||
fsize = os.path.getsize(path)
|
||||
data = struct.pack("<H", math.ceil(fsize/BLOCK_SIZE)) + fname.encode()[:32].ljust(32, b' ')
|
||||
pulses.block(TYPE_HEADER, data)
|
||||
pulses.block(TYPE_HEADER, data)
|
||||
data = (
|
||||
struct.pack("<HH", math.ceil(fsize/BLOCK_SIZE), fsize)
|
||||
+ fname.encode()[:32].ljust(32, b' ')
|
||||
)
|
||||
pulses.block(TYPE_BINARY, data)
|
||||
pulses.block(TYPE_BINARY, data)
|
||||
|
||||
def raw(pulses: PulseWriter, data:bytes) -> None:
|
||||
pulses.block(TYPE_RAW, data)
|
||||
|
||||
Reference in New Issue
Block a user