forked from commanderx16/x16-emulator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spi.c
100 lines (84 loc) · 1.58 KB
/
spi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Commander X16 Emulator
// Copyright (c) 2019 Michael Steil
// All rights reserved. License: 2-clause BSD
#include <stdio.h>
#include <stdbool.h>
#include "spi.h"
#include "sdcard.h"
#include "via.h"
// VIA#2
// PB0 SPICLK
// PB1 SS
// PB2-4 unassigned
// PB5 SD write protect
// PB6 SD detect
// PB7 MOSI
// CB1 SPICLK (=PB0)
// CB2 MISO
static bool initialized;
void
spi_init()
{
initialized = false;
}
void
spi_step()
{
if (!sdcard_file) {
return;
}
uint8_t port = via2_pb_get_out();
bool clk = port & 1;
bool ss = !((port >> 1) & 1);
bool mosi = port >> 7;
static bool last_clk = false;
static bool last_ss;
static int bit_counter = 0;
// only care about rising clock
if (clk == last_clk) {
return;
}
last_clk = clk;
if (clk == 0) {
return;
}
if (ss && !last_ss) {
bit_counter = 0;
sdcard_select();
}
last_ss = ss;
// For initialization, the client has to pull&release CLK 74 times.
// The SD card should be deselected, because it's not actual
// data transmission (we ignore this).
if (!initialized) {
if (clk == 1) {
static int init_counter = 0;
init_counter++;
if (init_counter >= 70) {
sdcard_select();
initialized = true;
}
}
return;
}
// for everything else, the SD card neeeds to be selcted
if (!ss) {
return;
}
// receive byte
static uint8_t inbyte, outbyte;
bool bit = mosi;
inbyte <<= 1;
inbyte |= bit;
// printf("BIT: %d BYTE =$%02x\n", bit, inbyte);
bit_counter++;
if (bit_counter != 8) {
return;
}
bit_counter = 0;
if (initialized) {
outbyte = sdcard_handle(inbyte);
}
// send byte
via2_sr_set(outbyte);
}