Delete everything

This commit is contained in:
Byron Lathi
2024-03-02 20:10:50 -08:00
parent 273484b994
commit 0a0394ae33
293 changed files with 1 additions and 94765 deletions

View File

@@ -1,40 +0,0 @@
CC=../cc65/bin/cl65
LD=../cc65/bin/cl65
CFLAGS=-T -t none -I. --cpu "65C02"
LDFLAGS=-C link.ld -m $(NAME).map
NAME=kernel
O65 = $(NAME).o65
FSDIR=$(REPO_TOP)/sw/fsdir
LISTS=lists
SRCS=$(wildcard *.s) $(wildcard *.c)
SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
# Make sure the kernel linked to correct address, no relocation!
all: $(O65) $(FSDIR)
cp $(O65) $(FSDIR)
$(FSDIR):
mkdir $(FSDIR)
$(O65): $(OBJS)
$(LD) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
%.o: %.s $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
$(LISTS):
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
.PHONY: clean
clean:
rm -rf $(OBJS) $(O65) $(LISTS) $(NAME).map

View File

@@ -1,53 +0,0 @@
; ---------------------------------------------------------------------------
; crt0.s
; ---------------------------------------------------------------------------
;
; Startup code for cc65 (Single Board Computer version)
.export _init, _exit
.import _main, _cputc
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import __STACKSTART__, __STACKSIZE__ ; Linker generated
.import copydata, zerobss, initlib, donelib
.include "zeropage.inc"
; ---------------------------------------------------------------------------
; Place the startup code in a special segment
.segment "STARTUP"
; ---------------------------------------------------------------------------
; A little light 6502 housekeeping
_init: LDX #$FF ; Initialize stack pointer to $01FF
TXS
CLD ; Clear decimal mode
; ---------------------------------------------------------------------------
; Set cc65 argument stack pointer
LDA #<(__STACKSTART__ + __STACKSIZE__)
STA sp
LDA #>(__STACKSTART__ + __STACKSIZE__)
STA sp+1
; ---------------------------------------------------------------------------
; Initialize memory storage
JSR zerobss ; Clear BSS segment (no longer fails)
; JSR copydata ; Initialize DATA segment (this also fails. but prints something)
JSR initlib ; Run constructors (This one works)
; ---------------------------------------------------------------------------
; Call main()
cli
JSR _main
; ---------------------------------------------------------------------------
; Back from main (this is also the _exit entry): force a software break
_exit: JSR donelib ; Run destructors
BRK

View File

@@ -1,10 +0,0 @@
#ifndef _BOARD_IO_H
#define _BOARD_IO_H
#include <stdint.h>
uint8_t sw_read();
void led_set(uint8_t val);
#endif

View File

@@ -1,24 +0,0 @@
.include "io.inc65"
.importzp sp, sreg
.export _sw_read
.export _led_set
.autoimport on
.code
; @out A: The Value of the switches
; Reads the current values of the switches.
_sw_read:
lda SW
ldx #$0
rts
; @in A: val
; @out A: 0 for success, 1 for failure
; Sets the LEDs
_led_set:
sta LED
rts

View File

@@ -1,60 +0,0 @@
.importzp sp, sreg
.import _uart_txb_block
.import _lastchar
.export _cputc
.export gotoxy
.export _clrscr
;.export _cgetc
.autoimport on
.code
; void __fastcall__ cputc (char c);
_cputc:
jsr _uart_txb_block
cmp #$0a
bne @1
lda #$0d
jsr _uart_txb_block
@1: rts
; void __fastcall__ gotoxy (unsigned char x, unsigned char y);
gotoxy:
phx
phy
tay ; Move y position to y
lda (sp)
tax ; Move x position to x
lda #$1b
jsr _uart_txb_block
lda #'['
jsr _uart_txb_block
tya
jsr _uart_txb_block
lda #';'
jsr _uart_txb_block
txa
jsr _uart_txb_block
lda #'H'
jsr _uart_txb_block
ply
plx
rts
_clrscr:
phx
lda #$1b
jsr _uart_txb_block
lda #'c'
jsr _uart_txb_block
pla
rts
;_cgetc:
;@2: lda _lastchar
; beq @2
; stz _lastchar
; rts

View File

@@ -1,32 +0,0 @@
#ifndef _INTERRUPT_CONTROLLER_H
#define _INTERRUPT_CONTROLLER_H
#include <stdint.h>
// These need to be copied in interrupt_controller.s
#define IRQ_CMD_ADDR 0xeffc
#define IRQ_DAT_ADDR 0xeffd
#define IRQ_CMD_MASK 0xe0
#define IRQ_REG_MASK 0x1f
#define IRQ_CMD_READIRQ 0x00
#define IRQ_CMD_ENABLE 0x20
#define IRQ_CMD_TYPE 0x40
#define IRQ_CMD_EOI 0xff
#define IRQ_EDGE 0
#define IRQ_LEVEL 1
void init_interrupt_controller();
void enable_irq(uint8_t type, uint8_t irqnum);
void disable_irq(uint8_t irqnum);
// This should accept irqnum later.
void send_eoi();
#endif

View File

@@ -1,148 +0,0 @@
.MACPACK generic
.autoimport
.importzp tmp1, tmp2
.export _init_interrupt_controller
.export _enable_irq
.export _disable_irq
.export _send_eoi
.import irq_int, nmi_int
IRQ_CMD_ADDR = $effc
IRQ_DAT_ADDR = $effd
IRQ_CMD_MASK = $e0
IRQ_REG_MASK = $1f
IRQ_CMD_READIRQ = $00
IRQ_CMD_ENABLE = $20
IRQ_CMD_TYPE = $40
IRQ_CMD_EOI = $ff
IRQ_VECTOR = $220
NMI_VECTOR = $222
.code
; void init_irq();
; mask all IRQs, set all type to edge.
.proc _init_interrupt_controller
lda #<irq_int
sta IRQ_VECTOR
lda #>irq_int
sta IRQ_VECTOR+1
lda #<nmi_int
sta NMI_VECTOR
lda #>nmi_int
sta NMI_VECTOR+1
ldx #$20 ; enable
ldy #00
jsr cmd_all
ldx #$40 ; edge type
ldy #$00
jsr cmd_all
rts
cmd_all: ; Send the same value to all 32 bytes
txa
add #$10
sta tmp1
loop:
txa
sta IRQ_CMD_ADDR
tya
sta IRQ_DAT_ADDR
inx
cpx tmp1
blt loop
rts
.endproc
; void enable_irq(uint8_t type, uint8_t irqnum);
; in A:
.proc _enable_irq
; Decide which byte we need to modify by dividing by 8 (>> 3)
pha
lsr
lsr
lsr ; A is now bytesel
sta tmp2 ; tmp2 is now bytesel
add #IRQ_CMD_ENABLE
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
sta tmp1
pla
and #$07 ; A is now 0-7
tax
inx ; X is now 1-8
lda #$01
L1: dex
beq L2
asl
bra L1
L2: pha ; Push bit mask to stack
ora tmp1 ; A is now 1 << (0-7) | enable
sta IRQ_DAT_ADDR
lda tmp2
add #IRQ_CMD_TYPE
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
sta tmp1
jsr popa ; A is now type
beq bit0
bit1: ; set `bit` to 1
pla
ora tmp1
bra L3
bit0: ; set `bit` to 0
pla
eor #$ff
and tmp1
L3: sta IRQ_DAT_ADDR
rts
.endproc
; TODO this is mostly the same as enable, why copy?
.proc _disable_irq
; Decide which byte we need to modify by dividing by 32 (>> 5)
pha
lsr
lsr
lsr ; A is now bytesel
add #IRQ_CMD_ENABLE
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
sta tmp1
pla
and $07 ; A is now 0-7
tax
inx ; X is now 1-8
lda #$01
L1: dex
beq L2
asl
bra L1
L2: eor #$ff ; Invert to set enable to 0
and tmp1 ; a is now ~(1 << (0-7)) & enable
sta IRQ_DAT_ADDR
rts
.endproc
; This should accept irqnum later.
; void send_eoi();
.proc _send_eoi
lda #IRQ_CMD_EOI
sta IRQ_CMD_ADDR
lda #$1
sta IRQ_DAT_ADDR
rts
.endproc

View File

@@ -1,30 +0,0 @@
UART = $efe6
UART_TXB = UART
UART_RXB = UART
UART_STATUS = UART + 1
LED = $efff
SW = LED
SPI_BAUD = $efd8
SPI_INPUT = $efd9
SPI_OUTPUT = $efda
SPI_CTRL = $efdb
SPI_STATUS = SPI_CTRL
MULTIPLIER_BASE = $eff0
MULTIPLIER_AL = MULTIPLIER_BASE + 0
MULTIPLIER_AH = MULTIPLIER_BASE + 1
MULTIPLIER_BL = MULTIPLIER_BASE + 2
MULTIPLIER_BH = MULTIPLIER_BASE + 3
MULTIPLIER_OLL = MULTIPLIER_BASE + 4
MULTIPLIER_OLH = MULTIPLIER_BASE + 5
MULTIPLIER_OHL = MULTIPLIER_BASE + 6
MULTIPLIER_OHH = MULTIPLIER_BASE + 7
GOLDEN_OUTPUT_0 = $03
GOLDEN_OUTPUT_1 = $0a
GOLDEN_OUTPUT_2 = $08
GOLDEN_OUTPUT_3 = $00

View File

@@ -1,10 +0,0 @@
#ifndef _MAPPER_H
#define _MAPPER_H
#include <stdint.h>
void init_mapper();
void map(uint16_t p_page, uint8_t v_page);
#endif

View File

@@ -1,38 +0,0 @@
.MACPACK generic
.autoimport
.export _init_mapper
.export _map
MAPPER_BASE = $200
.code
; void init_paging();
; This should be identity mapped at reset, but we can do it again anyway
.proc _init_mapper
ldx #$00
L1:
txa
lsr
sta MAPPER_BASE,x
lda #$00
sta MAPPER_BASE+1,x
inx
inx
cpx #$20
blt L1
rts
.endproc
; void map(uint16_t p_page, uint8_t v_page);
.proc _map
asl
tax ; x = v_page * 2
jsr popa ; low byte of p_page
sta MAPPER_BASE,x ; write low byte to mm_low
jsr popa ; high byte of p_page
sta MAPPER_BASE+1,x ; write high byte to mm_high
rts
.endproc

View File

@@ -1,12 +0,0 @@
#ifndef _MULTIPLER_H
#define _MULTIPLER_H
#include <stdint.h>
/* Multiply 2 integers into 1 long */
uint32_t lmulii(uint16_t a, uint16_t b);
/* Multiply 2 integers into 1 integer, discarding upper bits. */
uint16_t imulii(uint16_t a, uint16_t b);
#endif

View File

@@ -1,36 +0,0 @@
.include "io.inc65"
.MACPACK generic
.import popax
.importzp sreg
.export _lmulii, _imulii
.code
.proc _lmulii
sta MULTIPLIER_BL
stx MULTIPLIER_BH
jsr popax
sta MULTIPLIER_AL
stx MULTIPLIER_AH
lda MULTIPLIER_OHL
sta sreg
lda MULTIPLIER_OHH
sta sreg+1
lda MULTIPLIER_OLL
ldx MULTIPLIER_OLH
rts
.endproc
.proc _imulii
sta MULTIPLIER_BL
stx MULTIPLIER_BH
jsr popax
sta MULTIPLIER_AL
stx MULTIPLIER_AH
lda MULTIPLIER_OLL
ldx MULTIPLIER_OLH
rts
.endproc

View File

@@ -1,25 +0,0 @@
#ifndef _RTC_H
#define _RTC_H
#include <stdint.h>
#define RTC_CMD_ADDR 0xeffe
#define RTC_DAT_ADDR 0xefff
#define RTC_THRESHOLD 0x00
#define RTC_INCREMENT 0x10
#define RTC_IRQ_THRESHOLD 0x20
#define RTC_OUTPUT 0x30
#define RTC_CONTROL 0x30
/* initialize RTC with default values */
void init_rtc(void);
/* handle RTC interrupts */
void handle_rtc(void);
void rtc_set(uint32_t val, uint8_t idx);
#endif

View File

@@ -1,112 +0,0 @@
.MACPACK generic
.importzp tmp1
.import popa
.export _init_rtc
.export _handle_rtc
.export _rtc_set
RTC_CMD = $effe
RTC_DAT = $efff
RTC_THRESHOLD = $00
RTC_INCREMENT = $10
RTC_IRQ_THRESHOLD = $20
RTC_OUTPUT = $30
RTC_CONTROL = $30
THRESHOLD_0 = $a0
THRESHOLD_1 = $0f
; THRESHOLD_1 = $00
THRESHOLD_2 = $00
THRESHOLD_3 = $00
IRQ_THRESHOLD_0 = $32
; IRQ_THRESHOLD_0 = $10
IRQ_THRESHOLD_1 = $00
IRQ_THRESHOLD_2 = $00
IRQ_THRESHOLD_3 = $00
; void init_rtc(void);
; Initialize rtc and generate 50ms interrupts
.proc _init_rtc
lda #RTC_INCREMENT+0 ; Set increment to 1
sta RTC_CMD
lda #$01
sta RTC_DAT
lda #RTC_INCREMENT+1
sta RTC_CMD
lda #$00
sta RTC_DAT
lda #RTC_INCREMENT+2
sta RTC_CMD
lda #$00
sta RTC_DAT
lda #RTC_INCREMENT+3
sta RTC_CMD
lda #$00
sta RTC_DAT
lda #RTC_THRESHOLD+0 ; Set threshold to 4000 ($fa0)
sta RTC_CMD
lda #THRESHOLD_0
sta RTC_DAT
lda #RTC_THRESHOLD+1
sta RTC_CMD
lda #THRESHOLD_1
sta RTC_DAT
lda #RTC_THRESHOLD+2
sta RTC_CMD
lda #THRESHOLD_2
sta RTC_DAT
lda #RTC_THRESHOLD+3
sta RTC_CMD
lda #THRESHOLD_3
sta RTC_DAT
lda #RTC_IRQ_THRESHOLD+0 ; Set irq threshold to 50 ($32)
sta RTC_CMD
lda #IRQ_THRESHOLD_0
sta RTC_DAT
lda #RTC_IRQ_THRESHOLD+1
sta RTC_CMD
lda #IRQ_THRESHOLD_1
sta RTC_DAT
lda #RTC_IRQ_THRESHOLD+2
sta RTC_CMD
lda #IRQ_THRESHOLD_2
sta RTC_DAT
lda #RTC_IRQ_THRESHOLD+3
sta RTC_CMD
lda #IRQ_THRESHOLD_3
sta RTC_DAT
lda #$30
sta RTC_CMD
lda #$3
sta RTC_DAT
rts
.endproc
; void rtc_set(uint32_t val, uint8_t idx);
.proc _rtc_set
sta tmp1 ; store idx in tmp1
ldx #$04
L1: lda tmp1
sta RTC_CMD ; store cmd+idx to CMD
jsr popa ; pop 1 byte of argument
sta RTC_DAT ; write it to data
inc tmp1 ; increase index
dex
bne L1 ; repeat 4 times
rts
.endproc
.proc _handle_rtc
nop
rti
.endproc

View File

@@ -1,445 +0,0 @@
#include <conio.h>
#include "sd_card.h"
#include "sd_print.h"
#include "spi.h"
/*******************************************************************************
Initialize SD card
*******************************************************************************/
uint8_t SD_init()
{
uint16_t i;
uint8_t res[5], cmdAttempts = 0;
SD_powerUpSeq();
while((res[0] = SD_goIdleState()) != SD_IN_IDLE_STATE)
{
cmdAttempts++;
if(cmdAttempts == CMD0_MAX_ATTEMPTS)
{
cputs("Go IDLE\r\n");
return SD_ERROR;
}
}
for (i = 0; i < 1000; i++);
SD_sendIfCond(res);
if(res[0] != SD_IN_IDLE_STATE)
{
cputs("IF Cond\r\n");
return SD_ERROR;
}
if(res[4] != 0xAA)
{
return SD_ERROR;
}
cmdAttempts = 0;
do
{
if(cmdAttempts == CMD55_MAX_ATTEMPTS)
{
cputs("op_cond error\r\n");
return SD_ERROR;
}
res[0] = SD_sendApp();
if(SD_R1_NO_ERROR(res[0]))
{
res[0] = SD_sendOpCond();
}
for (i = 0; i < 1000; i++);
cmdAttempts++;
}
while(res[0] != SD_READY);
for (i = 0; i < 1000; i++);
SD_readOCR(res);
return SD_SUCCESS;
}
/*
// Send a command with starting end ending clock pulses
uint8_t res1_cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
uint8_t res1;
// assert chip select
spi_exchange(0xFF);
spi_select(0);
spi_exchange(0xFF);
// send CMD0
SD_command(cmd, arg, crc);
// read response
res1 = SD_readRes1();
// deassert chip select
spi_exchange(0xFF);
spi_deselect(0);
spi_exchange(0xFF);
return res1;
}
*/
/*******************************************************************************
Run power up sequence
*******************************************************************************/
/*
void SD_powerUpSeq()
{
uint16_t i;
uint8_t j;
// make sure card is deselected
spi_deselect(0);
// give SD card time to power up
for (i = 0; i < 1000; i++);
// select SD card
spi_exchange(0xFF);
spi_deselect(0);
// send 80 clock cycles to synchronize
for(j = 0; j < SD_INIT_CYCLES; j++)
spi_exchange(0xFF);
}
*/
/*******************************************************************************
Send command to SD card
*******************************************************************************/
/*
void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc)
{
// transmit command to sd card
spi_exchange(cmd|0x40);
// transmit argument
spi_exchange((uint8_t)(arg >> 24));
spi_exchange((uint8_t)(arg >> 16));
spi_exchange((uint8_t)(arg >> 8));
spi_exchange((uint8_t)(arg));
// transmit crc
spi_exchange(crc|0x01);
}
*/
/*******************************************************************************
Read R1 from SD card
*******************************************************************************/
/*
uint8_t SD_readRes1()
{
uint8_t i = 0, res1;
// keep polling until actual data received
while((res1 = spi_exchange(0xFF)) == 0xFF)
{
i++;
// if no data received for 8 bytes, break
if(i > 8) break;
}
return res1;
}
*/
/*******************************************************************************
Read R2 from SD card
*******************************************************************************/
/*
void SD_readRes2(uint8_t *res)
{
// read response 1 in R2
res[0] = SD_readRes1();
// read final byte of response
res[1] = spi_exchange(0xFF);
}
*/
/*******************************************************************************
Read R3 from SD card
*******************************************************************************/
/*
void SD_readRes3(uint8_t *res)
{
// read response 1 in R3
res[0] = SD_readRes1();
// if error reading R1, return
if(res[0] > 1) return;
// read remaining bytes
SD_readBytes(res + 1, R3_BYTES);
}
*/
/*******************************************************************************
Read R7 from SD card
*******************************************************************************/
/*
void SD_readRes7(uint8_t *res)
{
// read response 1 in R7
res[0] = SD_readRes1();
// if error reading R1, return
if(res[0] > 1) return;
// read remaining bytes
SD_readBytes(res + 1, R7_BYTES);
}
*/
/*******************************************************************************
Read specified number of bytes from SD card
*******************************************************************************/
/*
void SD_readBytes(uint8_t *res, uint8_t n)
{
while(n--) *res++ = spi_exchange(0xFF);
}
*/
/*******************************************************************************
Command Idle State (CMD0)
*******************************************************************************/
uint8_t SD_goIdleState()
{
return res1_cmd(CMD0, CMD0_ARG, CMD0_CRC);
}
/*******************************************************************************
Send Interface Conditions (CMD8)
*******************************************************************************/
void SD_sendIfCond(uint8_t *res)
{
// assert chip select
spi_exchange(0xFF);
spi_select(0);
spi_exchange(0xFF);
// send CMD8
SD_command(CMD8, CMD8_ARG, CMD8_CRC);
// read response
SD_readRes7(res);
//SD_readBytes(res + 1, R7_BYTES);
// deassert chip select
spi_exchange(0xFF);
spi_deselect(0);
spi_exchange(0xFF);
}
/*******************************************************************************
Read Status
*******************************************************************************/
void SD_sendStatus(uint8_t *res)
{
// assert chip select
spi_exchange(0xFF);
spi_select(0);
spi_exchange(0xFF);
// send CMD13
SD_command(CMD13, CMD13_ARG, CMD13_CRC);
// read response
SD_readRes2(res);
// deassert chip select
spi_exchange(0xFF);
spi_deselect(0);
spi_exchange(0xFF);
}
/*******************************************************************************
Read single 512 byte block
token = 0xFE - Successful read
token = 0x0X - Data error
token = 0xFF - timeout
*******************************************************************************/
// uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token)
// {
// uint8_t res1, read;
// uint16_t readAttempts;
// uint16_t i;
// // set token to none
// *token = 0xFF;
// // assert chip select
// spi_exchange(0xFF);
// spi_select(0);
// spi_exchange(0xFF);
// // send CMD17
// SD_command(CMD17, addr, CMD17_CRC);
// // read R1
// res1 = SD_readRes1();
// // if response received from card
// if(res1 != 0xFF)
// {
// // wait for a response token (timeout = 100ms)
// readAttempts = 0;
// while(++readAttempts != SD_MAX_READ_ATTEMPTS)
// if((read = spi_exchange(0xFF)) != 0xFF) break;
// cprintf("read attempts: %d\r\n", readAttempts);
// // if response token is 0xFE
// if(read == SD_START_TOKEN)
// {
// // read 512 byte block
// for(i = 0; i < SD_BLOCK_LEN; i++) *buf++ = spi_exchange(0xFF);
// // read 16-bit CRC
// spi_exchange(0xFF);
// spi_exchange(0xFF);
// }
// // set token to card response
// *token = read;
// }
// // deassert chip select
// spi_exchange(0xFF);
// spi_deselect(0);
// spi_exchange(0xFF);
// return res1;
// }
#define SD_MAX_WRITE_ATTEMPTS 3907
/*******************************************************************************
Write single 512 byte block
token = 0x00 - busy timeout
token = 0x05 - data accepted
token = 0xFF - response timeout
*******************************************************************************/
uint8_t SD_writeSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token)
{
(void)addr;
(void)buf;
(void)token;
/*
uint16_t readAttempts;
uint8_t res1, read;
uint16_t i;
// set token to none
*token = 0xFF;
// assert chip select
spi_exchange(0xFF);
spi_select(0);
spi_exchange(0xFF);
// send CMD24
SD_command(CMD24, addr, CMD24_CRC);
// read response
res1 = SD_readRes1();
// if no error
if(res1 == SD_READY)
{
// send start token
spi_exchange(SD_START_TOKEN);
// write buffer to card
for(i = 0; i < SD_BLOCK_LEN; i++) spi_exchange(buf[i]);
// wait for a response (timeout = 250ms)
readAttempts = 0;
while(++readAttempts != SD_MAX_WRITE_ATTEMPTS)
if((read = spi_exchange(0xFF)) != 0xFF) { *token = 0xFF; break; }
// if data accepted
if((read & 0x1F) == 0x05)
{
// set token to data accepted
*token = 0x05;
// wait for write to finish (timeout = 250ms)
readAttempts = 0;
while(spi_exchange(0xFF) == 0x00)
if(++readAttempts == SD_MAX_WRITE_ATTEMPTS) { *token = 0x00; break; }
}
}
// deassert chip select
spi_exchange(0xFF);
spi_deselect(0);
spi_exchange(0xFF);
return res1;
*/
return 0;
}
/*******************************************************************************
Reads OCR from SD Card
*******************************************************************************/
void SD_readOCR(uint8_t *res)
{
uint8_t tmp;
// assert chip select
spi_exchange(0xFF);
spi_select(0);
tmp = spi_exchange(0xFF);
if(tmp != 0xFF) while(spi_exchange(0xFF) != 0xFF) ;
// send CMD58
SD_command(CMD58, CMD58_ARG, CMD58_CRC);
// read response
SD_readRes3(res);
// deassert chip select
spi_exchange(0xFF);
spi_deselect(0);
spi_exchange(0xFF);
}
/*******************************************************************************
Send application command (CMD55)
*******************************************************************************/
uint8_t SD_sendApp()
{
return res1_cmd(CMD55, CMD55_ARG, CMD55_CRC);;
}
/*******************************************************************************
Send operating condition (ACMD41)
*******************************************************************************/
uint8_t SD_sendOpCond()
{
return res1_cmd(ACMD41, ACMD41_ARG, ACMD41_CRC);
}

View File

@@ -1,80 +0,0 @@
#ifndef _SD_CARD_H
#define _SD_CARD_H
#include <stdint.h>
// command definitions
#define CMD0 0
#define CMD0_ARG 0x00000000
#define CMD0_CRC 0x94
#define CMD8 8
#define CMD8_ARG 0x0000001AA
#define CMD8_CRC 0x86
#define CMD9 9
#define CMD9_ARG 0x00000000
#define CMD9_CRC 0x00
#define CMD10 9
#define CMD10_ARG 0x00000000
#define CMD10_CRC 0x00
#define CMD13 13
#define CMD13_ARG 0x00000000
#define CMD13_CRC 0x00
#define CMD17 17
#define CMD17_CRC 0x00
#define CMD24 24
#define CMD24_CRC 0x00
#define CMD55 55
#define CMD55_ARG 0x00000000
#define CMD55_CRC 0x00
#define CMD58 58
#define CMD58_ARG 0x00000000
#define CMD58_CRC 0x00
#define ACMD41 41
#define ACMD41_ARG 0x40000000
#define ACMD41_CRC 0x00
#define SD_IN_IDLE_STATE 0x01
#define SD_READY 0x00
#define SD_R1_NO_ERROR(X) X < 0x02
#define R3_BYTES 4
#define R7_BYTES 4
#define CMD0_MAX_ATTEMPTS 255
#define CMD55_MAX_ATTEMPTS 255
#define SD_ERROR 1
#define SD_SUCCESS 0
#define SD_MAX_READ_ATTEMPTS 1563
#define SD_READ_START_TOKEN 0xFE
#define SD_INIT_CYCLES 80
#define SD_START_TOKEN 0xFE
#define SD_ERROR_TOKEN 0x00
#define SD_DATA_ACCEPTED 0x05
#define SD_DATA_REJECTED_CRC 0x0B
#define SD_DATA_REJECTED_WRITE 0x0D
#define SD_BLOCK_LEN 512
// SD functions
uint8_t SD_init();
void SD_powerUpSeq();
void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc);
uint8_t SD_readRes1();
void SD_readRes2(uint8_t *res);
void SD_readRes3(uint8_t *res);
void SD_readRes7(uint8_t *res);
void SD_readBytes(uint8_t *res, uint8_t n);
uint8_t SD_goIdleState();
void SD_sendIfCond(uint8_t *res);
void SD_sendStatus(uint8_t *res);
void SD_readOCR(uint8_t *res);
uint8_t SD_sendApp();
uint8_t SD_sendOpCond();
uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *error);
uint8_t SD_writeSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *res);
uint8_t res1_cmd(uint8_t cmd, uint32_t arg, uint8_t crc);
#endif

View File

@@ -1,303 +0,0 @@
.export _SD_command
.export _SD_readRes1
.export _SD_readRes2
.export _SD_readRes3
.export _SD_readRes7
.export _SD_readBytes
.export _SD_powerUpSeq
.export _res1_cmd
.export _SD_readSingleBlock
.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3
.autoimport on
.MACPACK generic
; void SD_command(uint8_t cmd, uint32_t arg, uint8_t crc)
; The plan: push crc to stack, load arg into tmp1 through 4
.proc _SD_command: near
pha ; Push CRC to cpu stack
ldy #$04
lda (sp),y ; Load CMD
ora #$40 ; start bit
jsr _spi_exchange
dey
arg_loop: ; send ARG
lda (sp),y ; is this sending only 3?
jsr _spi_exchange
dey
bpl arg_loop
pla ; Pull CRC from stack
ora #$01 ; stop bit
jsr _spi_exchange
jsr incsp5 ; pop all off stack
rts
.endproc
; uint8_t SD_readRes1 (void)
.proc _SD_readRes1: near
; Try to read/write up to 8 times, then return value
ldx #$08
tryread:
lda #$ff
jsr _spi_exchange
cmp #$ff
bne end
dex
bne tryread
end: ; x will be 0 here anyway
rts
.endproc
; void SD_readRes2(uint8_t *res)
.proc _SD_readRes2: near
sta ptr1 ; store res in ptr1
stx ptr1 + 1
jsr _SD_readRes1 ; get first response 1
sta (ptr1)
lda #$ff
jsr _spi_exchange ; get final byte of response
ldy #$01
sta (ptr1),y
jsr incsp2
rts
.endproc
; void SD_readBytes(uint8_t *res, uint8_t n)
.proc _SD_readBytes: near
tax
jsr popptr1 ; store res in ptr1
read:
lda #$ff ; read data first
jsr _spi_exchange
sta (ptr1)
inc ptr1 ; then increment res
bne @L1
inc ptr1 + 1
@L1: dex ; then decrement x
bne read ; and if x is zero we are done
rts
.endproc
; void SD_readRes7(uint8_t *res)
_SD_readRes7:
; void SD_readRes3(uint8_t *res)
.proc _SD_readRes3: near
sta ptr1 ; store res in ptr1
stx ptr1 + 1
jsr _SD_readRes1 ; read respopnse 1 in R3
cmp #$02 ; if error reading R1, return
bge @L1
inc ptr1 ; read remaining bytes
bne @L2
inc ptr1
@L2: lda ptr1 ; push low byte
ldx ptr1 + 1
jsr pushax
lda #$04 ; R3_BYTES
jsr _SD_readBytes
@L1: rts
.endproc
; uint8_t res1_cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
.proc _res1_cmd: near
pha ; push crc to processor stack
lda #$ff
jsr _spi_exchange
lda #$00 ; this gets ignored anyway
jsr _spi_select
lda #$ff
jsr _spi_exchange
pla
jsr _SD_command ; rely on command to teardown stack
jsr _SD_readRes1
tay ; spi doesn't touch y
lda #$ff
jsr _spi_exchange
lda #$00 ; this gets ignored anyway
jsr _spi_deselect
lda #$ff
jsr _spi_exchange
tya
ldx #$00 ; Promote to integer
rts
.endproc
; void SD_powerUpSeq(void)
.proc _SD_powerUpSeq: near
lda #$00
jsr _spi_deselect
jsr _sd_delay
lda #$ff
jsr _spi_exchange
lda #$00
jsr _spi_deselect
ldx #$50 ; SD_INIT_CYCLES
@L1: lda #$ff
jsr _spi_exchange
dex
bne @L1
rts
.endproc
; 1ms delay approx. saves no registers
.proc _sd_delay: near
ldx #$01 ; delay loop: A*X*10 + 4
@L1: lda #$c8 ; 1ms at 2MHz
@L2: dec ; 2
bne @L2 ; 3
dex ; 2
bne @L1 ; 3
rts
.endproc
; ;uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token)
.proc _SD_readSingleBlock: near
; token address in a/x
; buf address next on stack
; sd address above that
; ptr2 = *token
sta ptr2
stx ptr2 + 1
lda #$ff
sta (ptr2)
; ptr1 = *buf
jsr popptr1
; 4 bytes on stack are addr
; Move addr down on the stack
lda sp
sta ptr3
lda sp + 1
sta ptr3 + 1
; find a way to do this in a loop?
jsr decsp1
ldy #$0
lda (ptr3),y
sta (sp),y
iny
lda (ptr3),y
sta (sp),y
iny
lda (ptr3),y
sta (sp),y
iny
lda (ptr3),y
sta (sp),y
lda #$ff
jsr _spi_exchange
lda #$00 ; this gets ignored anyway
jsr _spi_select
lda #$ff
jsr _spi_exchange
; push cmd17
lda #$11
ldy #$4
sta (sp),y
; crc, 0
lda #$00
jsr _SD_command ; rely on command to teardown stack
jsr _SD_readRes1
cmp #$ff ; if 0xFF then you failed
beq end
sta tmp3 ; tmp3 = read
; y = read_attempts
ldy #$0
resp_loop:
lda #$ff
jsr _spi_exchange
sta tmp2 ; tmp2 = read
lda tmp2
cmp #$ff
bne got_resp
iny
bne resp_loop
bra after_read
got_resp:
ldx #$2
ldy #$00
load_loop:
lda #$ff
jsr _spi_exchange
sta (ptr1)
inc ptr1
bne @2
inc ptr1 + 1
@2: dey
bne load_loop
ldy #$00
dex
bne load_loop
lda #$ff
jsr _spi_exchange
lda #$ff
jsr _spi_exchange
after_read:
lda tmp2
sta (ptr2)
lda tmp3
end:
pha
lda #$ff
jsr _spi_exchange
lda #$00 ; this gets ignored anyway
jsr _spi_deselect
lda #$ff
jsr _spi_exchange
pla
rts
.endproc

View File

@@ -1,26 +0,0 @@
#include <conio.h>
#include "sd_print.h"
#include "sd_card.h"
void SD_printBuf(uint8_t *buf)
{
uint8_t colCount = 0;
uint16_t i;
for(i = 0; i < SD_BLOCK_LEN; i++)
{
cprintf("%2x", *buf++);
if(colCount == 31)
{
cputs("\r\n");
colCount = 0;
}
else
{
cputc(' ');
colCount++;
}
}
cputs("\r\n");
}

View File

@@ -1,61 +0,0 @@
#ifndef SD_PRINT_H
#define SD_PRINT_H
#include <stdint.h>
/* R1 MACROS */
#define PARAM_ERROR(X) X & 0b01000000
#define ADDR_ERROR(X) X & 0b00100000
#define ERASE_SEQ_ERROR(X) X & 0b00010000
#define CRC_ERROR(X) X & 0b00001000
#define ILLEGAL_CMD(X) X & 0b00000100
#define ERASE_RESET(X) X & 0b00000010
#define IN_IDLE(X) X & 0b00000001
/* R2 MACROS */
#define OUT_OF_RANGE(X) X & 0b10000000
#define ERASE_PARAM(X) X & 0b01000000
#define WP_VIOLATION(X) X & 0b00100000
#define CARD_ECC_FAILED(X) X & 0b00010000
#define CC_ERROR(X) X & 0b00001000
#define ERROR(X) X & 0b00000100
#define WP_ERASE_SKIP(X) X & 0b00000010
#define CARD_LOCKED(X) X & 0b00000001
/* R3 MACROS */
#define POWER_UP_STATUS(X) X & 0x40
#define CCS_VAL(X) X & 0x40
#define VDD_2728(X) X & 0b10000000
#define VDD_2829(X) X & 0b00000001
#define VDD_2930(X) X & 0b00000010
#define VDD_3031(X) X & 0b00000100
#define VDD_3132(X) X & 0b00001000
#define VDD_3233(X) X & 0b00010000
#define VDD_3334(X) X & 0b00100000
#define VDD_3435(X) X & 0b01000000
#define VDD_3536(X) X & 0b10000000
/* R7 MACROS */
#define CMD_VER(X) ((X >> 4) & 0xF0)
#define VOL_ACC(X) (X & 0x1F)
#define VOLTAGE_ACC_27_33 0b00000001
#define VOLTAGE_ACC_LOW 0b00000010
#define VOLTAGE_ACC_RES1 0b00000100
#define VOLTAGE_ACC_RES2 0b00001000
/* DATA ERROR TOKEN */
#define SD_TOKEN_OOR(X) X & 0b00001000
#define SD_TOKEN_CECC(X) X & 0b00000100
#define SD_TOKEN_CC(X) X & 0b00000010
#define SD_TOKEN_ERROR(X) X & 0b00000001
void SD_printR1(uint8_t res);
void SD_printR2(uint8_t *res);
void SD_printR3(uint8_t *res);
void SD_printR7(uint8_t *res);
void SD_printBuf(uint8_t *buf);
void SD_printDataErrToken(uint8_t token);
#endif

View File

@@ -1,17 +0,0 @@
#ifndef _SERIAL_H
#define _SERIAL_H
#include <stdint.h>
void serial_handle_irq();
void serial_init();
void serial_putc(char c);
void serial_puts(char* s);
char serial_getc();
char serial_getc_nb();
#endif

View File

@@ -1,94 +0,0 @@
.MACPACK generic
.autoimport
.import _enable_irq, _send_eoi, _uart_txb_block
.importzp tmp1, ptr1
.export _serial_init
.export _serial_handle_irq
.export _serial_putc, _serial_puts, _serial_getc, _serial_getc_nb
.zeropage
last_char: .res 1
.code
UART = $efe6
UART_TXB = UART
UART_RXB = UART
UART_STATUS = UART + 1
; Initialize Serial Port
; No initialization needed, just register irq handler.
.proc _serial_init
lda #<_serial_handle_irq
ldx #>_serial_handle_irq
jsr pushax
lda #$01
jsr _register_irq
stz last_char
rts
.endproc
; Serial Port IRQ Handler
; Get the character and store it.
.proc _serial_handle_irq
lda UART_RXB
ora #$80 ; set msb
sta last_char
jsr _send_eoi
rti
.endproc
; Serial Port Get Character
; If a character has not been received, block until one is.
.proc _serial_getc
L1: lda last_char
bpl L1
and #$7f
sta last_char
rts
.endproc
; Serial Port Get Character Non-Blocking
; return last character, even if it has already been read.
; If the character is new, we still clear the new flag.
.proc _serial_getc_nb
lda last_char
bpl L1
and #$7f
sta last_char
L1: rts
.endproc
; Serial Port Put Character
; send a single character over the serial port.
.proc _serial_putc
jsr _uart_txb_block
cmp #$0a
bne @1
lda #$0d
jsr _uart_txb_block
@1: rts
.endproc
; Send a string over the serial port. Needs stlen
.proc _serial_puts
sta ptr1 ; Store pointer in ptr1
stx ptr1+1
ldy #$00 ; initialize y to 0
L1: lda (ptr1),y ; load character from string
beq L2 ; Quit if NULL
jsr _serial_putc ; send character (does not change y or ptr1)
iny ; increment y
bne L1 ; If Y == 0, increment high byte of pointer
inc ptr1+1
bne L1 ; if high byte wraps around, give up
L2: rts
.endproc

View File

@@ -1,12 +0,0 @@
#ifndef _SPI_H
#define _SPI_H
#include <stdint.h>
void spi_select(uint8_t id);
void spi_deselect(uint8_t id);
uint8_t spi_read();
void spi_write(uint8_t data);
uint8_t spi_exchange(uint8_t data);
#endif

View File

@@ -1,39 +0,0 @@
.include "io.inc65"
.importzp zp, sreg
.export _spi_select, _spi_deselect
.export _spi_read, _spi_write, _spi_exchange
.autoimport on
.code
; void spi_select(uint8_t id)
; Select a (the) slave by pulling its CS line down
; TODO allow active high or active low CS
; TODO allow more than one slave
_spi_select:
lda #$1 ; Ignore whatever id is, 1 is the only option
sta SPI_CTRL
rts
; void spi_deslect(uint8_t id)
; Deslect a slave by pulling its CS line up
; TODO allow active high or active low CS
_spi_deselect:
stz SPI_CTRL
rts
; uint8_t spi_read()
_spi_read:
lda #$0
; void spi_write(uint8_t data)
_spi_write:
; uint8_t spi_exchange(uint8_t data)
_spi_exchange:
sta SPI_OUTPUT
@1: lda SPI_CTRL
bmi @1
lda SPI_INPUT
rts

View File

@@ -1,13 +0,0 @@
#ifndef _TERMINAL_H
#define _TERMINAL_H
#include <stdint.h>
int8_t terminal_read(uint8_t fd, void* buf, uint8_t nbytes);
int8_t terminal_write(uint8_t fd, const void* buf, uint8_t nbytes);
int8_t terminal_open(const uint8_t* filename);
int8_t terminal_close(uint8_t fd);
#endif /* _TERMINAL_H */

View File

@@ -1,145 +0,0 @@
.MACPACK generic
.autoimport
.importzp tmp1, ptr1
.import _serial_getc
.export _terminal_read, _terminal_write, _terminal_open, _terminal_close
.data
terminal_buf: .res 128
.code
; int8_t terminal_read(uint8_t fd, void* buf, uint8_t nbytes);
; Read up to size-1 (127 max) before the enter key is pressed.
; A newline character is automatically added.
; Inputs: int8_t* buf - where input characters are stored
; uint8_t n - number of characters to read (max buf size minux 1)
; Return Value: number of characters read on success, -1 on failure
; Function: Reads keyboard input
.proc _terminal_read
cmp #$00 ; Check that nbytes is > 0 and < 128
beq FAIL
cmp #$81
bge FAIL
sta tmp1 ; Store nbytes in tmp1
jsr popax ; Check that buf != NULL
cmp #$00
bne L1
cpx #$00
bne L1
bra FAIL
; while i < nbytes, store getc into terminal_buf y
L1: sta ptr1
stx ptr1+1
ldy #$00
LOOP: cpy tmp1
bge END
jsr _serial_getc
sta terminal_buf,y
cmp #$0d ; If newline, do something
bne L2
lda #$0a ; hacky serial, we want $0a, not $0d
jsr _serial_putc
bra END
L2: cmp #$08 ; Handle backspace
bne L3
lda tmp1
beq LOOP
lda #$08
jsr _serial_putc
dey
lda #$00
sta terminal_buf,y
bra LOOP
L3: lda terminal_buf,y ; Normal character
sta (ptr1),y
jsr _serial_putc
iny
bra LOOP
END: phy ; Zero out terminal buffer
ldy #$00
lda #$00
L4: sta terminal_buf,y
iny
cpy #$80
blt L4
L5: ply ; End string with NULL
lda #$0a
sta (ptr1),y
iny
cpy #$80 ; But not if we are at max
bge L6
lda #$00
sta (ptr1),y
L6: lda #$00 ; Return - on success
rts
FAIL: lda #$ff ; return -1 on fail
rts
.endproc
; int8_t terminal_write(uint8_t fd, const void* buf, uint8_t nbytes);
; write characters to the terminal
; Inputs: int8_t* buf - buffer of characters to write
; uint8_t n - number of characters to write
; Return Value: 0 on success, -1 on failure
; Writes to screen. Only stops after n chars written.
; This seems to not care about null termination?
.proc _terminal_write
sta tmp1 ; put nbytes in tmp1
jsr popax ; check that buf is not null
cmp #$00
bne L1
cpx #$00
bne L1
bra FAIL
L1: sta ptr1
stx ptr1+1
ldy #$00
LOOP: lda (ptr1),y ; Loop through buffer and print
jsr _serial_putc
iny
cpy tmp1
blt LOOP
lda #$00
rts
FAIL: lda #$ff ; old code didn't fail, but new code does.
rts
.endproc
; terminal_open
; open terminal device
; Inputs: uint8_t* filename
; Outputs: none
; Return Value: 0 on success
; Function: none.
.proc _terminal_open
lda #$0
rts
.endproc
; terminal_close
; close terminal device
; Inputs: int32_t fd
; Outputs: none
; Return Value: 0 on success (but this always failes)
; Function: none.
.proc _terminal_close
lda #$ff ; -1
rts
.endproc

View File

@@ -1,13 +0,0 @@
#ifndef _UART_H
#define _UART_H
#include <stdint.h>
void uart_txb(uint8_t val);
void uart_txb_block(uint8_t val);
uint8_t uart_rxb();
uint8_t uart_status();
#endif

View File

@@ -1,36 +0,0 @@
.include "io.inc65"
.importzp sp, sreg
.export _uart_txb, _uart_txb_block
.export _uart_rxb
.export _uart_status
.autoimport on
.code
; @in A: byte to transmit
; Transmits a byte over the UART
_uart_txb:
sta UART_TXB ; Just write value, don't wait
rts
_uart_txb_block:
pha
sta UART_TXB ; Write value
@1: lda UART_STATUS ; Wait for status[1] to be 0
bit #$02
bne @1
pla
rts
_uart_rxb:
lda UART_RXB ; Read value
ldx #$00
rts
_uart_status:
lda UART_STATUS
ldx #$00
rts

View File

@@ -1,53 +0,0 @@
#ifndef _FAT32_H
#define _FAT32_H
#include <stdint.h>
#include <stdio.h>
void fat32_init();
extern uint32_t root_cluster;
extern uint16_t fat_start_sector;
extern uint32_t data_start_sector;
extern uint32_t fat_size;
extern uint8_t* sd_buf;
extern uint8_t sectors_per_cluster;
extern uint8_t log2_sectors_per_cluster;
struct fat32_directory_entry {
char file_name[8];
char file_ext[3];
uint8_t attr1;
uint8_t attr2;
uint8_t create_time_10ms;
uint16_t create_time;
uint16_t create_date;
uint16_t access_date;
uint16_t cluster_high;
uint16_t modified_time;
uint16_t modified_date;
uint16_t cluster_low;
uint32_t file_size;
};
struct lfn_entry {
uint8_t sequence_number;
uint16_t name_0[5];
uint8_t attributes;
uint8_t type;
uint8_t checksum;
uint16_t name_1[6];
uint16_t cluster_low;
uint16_t name_2[2];
};
int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry);
int8_t fat32_read_sector(uint32_t cluster, uint32_t sector, void* buf);
uint32_t fat32_next_cluster(uint32_t cluster);
int8_t fat32_file_open(const char* filename);
size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes);
size_t fat32_file_write(int8_t fd, const void* buf, size_t nbytes);
int8_t fat32_file_close(int8_t fd);
#endif

View File

@@ -1,112 +0,0 @@
.MACPACK generic
.autoimport
.feature string_escapes
.importzp ptr1, sreg
.import _SD_readSingleBlock
.export _fat32_init
.export _root_cluster, _fat_start_sector, _data_start_sector
.export _fat_size, _sd_buf, _sectors_per_cluster, _log2_sectors_per_cluster
.data
_root_cluster: .res 4
_fat_start_sector: .res 2
_data_start_sector: .res 4
_fat_size: .res 4
_sectors_per_cluster: .res 1
_log2_sectors_per_cluster: .res 1
_sd_buf: .res 512
data_start_sect_str: .asciiz "Data sector start: 0x%lx\n"
starting_cluster_str: .asciiz "Root cluster num: %lx\n";
value_str: .asciiz "Value: 0x%x\n"
.code
bytes_per_sector = _sd_buf + $0B
sectors_per_cluster = _sd_buf + $0D
reserved_sectors = _sd_buf + $0E
fat_count = _sd_buf + $10
sectors_per_fat = _sd_buf + $24
root_cluster_offs = _sd_buf + $2C
.proc _fat32_init
; load sector 0 into sd_buf
lda #$00
ldx #$00
stz sreg
stz sreg+1
jsr pusheax
lda #<_sd_buf
ldx #>_sd_buf
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
lda sectors_per_cluster
sta _sectors_per_cluster
ldx #$0
@1: bit #$01
bne L0
inx
lsr
bra @1
L0: txa
sta _log2_sectors_per_cluster
ldx #$00
L1: lda root_cluster_offs,x
sta _root_cluster,x
inx
cpx #$4
blt L1
; Multiply reserved sectors and bytes per sector, then divide by 512 to get sd sectors
lda reserved_sectors
jsr pusha0
lda bytes_per_sector
ldx bytes_per_sector+1
jsr _imulii
txa
lsr
sta _fat_start_sector
stz _fat_start_sector + 1
; multiply fat size and number of fats to get total fat size
lda fat_count
jsr pusha0
lda sectors_per_fat
ldx sectors_per_fat+1
jsr _lmulii
sta _fat_size
stx _fat_size+1
lda sreg
sta _fat_size+2
lda sreg+1
sta _fat_size+3
; Add fat size to starting fat sector to get data start sector
clc
lda _fat_size
adc _fat_start_sector
sta _data_start_sector
lda _fat_size+1
adc _fat_start_sector+1
sta _data_start_sector+1
lda _fat_size+2
sta _data_start_sector+2
lda _fat_size+3
sta _data_start_sector+3
rts
.endproc

View File

@@ -1,207 +0,0 @@
#include <devices/sd_card.h>
#include <process/process.h>
#include <conio.h>
#include <stdint.h>
#include <string.h>
#include "fat32.h"
#include "fs.h"
static struct fops fat32_file_ops = {fat32_file_open, fat32_file_close, fat32_file_read, fat32_file_write};
int8_t fd_val;
//TODO
size_t fat32_file_write(int8_t fd, const void* buf, size_t nbytes) {
(void)fd;
(void)buf;
(void)nbytes;
return -1;
}
/*
* file_close
* DESCRIPTION: close device abstracted as file
* INPUTS: fd -- file descriptor for file to be closed
* OUTPUTS: none
* RETURN VALUE: none
* SIDE EFFECTS: none
*/
int8_t fat32_file_close(int8_t fd) {
struct pcb* pcb;
pcb = get_pcb_ptr();
/* update pcb to remove process */
pcb->file_desc_array[fd].flags = !IN_USE;
return 0;
}
int8_t fat32_file_open(const char* filename) {
int8_t ret;
int8_t i;
int8_t fd;
struct fat32_directory_entry dentry;
struct pcb* pcb = get_pcb_ptr();
ret = fat32_get_cluster_by_name(filename, &dentry);
if (ret) {
cprintf("Error finding cluster for filename");
return -1;
}
/* try to find an empty file desciptor, fail otherwise */
//TODO We start at 3 here because 0, 1, 2 will be reserved later
for (i = 3; i < FILE_DESC_SIZE; i++) {
if (pcb->file_desc_array[i].flags == !IN_USE) {
fd = i;
break;
}
}
if (fd == -1){
return -1;
}
/* add process */
pcb->file_desc_array[fd].f32_dentry = dentry;
pcb->file_desc_array[fd].flags = IN_USE;
pcb->file_desc_array[fd].file_pos = 0;
pcb->file_desc_array[fd].file_ops = &fat32_file_ops;
return fd;
}
size_t fat32_file_read(int8_t fd, void* buf, size_t nbytes) {
uint16_t i;
size_t offset;
size_t leftover_length;
size_t bytes_read = 0;
size_t clusters;
uint32_t sector;
struct pcb* pcb = get_pcb_ptr();
struct file_desc* fdesc = &pcb->file_desc_array[fd];
uint32_t cluster_seq = fdesc->file_pos >> (9 + log2_sectors_per_cluster);
uint32_t cluster = ((uint32_t)fdesc->f32_dentry.cluster_high << 16) | fdesc->f32_dentry.cluster_low;
/* validate starting position isn't past end of file */
if (fdesc->file_pos >= fdesc->f32_dentry.file_size){
return 0;
}
/* validate final pos isn't past end of file */
if (fdesc->file_pos+nbytes > fdesc->f32_dentry.file_size){
nbytes = fdesc->f32_dentry.file_size - fdesc->file_pos;
}
// This can stay for now, as long as cluster_seq is correct.
for (i = 0; i < cluster_seq; i++) {
cluster = fat32_next_cluster(cluster);
}
clusters = nbytes >> (9 + log2_sectors_per_cluster);
/* Handle first unaligned block */
offset = fdesc->file_pos % 512; // This is the offset into the sector, not the cluster
leftover_length = 512 - offset;
sector = (fdesc->file_pos >> 9) & (sectors_per_cluster-1);
if (leftover_length != 0) {
if (nbytes <= leftover_length) {
fat32_read_sector(cluster, sector, sd_buf);
memcpy(buf, sd_buf + offset, nbytes);
bytes_read += nbytes;
fdesc->file_pos += bytes_read;
return bytes_read;
} else {
fat32_read_sector(cluster, sector, sd_buf);
memcpy(buf, sd_buf + offset, leftover_length);
bytes_read += leftover_length;
fdesc->file_pos += bytes_read;
}
}
/* Handle middle aligned blocks */
for (i = 0; i < clusters; i++) {
cluster = fat32_next_cluster(cluster);
if (cluster >= 0xffffff00) {
// cprintf("Last cluster in file!\n");
}
if (nbytes - bytes_read > 512) {
leftover_length = 512;
} else {
leftover_length = nbytes - bytes_read;
}
fat32_read_sector(cluster, cluster, sd_buf);
memcpy((uint8_t*)buf+bytes_read, sd_buf, leftover_length);
bytes_read += leftover_length;
fdesc->file_pos += bytes_read;
if (bytes_read == nbytes) {
return bytes_read;
}
}
return bytes_read;
}
// Read the sector offset from a given cluster into buf
// Why do we need this though, this is just doing a single multiplication?
// No, it is also doing an addition
int8_t fat32_read_sector(uint32_t cluster, uint32_t sector, void* buf) {
uint8_t error;
uint32_t addr = (cluster - 2) * sectors_per_cluster + sector + data_start_sector;
SD_readSingleBlock(addr, buf, &error);
return error;
}
// This will not handle clusters numbers that leaves a sector
uint32_t fat32_next_cluster(uint32_t cluster) {
uint8_t error;
uint32_t addr = fat_start_sector;
uint32_t cluster_val;
SD_readSingleBlock(addr, sd_buf, &error);
cluster_val = ((uint32_t*)sd_buf)[cluster];
return cluster_val;
}
int8_t fat32_get_cluster_by_name(const char* name, struct fat32_directory_entry* dentry) {
struct fat32_directory_entry* local_entry;
int i = 0;
uint32_t cluster;
cluster = fat32_next_cluster(root_cluster);
cprintf("Sectors per cluster: %hhx\n", sectors_per_cluster);
fat32_read_sector(root_cluster, 0, sd_buf);
for (i = 0; i < 16; i++){
local_entry = (struct fat32_directory_entry*)(sd_buf + i*32);
if (local_entry->attr1 == 0xf || local_entry->attr1 & 0x8 || !local_entry->attr1) {
continue;
}
cprintf("Name: %.11s\n", local_entry->file_name, local_entry->file_ext);
if (!strncmp(local_entry->file_name, name, 11)) {
i = -1;
break;
}
}
if (i != -1) {
cprintf("Failed to find file.\n");
return -1;
}
cprintf("Found file!\n");
memcpy(dentry, local_entry, 32);
return 0;
}

View File

@@ -1,22 +0,0 @@
#ifndef _FS_H
#define _FS_H
#include <stdint.h>
#include <stdio.h>
#include <process/process.h>
/* syscalls for files */
size_t file_read(int8_t fd, void* buf, size_t nbytes);
size_t file_write(int8_t fd, const void* buf, size_t nbytes);
int8_t file_open(const char* filename);
int8_t file_close(int8_t fd);
/* syscalls for directories */
size_t directory_read(int8_t fd, void* buf, size_t nbytes);
size_t directory_write(int8_t fd, const void* buf, size_t nbytes);
int8_t directory_open(const char* filename);
int8_t directory_close(int8_t fd);
#endif

View File

@@ -1,16 +0,0 @@
#ifndef _INTERRUPT_H
#define _INTERRUPT_H
#include <stdint.h>
#define BUTTON (1 << 0)
#define UART (1 << 1)
void init_interrupts();
void register_irq(void* addr, uint8_t irqn);
uint8_t irq_get_status();
void irq_set_status(uint8_t);
#endif

View File

@@ -1,76 +0,0 @@
.MACPACK generic
.autoimport
.import _enable_irq
.import _map
.export irq_int, nmi_int
.export _register_irq
.export _init_interrupts
IRQ_CMD_ADDR = $effc
IRQ_DAT_ADDR = $effd
IRQ_CMD_READIRQ = $00
; void init_interrupts();
; remap the upper page into ram,
; then load the new vector addresses.
.proc _init_interrupts
; map(001f, f);
lda #$1f
jsr pushax
lda #$f
jsr _map
lda #<irq_int
sta $fffe
lda #>irq_int
sta $ffff
lda #<nmi_int
sta $fffa
lda #>nmi_int
sta $fffb
rts
.endproc
.proc nmi_int
rti
.endproc
; irq_int
.proc irq_int
; Load IRQ number
lda #IRQ_CMD_READIRQ
sta IRQ_CMD_ADDR
lda IRQ_DAT_ADDR
; shift by 2 (oh so only 128 interrupts are supported lol)
asl
tax
jmp (irq_table,x)
; use that to index jump table
.endproc
; void register_irq(void* addr, uint8_t irqn);
.proc _register_irq
asl
tax
jsr popa
sta irq_table,x
jsr popa
sta irq_table+1,x
lda #$00
jsr pusha
txa
lsr
jsr _enable_irq
rts
.endproc
.data
; interrupt handler jump table
irq_table: .res 256

View File

@@ -1,11 +0,0 @@
#include <stdint.h>
#include <conio.h>
#include "interrupts/interrupt.h"
#include "devices/uart.h"
void handle_irq() {
}

View File

@@ -1,71 +0,0 @@
#include <conio.h>
#include <string.h>
#include "devices/interrupt_controller.h"
#include "interrupts/interrupt.h"
#include "devices/mapper.h"
#include "devices/rtc.h"
#include "devices/serial.h"
#include "devices/terminal.h"
#include "filesystems/fat32.h"
void handle_rtc_interrupt() {
// cputs("In IRQ interrupt!\n");
// cputc('A');
send_eoi();
asm volatile ("rti");
}
char buf[128];
int main() {
int8_t fd;
size_t nbytes, i;
cputs("Kernel\n");
cputs("Init Mapper\n");
init_mapper();
cputs("Initialize Interrupts\n");
init_interrupts();
cputs("Initialize Interrupt Controller\n");
init_interrupt_controller();
cputs("Initialize RTC\n");
init_rtc();
register_irq(&handle_rtc_interrupt, 0);
rtc_set(0xaaaa, RTC_THRESHOLD);
rtc_set(0xbbbb, RTC_IRQ_THRESHOLD);
asm volatile("cli");
cputs("Initialize Serial\n");
serial_init();
serial_puts("Hello from serial!\n");
fat32_init();
/* This is what is going to be part of open */
fd = fat32_file_open("VERYLA~1TXT");
cprintf("fd: %x\n", fd);
nbytes = fat32_file_read(fd, buf, 23);
for (i = 0; i < nbytes; i++) {
cprintf("%c", buf[i]);
}
while ((nbytes = fat32_file_read(fd, buf, 128))){
for (i = 0; i < nbytes; i++) {
cprintf("%c", buf[i]);
}
}
return 0;
}

View File

@@ -1,48 +0,0 @@
MEMORY
{
ZP: start = $0, size = $100, type = rw, define = yes;
STACK: start = $200, size = $E00, type = rw, define = yes;
KERNEL: start = $1000, size = $7000, type = rw, define = yes, file = %O;
USER: start = $8000, size = $6000, type = rw, define = yes;
IO: start = $E000, size = $1000, type = rw, define = yes;
ROM: start = $f000, size = $1000, type = rw, define = yes; #rw for vectors
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
STARTUP: load = KERNEL, type = ro;
ONCE: load = KERNEL, type = ro, optional = yes;
CODE: load = KERNEL, type = ro;
RODATA: load = KERNEL, type = ro;
DATA: load = KERNEL, type = rw, define = yes;
BSS: load = KERNEL, type = rw, define = yes;
HEAP: load = KERNEL, type = rw, define = yes, optional = yes;
}
FILES
{
%O: format = o65;
}
FORMATS
{
o65: os = super, version = 0, type = small,
export = _init;
}
FEATURES {
CONDES: segment = STARTUP,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = STARTUP,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
}
SYMBOLS {
__STACKSIZE__: value = $0200, type = weak;
__STACKSTART__: type = weak, value = $0800;
}

View File

@@ -1,9 +0,0 @@
#include <process/process.h>
struct pcb fake_pcb;
//TODO
struct pcb* get_pcb_ptr() {
return &fake_pcb;
}

View File

@@ -1,46 +0,0 @@
#ifndef _PROCESS_H
#define _PROCESS_H
#include <stdint.h>
#include <filesystems/fat32.h>
#include <stdio.h>
#define FILE_DESC_SIZE 8
#define IN_USE 1
struct fops {
int8_t (*open)(const char* filename);
int8_t (*close)(int8_t fd);
size_t (*read)(int8_t fd, void* buf, size_t nbytes);
size_t (*write)(int8_t fd, const void* buf, size_t nbytes);
};
struct file_desc {
struct fops* file_ops;
uint8_t fs_type;
union {
struct fat32_directory_entry f32_dentry;
};
uint32_t file_pos;
uint32_t flags;
};
/* Process Control Block struct */
struct pcb {
struct file_desc file_desc_array[FILE_DESC_SIZE];
int32_t is_vidmapped;
uint8_t args[128];
uint16_t execute_return;
uint16_t pid;
uint16_t parent_pid;
uint16_t parent_esp;
};
struct pcb* get_pcb_ptr();
#endif