OXYGENHUB
◆ riscv-1 x16-emulator / src / vera_spi.c
1.7 KiB · C · last changed main: while the CPU waits in WAI, step the machine to its next event at once 14 days ago source blame history raw
1
// Commander X16 Emulator
2
// Copyright (c) 2019 Michael Steil
3
// All rights reserved. License: 2-clause BSD
4
5
#include <stdio.h>
6
#include <stdbool.h>
7
#include "sdcard.h"
8
9
#define SPI_CLOCK_RATE_MHZ 12.5f
10
11
bool ss;
12
bool busy;
13
bool autotx;
14
uint8_t sending_byte, received_byte;
15
float outcounter;
16
17
void
18
vera_spi_init()
19
{
20
	ss = false;
21
	busy = false;
22
	autotx = false;
23
	received_byte = 0xff;
24
}
25
26
void
27
vera_spi_step(int mhz, int clocks)
28
{
29
	if (busy) {
30
		outcounter += (float)clocks * SPI_CLOCK_RATE_MHZ / (float)mhz;
31
		if (outcounter >= 10) { // A value of 9 here is closer to reality, but hardware
32
		                        // can take slightly longer depending on clock-alignment.
33
								// 10 cycles here should be safe and won't succeed in emulation
34
								// while failing on hardware.
35
			busy = false;
36
			if (sdcard_attached) {
37
				received_byte = sdcard_handle(sending_byte);
38
			} else {
39
				received_byte = 0xff;
40
			}
41
		}
42
	}
43
}
44
45
// A byte is on its way: vera_spi_step() is counting clocks toward its end.
46
bool
47
vera_spi_busy(void)
48
{
49
	return busy;
50
}
51
52
uint8_t
53
vera_spi_read(uint8_t reg)
54
{
55
	switch (reg) {
56
		case 0:
57
			if (autotx && ss && !busy) {
58
				// autotx mode will automatically send $FF after each read
59
				sending_byte = 0xff;
60
				busy = true;
61
				outcounter = 0;
62
			}
63
			return received_byte;
64
		case 1:
65
			return busy << 7 | autotx << 2 | ss;
66
	}
67
	return 0;
68
}
69
70
void
71
vera_spi_write(uint8_t reg, uint8_t value)
72
{
73
	switch (reg) {
74
		case 0:
75
			if (ss && !busy) {
76
				sending_byte = value;
77
				busy = true;
78
				outcounter = 0;
79
			}
80
			break;
81
		case 1:
82
			if (ss != (value & 1)) {
83
				ss = value & 1;
84
				if (ss) {
85
					sdcard_select(ss);
86
				}
87
			}
88
			autotx = !!(value & 4);
89
			break;
90
	}
91
}