OXYGENHUB
# bd65c0cc08c7 x16-emulator / src / vera_spi.c
1.5 KiB · C · last changed chore(): initial commit 15 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
uint8_t
46
vera_spi_read(uint8_t reg)
47
{
48
	switch (reg) {
49
		case 0:
50
			if (autotx && ss && !busy) {
51
				// autotx mode will automatically send $FF after each read
52
				sending_byte = 0xff;
53
				busy = true;
54
				outcounter = 0;
55
			}
56
			return received_byte;
57
		case 1:
58
			return busy << 7 | autotx << 2 | ss;
59
	}
60
	return 0;
61
}
62
63
void
64
vera_spi_write(uint8_t reg, uint8_t value)
65
{
66
	switch (reg) {
67
		case 0:
68
			if (ss && !busy) {
69
				sending_byte = value;
70
				busy = true;
71
				outcounter = 0;
72
			}
73
			break;
74
		case 1:
75
			if (ss != (value & 1)) {
76
				ss = value & 1;
77
				if (ss) {
78
					sdcard_select(ss);
79
				}
80
			}
81
			autotx = !!(value & 4);
82
			break;
83
	}
84
}