@@ -5,11 +5,121 @@ package machine
5
5
6
6
import (
7
7
"device/avr"
8
+ "errors"
8
9
"runtime/interrupt"
9
10
"runtime/volatile"
10
11
"unsafe"
11
12
)
12
13
14
+ // Default size of the EEPROM on ATMega MCUs
15
+ const eepromSize = 1024
16
+
17
+ // EECR bitfield values.
18
+ // The constants provided by the AVR package are not correct, so these are the correct fields instead.
19
+ const (
20
+ eecrEERE = avr .EECR_EERE - 1
21
+ eecrEEPE = avr .EECR_EEPE - 1
22
+ eecrEEMPE = avr .EECR_EEMPE - 2
23
+ eecrEERIE = avr .EECR_EERIE - 5
24
+ eecrEEPM0 = avr .EECR_EEPM0 - 12
25
+ eecrEEPM1 = avr .EECR_EEPM1 - 27
26
+ )
27
+
28
+ // EEPROM on ATMega
29
+ type EEPROM struct {
30
+ }
31
+
32
+ // setAddress sets the address for a given read or write into the MCUs EEARH/L register.
33
+ func (e * EEPROM ) setAddress (addr int64 ) error {
34
+ if addr < 0 || addr > int64 (eepromSize ) {
35
+ return errors .New ("address provided is out of bounds" )
36
+ }
37
+
38
+ avr .EEARH .Set (uint8 (addr >> 8 ))
39
+ avr .EEARL .Set (uint8 (addr & 0xFF ))
40
+
41
+ return nil
42
+ }
43
+
44
+ // WriteAt writes len(data) bytes in the EEPROMs at the provided offset.
45
+ func (e * EEPROM ) WriteAt (data []byte , off int64 ) (int , error ) {
46
+ written := 0
47
+ for i , value := range data {
48
+ if err := e .WriteByteAt (value , off + int64 (i )); err != nil {
49
+ return written , err
50
+ }
51
+ written ++
52
+ }
53
+ return written , nil
54
+ }
55
+
56
+ // WriteByteAt performs the logic to writes a byte into the EEPROM at the given address.
57
+ func (e * EEPROM ) WriteByteAt (value byte , addr int64 ) error {
58
+ notReady := true
59
+ for notReady {
60
+ // Wait for the completion of the previous write (if there is one)
61
+ if ! avr .EECR .HasBits (1 << eecrEEPE ) {
62
+ notReady = false
63
+ }
64
+ }
65
+
66
+ if err := e .setAddress (addr ); err != nil {
67
+ return err
68
+ }
69
+
70
+ avr .EEDR .Set (value )
71
+
72
+ avr .EECR .SetBits (1 << eecrEEMPE )
73
+ avr .EECR .SetBits (1 << eecrEEPE )
74
+
75
+ return nil
76
+ }
77
+
78
+ // ReadAt reads exactly len(buf) into buf at the offset. It will return the amount of bytes copied or an error if one exists.
79
+ // The buffer cannot be empty, and an an error is thrown if fewer bytes are read than the size of the buffer.
80
+ func (e * EEPROM ) ReadAt (buf []byte , off int64 ) (int , error ) {
81
+ if len (buf ) == 0 {
82
+ return 0 , errors .New ("buffer cannot be empty" )
83
+ }
84
+
85
+ size := len (buf )
86
+ read := 0
87
+ for i := 0 ; i < size ; i ++ {
88
+ val , err := e .ReadByteAt (off + int64 (i ))
89
+ if err != nil {
90
+ return read , err
91
+ }
92
+
93
+ buf [i ] = val
94
+
95
+ read ++
96
+ }
97
+
98
+ if read < size {
99
+ return read , errors .New ("fewer bytes read than size of buffer" )
100
+ }
101
+
102
+ return read , nil
103
+ }
104
+
105
+ // ReadByteAt reads and returns the byte at the specified address. An error is returned if there is a failure to read.
106
+ func (e * EEPROM ) ReadByteAt (addr int64 ) (byte , error ) {
107
+ notReady := true
108
+ for notReady {
109
+ if ! avr .EECR .HasBits (1 << eecrEEPE ) {
110
+ notReady = false
111
+ }
112
+ }
113
+
114
+ if err := e .setAddress (addr ); err != nil {
115
+ return byte (0 ), err
116
+ }
117
+
118
+ avr .EECR .SetBits (1 << eecrEERE )
119
+
120
+ return avr .EEDR .Get (), nil
121
+ }
122
+
13
123
// I2C on AVR.
14
124
type I2C struct {
15
125
}
0 commit comments