-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfram.go
191 lines (177 loc) · 3.01 KB
/
fram.go
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package dodosim
import (
"fmt"
"io/ioutil"
)
const (
CLK int = 0
CS int = 1
MOSI int = 6
MISO int = 7
)
const (
WREN uint8 = 0x06
WRDI uint8 = 0x04
RDSR uint8 = 0x05
WRSR uint8 = 0x01
READ uint8 = 0x03
WRITE uint8 = 0x02
RDID uint8 = 0x9F
)
const (
None int = iota
ReadAddr1
ReadAddr2
WriteAddr1
WriteAddr2
Reading
Writing
)
type Fram struct {
Data [0x2000]uint8
Clock bool
Off bool
WaitingMosi bool
ByteIn uint8
ByteOut uint8
Bit uint8
BufferOut []uint8
BufferOutPos int
Address uint16
State int
WriteEnable bool
Flusher func(f *Fram)
}
func (f *Fram) New(fram []byte, flusher func(f *Fram)) {
f.Clock = false
f.Off = true
f.WaitingMosi = false
f.ByteIn = 0
f.ByteOut = 0
f.Bit = 0
f.BufferOut = nil
f.BufferOutPos = 0
f.Address = 0
f.State = None
f.WriteEnable = false
f.Flusher = flusher
for i, v := range fram {
f.Data[i] = v
}
}
func (f *Fram) Flush() {
ioutil.WriteFile("fram.bin", f.Data[:], 0644)
}
func (f *Fram) ReadBit(bit int) bool {
if bit == MISO {
return (f.ByteOut<<f.Bit)&0x80 == 0x80
}
return true
}
func (f *Fram) WriteBit(bit int, val bool) {
switch bit {
case CLK:
if !f.Off {
if val != f.Clock {
f.Clock = val
if f.Clock { // Rising edge of clock
var b uint8 = 0
if f.WaitingMosi {
b = 0x80
}
b = b >> f.Bit
f.ByteIn |= b
} else { // Falling Edge
f.Bit++
if f.Bit == 8 {
f.Bit = 0
t := f.ByteIn
f.ByteIn = 0
f.ByteOut = 0
f.processByte(t)
}
}
}
}
break
case CS:
if val != f.Off {
f.Off = val
if f.Off {
f.State = None
f.Address = 0
}
}
case MOSI:
if !f.Off {
f.WaitingMosi = val
}
}
}
func (f *Fram) processByte(val uint8) {
switch f.State {
case ReadAddr1:
f.Address = uint16(val) << 8
f.State = ReadAddr2
case ReadAddr2:
f.Address |= uint16(val) & 0xFF
f.State = Reading
f.ByteOut = f.Data[f.Address]
f.incAddress()
case WriteAddr1:
f.Address = uint16(val) << 8
f.State = WriteAddr2
case WriteAddr2:
f.Address |= uint16(val) & 0xFF
f.State = Writing
case Reading:
f.ByteOut = f.Data[f.Address]
f.incAddress()
case Writing:
if f.WriteEnable {
f.Data[f.Address] = val
}
f.incAddress()
case None:
if f.BufferOut != nil {
f.ByteOut = f.BufferOut[f.BufferOutPos]
f.BufferOutPos++
if f.BufferOutPos >= len(f.BufferOut) {
f.BufferOut = nil
f.BufferOutPos = 0
}
return
}
switch val {
case 0:
break
case WREN:
f.WriteEnable = true
case WRDI:
f.WriteEnable = false
if f.Flusher != nil {
f.Flusher(f)
}
case READ:
f.State = ReadAddr1
case WRITE:
f.State = WriteAddr1
case RDID:
f.ByteOut = 0x04
f.BufferOut = make([]uint8, 3)
f.BufferOutPos = 0
f.BufferOut[0] = 0x7F
f.BufferOut[1] = 0x03
f.BufferOut[2] = 0x02
default:
fmt.Println("Val: ", val)
panic("Yikes")
}
}
}
func (f *Fram) incAddress() {
f.Address++
if f.Address == 0x2000 {
f.Address = 0
}
}