6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 1:28 pm

All times are UTC




Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: Accessing CF card
PostPosted: Thu Aug 12, 2021 5:21 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8503
Location: Midwestern USA
cjs wrote:
BigDumbDinosaur wrote:
cjs wrote:
The original XMODEM also has the disadvantage that you must transfer 128 byte blocks...
Minor clarification: the payload size per XMODEM packet is 128 bytes.

I do not understand what you're "clarifying" here. How is this different from "XMODEM transfers 128 byte blocks"?

What I am clarifying is the XMODEM packet is 132 bytes, using a word (payload) that is familiar to contemporaries who know something about modern networking to describe the 128 bytes that represent the data. In my opinion, saying the transfer is a 128 byte block is a little ambiguous, as someone who is not familiar with XMODEM may think that 128 bytes is all that is transferred per transaction.

One thing I've learned about being a member around here is to not take for granted what someone does or does not know about things such as data transmission protocols. XMODEM is far enough in the past (44 years, to be exact) that some of our members may not know anything about it.

Quote:
Quote:
Another annoyance is XMODEM doesn't tell you how many bytes in a packet's payload are usable data and not fill bytes....

Of course not. XMODEM, being designed to carry disk sectors, has no fill bytes.

That was true as long as only CP/M was involved.

Although XMODEM's original purpose in life was indeed to transfer 128 byte CP/M disk sectors, it was seldom used that way during the BBS era (a time with which I am intimately acquainted—I ran a BBS from 1986 to 1992, and it wasn't on a CP/M box). The proliferation of BBSes running on non-CP/M machines in the 1980s—BBSes that largely used XMODEM and later on, XMODEM-CRC—meant that the data being transferred could be text, machine code, binary data or ASCII data. As all XMODEM packets have to be 132 bytes in size, and since it was likely the total data to be transferred was not an exact multiple of 128, the payload in that last packet would have had to be padded with fill bytes to meet XMODEM's requirements. That often gave rise to problems with unwanted garbage being attached to the tail end of a file.

Quote:
Quote:
Quote:
Regarding error checking, strength of checksums and the like, I recommend including a CRC-16 routine into your monitor that you can run on arbitrary sections of memory.

CRC-anything is pointless on a short-haul serial interface.

I wouldn't say it's always completely useless, but I agree with you enough that I did not suggest anybody use CRC to check packets over a serial interface. So either you're again being redundant here or you did not read what I wrote, but instead what you wanted someone who disagrees with you to write.

You're the one with the reading comprehension problem here. I did not say that you said CRC should be used to check a serial data stream. I said CRC is pointless on a short haul interface—and you quoted my exact words.

As for using CRC to do in-core checks, I consider that to be pointless as well if the data transfer is over a reliable interface. I will reiterate that I routinely transfer data between my Linux development box and my POC units at 115.2 Kbps using S-records and no other error-check protocol. I have never had a failure in some 12 years of doing so.

While the S-record single-byte checksum is not foolproof, it is sufficient in applications where data is transferred through direct connections. The S-record loader I have written for my POC units, which is based on work I did 30 years ago in a project for Fiscal Information terminal servers, aborts if any one record fails to checksum, something which I have tested to a considerable extent by intentionally corrupting S-record files and then sending them to a POC unit to see what would happen.

floobydust wrote:
As for CRC being useless in what is basically a direct-attach configuration, I would disagree from experience. I actually had a slightly flaky UART some time ago. In some cases it would transfer data without issue... every once in a while, the transfer would fail. A CRC error actually occurred based on the highly intermittent problem... who knew.

An S-record or Intel hex transfer would have almost certainly caught the same problem without incurring the expense of computing the CRC on each packet received. The only situation in which a CRC would have an advantage in analyzing a serial data stream would be in the extremely rare case in which two bytes are interchanged but are otherwise unaltered.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: Accessing CF card
PostPosted: Thu Aug 12, 2021 9:31 pm 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
BigDumbDinosaur wrote:
What I am clarifying is the XMODEM packet is 132 bytes...

Which is both unimportant for this discussion and confusingly brings in a second, irrelevant number. (That's right up there with "clarifying" that sectors on a 128-bytes/sector diskette actually store 144 bytes or whatever.) The key point is that when you use XMODEM to send your data, you must give it a multiple of 128 bytes to send; 132 bytes is not useful information when discussing this.

Quote:
Quote:
Of course not. XMODEM, being designed to carry disk sectors, has no fill bytes.
That was true as long as only CP/M was involved.

No, it was true from the start whether or not CP/M was involved and is still true to this day. When you pass data to an XMODEM routine for it to send, you pass it a multiple of 128 bytes and it sends all that; there is nothing to indicate whether or not there is "fill" and how the fill should be done and certainly nothing like that is communicated to the other end. That's all determined by the application using XMODEM, and is not part of XMODEM itself. (Look up protocol layering. If your XMODEM routines do accept lengths not a multiple of 128 bytes, you've pushed part of your application down into your network routines. There's still no way to communicate fill to the other end.)

As you say yourself:
Quote:
...since it was likely the total data to be transferred was not an exact multiple of 128, the payload in that last packet would have had to be padded with fill bytes to meet XMODEM's requirements. That often gave rise to problems with unwanted garbage being attached to the tail end of a file.

Exactly. The XMODEM protocol did not support any idea of "fill bytes" and the applications had to deal with it.

Quote:
Although XMODEM's original purpose in life was indeed to transfer 128 byte CP/M disk sectors, it was seldom used that way during the BBS era (a time with which I am intimately acquainted—I ran a BBS from 1986 to 1992, and it wasn't on a CP/M box).

What, because you started late you get to define my (and others') earlier BBS experience out of existence? Sorry, no. In my BBS era there were plenty of RCP/M machines, in fact they were the majority in the first few years of it, even for a while after the IBM PC came out. Not that this has anything to do with whether the protocol supports padding or not.

Quote:
You're the one with the reading comprehension problem here. I did not say that you said CRC should be used to check a serial data stream. I said CRC is pointless on a short haul interface—and you quoted my exact words.

Yes, but the question is why you said that again. When you quoted topic Y and then immediately repeated your point about topic X without addressing Y, that gave the strong impression that you didn't understand Y. If did understand that what I was talking about was different from a checksum or CRC in a serial data protocol, why did you quote that and then talk only about CRC in a serial data protocol?

Quote:
As for using CRC to do in-core checks, I consider that to be pointless as well if the data transfer is over a reliable interface.

So if the transfer was over a reliable interface then hardware will never fail to store the data correctly, programs will never accidentally modify the memory, and not even external events will modify that data? And even if the transfer was some time ago, you'll never later want to do a quick check to see what version of the code you put in EEPROM? Rubbish. (Or if you agree that the ability to generate a CRC of data in memory is useful, just say you agree with me and don't come out as if you disagree with something I've said.)

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
 Post subject: Re: Accessing CF card
PostPosted: Sat Aug 21, 2021 2:48 am 
Offline

Joined: Fri Dec 21, 2018 1:05 am
Posts: 1117
Location: Albuquerque NM USA
My simple-minded solution for saving and restoring EhBASIC program is having a "List" command in the monitor that displays user-specified range of memory as Intel Hex records on the console. The PC captures the Intel Hex records to a file on PC. Later it can be loaded back into 6502 memory. At 115200 you can dump the entire 64K memory content quite quickly.
Bill


Top
 Profile  
Reply with quote  
 Post subject: Re: Accessing CF card
PostPosted: Wed Dec 07, 2022 5:53 am 
Offline

Joined: Fri Feb 12, 2021 10:17 pm
Posts: 34
I used a Pico "RP2040". The pico has 2 spi's, a master one hosting the sd card with FATFS and a slave one to the 6502. In ROM I thus only needed space to make calls across the spi for disk commands and parameters, such as cd "some_directory", ls, rm "somefile", mv "somefile", load "somefile", save "somefile" and so on. I have these commands working for EHBASIC, Tali Forth, ED, and the A1 Assembler.

One the PICO side I did use C and spent some time creating the routines to respond to the calls from the 6502.

My EHBASIC's load and save commands operate on the ASCII source, specifically LOAD "MYWAVE.BAS" will instruct the pico to read and send the MYWAVE.BAS file (quickly but as if it was typed in) and save "MYBASPRG.BAS" followed by a list command will send the output of list to a new file on the SD card named MYBASPRG.BAS.

Other than writing the code for the load and save commands on the EHBASIC side, I also used one memory location as an indicator and added a couple lines to the EHBASIC assembly itself. There may be a better way to do it, but I needed an indicator that the list command had finished, and to accomplish this I update a memory location when READY is printed, such as when the list command finishes.

The SD card routines were written based on a 256 byte buffer, and they are quick.

The load and save ASCII routines were written based on the post by leeeeee at viewtopic.php?f=5&t=5760&view=next
Quote:
If you want to save the program as binary you should save (Smeml) to (Svarl)-1.

If you want to save the program as ASCII you should redirect the character output vector to write to your filesystem and then call LIST. Doing this can also allow you to specify line numbers or ranges as with LIST. The output vector should be restored and the file closed when LIST returns or an error is encountered.

To load a binary program start loading it at (Smeml) and set (Svarl) to the last address + 1 then call LAB_1477 to clear the variables and reset the execution pointer. An easy way to do the first part is by copying (Smeml) to (Svarl) and using (Svarl) as a post incremented save pointer. If there is a chance that the program has been relocated it's probably a good idea to rebuild the line pointer chain.

To load an ASCII program redirect the character input vector to read from your filesystem and return to the main interpreter loop. The input vector should be restored and the file closed when the file end is reached or an error is encountered.

I prefer ASCII format as it's far more portable, easier to manipulate and can include direct commands and comment lines that aren't saved to memory.

Lee.


Below is my minmon.asm. It definently needs to be "cleaned up", but it works and posting for now as is in hopes it will help someone.

There may be a little context loss without also posting the c code on the pico side. For now I can only think to mention, on the pico side I use a buffer initialized to all 3's when sending a files contents. In doing so, on the 6502 side I know when I read a 3 while reading what should be ascii text, I can interpret it to mean end of text/end of file...

Code:
; minimal monitor for EhBASIC and 6502 simulator V1.05
; tabs converted to space, tabwidth=6

; To run EhBASIC on the simulator load and assemble [F7] this file, start the simulator
; running [F6] then start the code with the RESET [CTRL][SHIFT]R. Just selecting RUN
; will do nothing, you'll still have to do a reset to run the code.

      .include "basic.asm"

; ######################################################################
; TO IDENTIFY AND IGNORE THE EXCESS LINEFEED CHARACTERS
; ######################################################################
LF  = $0A        ; Line feed character
CR  = $0D
; ######################################################################
; put the IRQ and MNI code in RAM so that it can be changed

IRQ_vec     = VEC_SV+2        ; IRQ code vector
NMI_vec     = IRQ_vec+$0A     ; NMI code vector

; ######################################################################
; Change of addresses to match my build
; ######################################################################
ACIA_data    =  $0210
ACIA_status  =  $0211
ACIA_command =  $0212
ACIA_control =  $0213

IO_AREA     =   $0210           ; set I/O area for this monitor

; now the code. all this does is set up the vectors and interrupt code
; and wait for the user to select [C]old or [W]arm start. nothing else
; fits in less than 128 bytes

; SOME ADDYS
PORTD   =     $0200
PORTC   =     $0201
DDRD    =     $0202
DDRC    =     $0203
MSGL    =     $91
MSGH    =     $92
FNMEL   =     $93
FNMEH   =     $94
MSGL2   =     $95
MSGH2   =     $96
STRLN   =     $99
IN      =     $3DAA
PRBYTE  =     $FFDC   
PRHEX   =     $FFE5
KEY_LF   =     $0a
KEY_CR   =     $0d

;setup the VIA (LCD DISPALY)
PORTB  =     $0200
PORTA  =     $0201
DDRB   =     $0202
DDRA   =     $0203
T1CL   =     $0204
T1CH   =     $0205
SR     =     $020a
ACR    =     $020b
PCR    =     $020c
IFR    =     $020d
IER    =     $020e
; SPI
SCK  = %00000001 ;Looking at chip 10000000
MOSI = %00000010 ;Looking at chip 01000000
CS   = %00000100 ;Looking at chip 00100000
MISO = %01000000 ;Looking at chip 00000010
; The next two address locations are arbitrary, anywhere that is free
spiin   =    $F3
spiout  =    $F4
; The next two address locations are arbitrary, anywhere that is free
LB_ENT  =    $3BF4
HB_ENT  =    $3BF5
; -------------------------------------------------------------------------------------------------------
Get_Char    = $db77   ; Check to see if there is a character, break on carry clear
kernel_putc = $db94    ; kernel_putc = $fc8c ; Send character to screen 

; IN BASIC.ASM CHANGE THIS TO 400 AS SHOWN. ORIGIONALLY IT WAS 200 BUT I HAVE DEVICES THERE.
; I use $300-$3FF for an input buffer.
; ALSO SET MEMORY APPROPRIATELY
;Ram_base          = $0400     ; start of user RAM (set as needed, should be page aligned)
;Ram_top           = $8000     ; end of user RAM+1 (set as needed, should be page aligned)


;      *=    $FF80             ; pretend this is in a 1/8K ROM
.segment "ELOAD"
    .WORD $1000               ; Run EHBASIC from RAM with a start address of $1000
; ######################################################################
; Change segment to match my build
; ######################################################################
.segment "EBASIC"
;.segment "OS"
; reset vector points here
.export EBASIC_RES
EBASIC_RES
      CLD                     ; clear decimal mode
      LDX   #$FF              ; empty stack
      TXS                     ; set the stack

; set up vectors and interrupt code, copy them to page 2

      LDY   #END_CODE-LAB_vec ; set index/count
LAB_stlp
      LDA   LAB_vec-1,Y       ; get byte from interrupt code
      STA   VEC_IN-1,Y        ; save to RAM
      DEY                     ; decrement index/count
      BNE   LAB_stlp          ; loop if more to do

; now do the signon message, Y = $00 here

LAB_signon
      LDA   LAB_mess,Y        ; get byte from sign on message
      BEQ   LAB_nokey         ; exit loop if done

      JSR   V_OUTP            ; output character
      INY                     ; increment index
      BNE   LAB_signon        ; loop, branch always

LAB_nokey
      JSR   V_INPT            ; call scan input device
      BCC   LAB_nokey         ; loop if no key

      AND   #$DF              ; mask xx0x xxxx, ensure upper case
      CMP   #'W'              ; compare with [W]arm start
      BEQ   LAB_dowarm        ; branch if [W]arm start

      CMP   #'C'              ; compare with [C]old start
      BNE   EBASIC_RES        ; loop if not [C]old start

      JMP   LAB_COLD          ; do EhBASIC cold start

LAB_dowarm
      JMP   LAB_WARM          ; do EhBASIC warm start

ACIAout
    CMP     #LF                     ; Ignore line feed character
    BEQ     Ignore
    jsr kernel_putc
Ignore
    rts

ACIAin
    clc
    JSR Get_Char
    BCC ACIAin_end
    AND #$7F         ;*Change to "standard ASCII"
ACIAin_end
   RTS


LAB_nobyw
      CLC                     ; flag no byte received
; ----------------------------------------------------------------------------------------------------------
;no_load                       ; empty load vector for EhBASIC
; http://forum.6502.org/viewtopic.php?f=5&t=1534&hilit=LAB_EVEX
; To load an ASCII program redirect the character input vector (ACIAin FROM LAB_VEC) to read from your
; filesystem and return to the main interpreter loop. The input vector should be restored and the file closed
; when the file end is reached or an error is encountered.
; http://forum.6502.org/viewtopic.php?f=5&t=5760&view=next
;Call the evaluate following expression routine, LAB_EVEZ, and look for a string by testing if the data type flag, Dtypef, is negative. If it is the string descriptor is on the descriptor stack so don't forget to pop it off there by calling LAB_22B6 once you're done with it.
;
;Lee.
; I think Lee meant LAB_EVEX
; ============================================================================================================
; START SEND COMMAND AND FILE NAME TO PICO. REMAP THE READ VECTOR THEN JUMP BACK INTO BASIC.
; ============================================================================================================
LOAD:
; ============================================================================================================
  LDA   #$FF      ; $FF=load (Probably not needed here)
  ;STA $70
;FILESAVE:
;  ; Push registers A, X and Y to the stack. Restore on exit.
  PHA
  PHX
  PHY
  JSR   LAB_EVEX   ; evaluate string
  JSR   LAB_EVST   ; test it is a string
  STA   STRLN      ; save string length
  STX   FNMEL      ; save string pointer low byte
  STY   FNMEH      ; save string pointer high byte

; Stage the "ESAVE FILENAME" command in the IN BUFFER
; ------------------------
; ESAVE
; ------------------------
  LDA #<ELOAD
  STA MSGL
  LDA #>ELOAD
  STA MSGH

  LDY #0
  LDX #0
PRINTLOAD
  LDA (MSGL),Y
  BEQ END_PRINTLOAD
  STA IN,X
  ;JSR $FFEF
  INX
  INY
  CPY MSGH
  BNE PRINTLOAD
END_PRINTLOAD
; ------------------------
; FILENAME
; ------------------------ 
  LDY #0
PRINTLOADNAME
  LDA (FNMEL),Y
  BEQ DONEPRINTLOADNAME
  STA IN,X
  ;JSR $FFEF
  ;JSR PRBYTE
  INX
  INY
  ;CMP FNMEH
  CPY STRLN
  BNE PRINTLOADNAME
DONEPRINTLOADNAME
  ; END WITH A ZERO
  LDA #0
  STA IN,X 
 
;  ; Send it.
  LDX #$0
;  JSR SND
  JSR SNDESAVECMD ; RENAME THIS SUBROUTINE
 ; Complete command, i.e. 256 bytes
  JSR spi_spi_complete_cmd
 
; Restore origional memory addresses   
    PLY
    PLX
    PLA     

    STX _fd

RECEIVE:
    LDX #0
    LDY #0


    lda #<fread_wrapper
    sta VEC_IN
    lda #>fread_wrapper
    sta VEC_IN+1

  JSR delay
  JSR delay
  jsr delay
  jsr delay

    ;LDX #0 ; WE NEED X TO BE ZERO IN ORDER TO COUNT CHARS FROM UPCOMING LIST COMMAND
    STZ $F8
   
    JMP LAB_1319 ; reset and return
    RTS ; << Should not be reached

; ============================================================================================================
; END SEND COMMAND AND FILE NAME TO PICO. REMAP THE READ VECTOR THEN JUMP BACK INTO BASIC.
; ============================================================================================================
fread_wrapper:

  phx
  phy
  ldx _fd
     
; ----------------------------------------------------------------------
  stz PORTA          ; Set chip select low BEGIN PACKET

  PHY
  LDA #'X'
  jsr spi_transceive ; Send
  INC $F8
  PLY

  PHA
  lda #CS
  sta PORTA          ; END PACKET
  PLA
; ----------------------------------------------------------------------
  ;CMP #'~'
  cmp #3      ; On the pico side, I initialize the buffer to all 3's, i.e. 3 means end of text. I then populate the buffer, so the 3's at the end indeed indicate the end of text.
  BEQ PEXIT
; ----------------------------------------------------------------------
  cmp #$0A ; replace with "basic end of line"
  bne KEY_LF_DONE
  lda #$0D
; ----------------------------------------------------------------------
KEY_LF_DONE
  PHA
  JSR delay
  JSR delay 
  PLA
  AND #$7F        ;*Change to "standard ASCII" AS WOZMON DOES *KEY ONE*
  sec
  ply
  plx
  cmp #0
  RTS 

PEXIT:
  ; Complete command, i.e. 256 bytes
  PHA
  LDA $F8
  TAX
  PLA
  CPX #0 ; HAS NOW CYCLED SO GET OUT
  BEQ GETOUT
  ply
  plx
  RTS
 
GETOUT 
  ;JSR spi_spi_complete_cmd
   
  jsr init_iovectors
       
  LDA   #<LAB_RMSG   ; "READY"
  LDY   #>LAB_RMSG
  JSR   LAB_18C3
 
  JMP   LAB_1319   ; relink program and clear variables

       
init_iovectors:
  lda #<ACIAin
  sta VEC_IN
  Lda #>ACIAin
  sta VEC_IN+1
  rts

; ----------------------------------------------------------------------------------------------------------
;no_save                       ; empty save vector for EhBASIC
;      RTS
; If you want to save the program as ASCII you should redirect the character output vector to write to your
; filesystem and then call LIST. Doing this can also allow you to specify line numbers or ranges as with LIST.
;The output vector should be restored and the file closed when LIST returns or an error is encountered.
; ============================================================================================================
SAVE:
; ============================================================================================================
  LDA   #$FF      ; $FF=load
  STA $70
; Push registers A, X and Y to the stack. Restore on exit.
  PHA
  PHX
  PHY
  JSR   LAB_EVEX   ; evaluate string
  JSR   LAB_EVST   ; test it is a string
  STA   STRLN      ; save string length
  STX   FNMEL      ; save string pointer low byte
  STY   FNMEH      ; save string pointer high byte
; ------------------------
; ESAVE
; ------------------------
  LDA #<ESAVE
  STA MSGL
  LDA #>ESAVE
  STA MSGH

  LDY #0
  LDX #0
PRINTESAVE
  LDA (MSGL),Y
  BEQ END_PRINTESAVE
  STA IN,X
  ;JSR $FFEF
  INX
  INY
  CPY MSGH
  BNE PRINTESAVE
END_PRINTESAVE
; ------------------------
; FILENAME
; ------------------------ 
  LDY #0
PRINTSAVNAME
  LDA (FNMEL),Y
  BEQ DONEPRINTSAVNAME
  STA IN,X
  ;JSR $FFEF
  ;JSR PRBYTE
  INX
  INY
  ;CMP FNMEH
  CPY STRLN
  BNE PRINTSAVNAME
DONEPRINTSAVNAME
  ; END WITH A ZERO
  LDA #0
  STA IN,X 
 
; Send it.
  LDX #$0
  JSR SNDESAVECMD
 ; Complete command, i.e. 256 bytes
  JSR spi_spi_complete_cmd
 
    PLY
    PLX
    PLA     

    STX _fd
   
    ;LDX #0 ; WE NEED X TO BE ZERO IN ORDER TO COUNT CHARS FROM UPCOMING LIST COMMAND
    STZ $50

; Here is where we remap output, then return to basic and issue the list command.
  lda #<fwrite_wrapper
  sta VEC_OUT
  lda #>fwrite_wrapper
  sta VEC_OUT+1 
  JMP LAB_1319 ; reset and return
  RTS ; << Should not be reached 

fwrite_wrapper:
  ;ldx #0 NEED TO DO THIS, AND I THINK BUILD 256 BYTES OR... PERHAPS I NEED TO USE A SPECIAL 1 BYTE BUFFER FOR THIS PART?
  CMP     #LF
  ;BNE GO
  BEQ SKIP  ; SKIP THE LF TO AVOID DOUBLE SPACED LINES, WE WILL STILL GET THE CARRIAGE RETURNS
  ;LDA     #CR
GO
  PHA
fwrite_wrapper_out_retry
  LDA ACIA_status
  AND #$10
  BEQ fwrite_wrapper_out_retry
  PLA
  STA ACIA_data
SAVPPRINTLIST   
  stz PORTA          ; Set chip select low BEGIN PACKET
  PHY
  jsr spi_transceive ; Send
  INC $50
  PLY
  lda #CS
  sta PORTA          ; END PACKET
  ;PHA No need to push A, I don't care what came back in A from spi
  LDA $70
  BEQ SAVPDONE
  ;PLA
SKIP
  RTS

SAVPDONE
  ; Complete command, i.e. 256 bytes
  PHA
  LDA $50
  TAX
  PLA
  JSR spi_spi_complete_cmd
  jsr SAV2init_iovectors
  jmp LAB_1319 ; cleanup and Return to BASIC
  rts
SAV2init_iovectors:
  lda #<ACIAout
  sta VEC_OUT
  lda #>ACIAout
  sta VEC_OUT+1
  rts


LAB_vec
      .word ACIAin            ; input vector byte in from simulated ACIA
      .word ACIAout           ; output vecto byte out to simulated ACIA
      .word LOAD              ; load vector
      .word SAVE              ; save vector
      ;.word no_load           ; null load vector for EhBASIC
      ;.word no_save           ; null save vector for EhBASIC
     
; EhBASIC IRQ support

IRQ_CODE
      PHA                     ; save A
      LDA   IrqBase           ; get the IRQ flag byte
      LSR                     ; shift the set b7 to b6, and on down ...
      ORA   IrqBase           ; OR the original back in
      STA   IrqBase           ; save the new IRQ flag byte
      PLA                     ; restore A
      RTI

; EhBASIC NMI support

NMI_CODE
      PHA                     ; save A
      LDA   NmiBase           ; get the NMI flag byte
      LSR                     ; shift the set b7 to b6, and on down ...
      ORA   NmiBase           ; OR the original back in
      STA   NmiBase           ; save the new NMI flag byte
      PLA                     ; restore A
      RTI

END_CODE

LAB_mess
      .byte $0D,$0A,"6502 EhBASIC [C]old/[W]arm ?",$00
                              ; sign on string
                             
; ###########################################################
; UTILITIES
; ###########################################################
delay
  phx
  phy
  ldx #2
  ldy #1
delloop
  dey
  bne delloop
  dex
  bne delloop
  ply
  plx
  rts
; ######################################################################
; INITSPI
; ######################################################################
INITSPI:
  ;Initialize SPI
  lda #CS
  sta PORTA
  lda #%00000111 ; cs/mosi/sck (MISO should be low)
  sta DDRA
  RTS
; ######################################################################
; SNDCMD
; ######################################################################
SNDESAVECMD:
  LDY #$0
PRNT       
  LDA IN,Y
  BEQ SNDESAVECMDDONE
  stz PORTA          ; Set chip select low BEGIN PACKET
  PHY
  jsr spi_transceive ; Send
  PLY
  lda #CS
  sta PORTA          ; END PACKET
  INX
  INY
  BNE PRNT
SNDESAVECMDDONE
  RTS
; ######################################################################
; SND
; ######################################################################
SND:
  LDY #$0
PRINT       
  LDA (MSGL),Y
  BEQ DONE
  stz PORTA          ; Set chip select low BEGIN PACKET
  PHY
  jsr spi_transceive ; Send
  PLY
  lda #CS
  sta PORTA          ; END PACKET
  INX
  INY
  BNE PRINT
DONE
  RTS

; ######################################################################
; SPI COMPLETE COMMAND
; ######################################################################
spi_spi_complete_cmd:
  stz PORTA          ; Set chip select low BEGIN PACKET
  lda #$0
  jsr spi_transceive ; Send
  lda #CS
  sta PORTA          ; END PACKET
  inx
  cpx #$0
  bne spi_spi_complete_cmd
  RTS

; ######################################################################
; SPI TRANSCEIVE
; ######################################################################
spi_transceive: 
  stz spiin      ; Clear the input buffer
  sta spiout     ; store the output data
  ldy #8         ; Initialize the bit counter
  lda #MOSI      ; Set the A register to the MOSI bit mask

spi_loop:
  asl spiout     ; Move mSB of output into carry flag; next bit to send
  bcs spi_1      ; Test the carry flag
  trb PORTA      ; MSB was zero, set MOSI LOW
  jmp spi_2
spi_1:
 tsb PORTA       ; MSB was 1, set MOSI HIGH
spi_2:           
  inc PORTA      ; Set SCK high
  bit PORTA      ; Put MOSI into overflow flag
  clc            ; Clear the carry flag
  bvc spi_3      ; Test overflow flag
  sec       
spi_3:
  rol spiin      ; Rotate the carry flag into the receive buffer
  dec PORTA      ; set SCK low
  dey            ; Decrement the bit counter
  bne spi_loop   ; Continue sending/receiving bits
  lda spiin      ; Done; put the received data into A
  clc
  rts

SHWMSG      LDY #$0
PRINT2      LDA IN,Y
            BEQ DONE2
            JSR $FFEF
            INY
            BNE PRINT2
DONE2       RTS
 
; PICO PARALLEL COMMANDS
ESAVE:   .asciiz "ESAVE "
ELOAD:   .asciiz "ELOAD "
ELIST:   .asciiz "LIST"

_fd:        .res 1


For the save command indicator, i.e. to indicate the list command is done, at the beginning of a save I set location $70 to $FF, then I watch in the code above for location $70 to become $00. This occurs when READY is printed at the end of a list, by the addition of the following line in basic.asm
Code:
LAB_1274
                              ; clear ON IRQ/NMI bytes
      LDA   #$00              ; clear A
      STA   $70               ;  INDIATE PICO SAVE COMMAND DONE
      STA   IrqBase           ; clear enabled byte
      STA   NmiBase           ; clear enabled byte

_________________
Shaking out the dirty bits!

https://github.com/DonaldMoran


Top
 Profile  
Reply with quote  
 Post subject: Re: Accessing CF card
PostPosted: Wed Dec 07, 2022 7:48 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
(It'd be great to see also the code you wrote for the Pico - I think it's a great adjunct to a retrocomputing system, and it's both affordable and available.)


Top
 Profile  
Reply with quote  
 Post subject: Re: Accessing CF card
PostPosted: Thu Dec 08, 2022 3:02 am 
Offline

Joined: Fri Feb 12, 2021 10:17 pm
Posts: 34
BigEd wrote:
(It'd be great to see also the code you wrote for the Pico - I think it's a great adjunct to a retrocomputing system, and it's both affordable and available.)


Thanks BigEd and sure, attached is the C code.

This C code also needs to be cleaned up, it does work well but could surely be improved. I also included my CMakelists.txt file for reference.

You will note I am using both cores of the pico, one to serve as command line serial access, and the other to handle file system request. There is code for the ordinary things you would expect, mkdir, rm, ls and so on, and you will also notice a little for TaliForth specifically. With Forth I think many folks use one file and break it into 1024 byte chunks or flash memory to handle screens, whereas I took a different approach, I instead create separate 1024 byte files, one file per screen which then makes it easy for me to work with the files outside the system should I choose, etc.

You would want to stand up the pico sdk, and grab fatfs - I basically followed this digikey article to get the fatfs library - https://www.digikey.com/en/maker/projects/raspberry-pi-pico-rp2040-sd-card-example-with-micropython-and-cc/e472c7f578734bfd96d437e68e670050

I did this a couple different ways on a couple different builds. This version is my latest iteration and using spi, but on a previous build I used a pico connected parallel to second 6522 (8 pins for data and 2 for handshaking) via. PIO. I do still like that approach as well. Though this current SPI version is plenty quick, and though the parallel/PIO version was written in python, because I used PIO and connected parallel, it is actually a little quicker. Further, being in python makes it a little more friendly to those not familiar with C. On the other hand, this SPI approach is a little simpler to follow for those not familiar with PIO.

The reason I went with SPI this time was not only to try something new, but in the long run, I have a Github I want to update with the solutions, and in doing so, I want one section dedicated to, what can we do with as little hardware/cost as necessary, while another section may be geared more for performance/options, etc.

BigEd I appreciate your interest and comment, hope this comes as use to you and others.


Attachments:
File comment: The CMakeLists.txt to go along with the c code for use with the pico sdk.
CMakeLists.txt [698 Bytes]
Downloaded 79 times
File comment: Duel core, one core for handling a serial connection (command line) and another for handling disk access request / commands, etc. via spi
test_uart.c [35.41 KiB]
Downloaded 73 times

_________________
Shaking out the dirty bits!

https://github.com/DonaldMoran
Top
 Profile  
Reply with quote  
 Post subject: Re: Accessing CF card
PostPosted: Thu Dec 08, 2022 9:33 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
Thanks for sharing! The idea of publishing ideas for lost cost and simple solution is great.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 22 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: