Arduino Code
This is going to be a long post. It is parts of the Arduino code that runs the flash programmer and bus. SetupLoop.cpp
1 #include "Flash.h"
2 #include "serialIF.h"
3 #include "Interpreter.h"
4 #include "Arduino.h"
5 #include "CPLD.h"
6
7 // Arduino uses 'setup' and 'loop' instead of 'main'
8
9 void setup() {
10
11 pinMode(13, OUTPUT);
12
13 // Blink LED twice
14 digitalWrite(13, HIGH);
15 delay(500);
16 digitalWrite(13, LOW);
17 delay(500);
18 digitalWrite(13, HIGH);
19 delay(500);
20 digitalWrite(13, LOW);
21 }
22
23 void loop() {
24
25 Interpreter interpreter;
26 interpreter.Loop();
27
28 }
SerialIF.h
1 #ifndef INCLUDE_SERIALIF_H
2 #define INCLUDE_SERIALIF_H
3 #include <stdint.h>
4
5 // The SerialIF class provides application level access to communication facilities
6 // c must be:
7 // > command
8 // < response
9 // ! text
10 // $ payload
11 // . ready for payload
12 // Each exchange has an id
13 // packet ID is used for payloads
14 class SerialIF
15 {
16 public:
17 SerialIF();
18 ~SerialIF();
19
20 public:
21 // Basic send. See class doc for 'c'. response is a buffer of up to 256. length is 1-256,
22 bool Send(char c, const uint8_t* response, int16_t length, uint8_t id, uint16_t packetId);
23
24 // Basic send. See class doc for 'c'. buffer is a buffer of 256 bytes. length is 1-256,
25 int16_t Receive(char *pC, uint8_t* buffer, uint8_t* pId, uint16_t *pPacketId);
26 };
27
28 #endif
29
30 </stdint>
SerialIF.cpp
1 #include "SerialIF.h"
2 #include <arduino.h>
3
4 #define HEADER_LENGTH (6)
5 #define TIMEOUT (10000)
6 #define BAUD_RATE (9600)
7
8 ///////////////////////////////////////////////////////////////////////////////
9 //
10 // Object section
11 //
12
13 SerialIF::SerialIF()
14 {
15 Serial.begin(BAUD_RATE);
16 Serial.setTimeout(TIMEOUT);
17 }
18
19 SerialIF::~SerialIF()
20 {
21 Serial.end();
22 }
23
24 ///////////////////////////////////////////////////////////////////////////////
25 //
26 // Low Level Read/Write section
27 //
28
29 // A single communication consists of a header and the data
30 // Header is 6 bytes:
31 // [0] A character:
32 // '>' PC to Arduino command
33 // '<' Arduino to PC response
34 // '!' In progess Arduino -> PC text
35 // '$' Payload packet (256 bytes unless the last one)
36 // '.' OK to send next payload packet
37 // [1] length 1-255, 0 means 256
38 // [2] 8 bit transaction id
39 // [3] sum adjustment. Adjust this so the sum of header and data is 0xff
40 // [4] 2 byte packet # high byte
41 // [5] 2 byte packet # low byte
42 //
43 // The header is hidden from the interface. The user simply used the 'command', 'response',
44 // 'eventString', or 'buffer' and the proper calling function
45 //
46
47 bool SerialIF::Send(char c, const uint8_t* response, int16_t length, uint8_t id, uint16_t packetId)
48 {
49 // Setup up header
50 uint8_t header[HEADER_LENGTH];
51 header[0] = c;
52 header[1] = (uint8_t)length; // 256 converts to 0 in cast
53 header[2] = id;
54 header[3] = 0;
55 header[4] = (byte)(packetId >> 8);
56 header[5] = (byte)packetId;
57
58 // Determine sum for error checking
59 uint8_t sum = 0;
60 for (int16_t i = 0; i < HEADER_LENGTH; i++)
61 {
62 sum += header[i];
63 }
64 for (int16_t i = 0; i < length; i++)
65 {
66 sum += response[i];
67 }
68 header[3] = (uint8_t)~sum;
69
70 // ensure it all gets send
71 const uint8_t* p = header;
72 int len = HEADER_LENGTH;
73 int sent = 0;
74 while (sent < len)
75 {
76 int got = Serial.write(p, len - sent);
77 if (got < 0 || got > len - sent)
78 {
79 digitalWrite(13, HIGH);
80 return false;
81 }
82 sent += got;
83 p += got;
84 }
85 len = length;
86 p = response;
87 sent = 0;
88 while (sent < len)
89 {
90 int got = Serial.write(p, len - sent);
91 if (got < 0 || got > len - sent)
92 {
93 digitalWrite(13, HIGH);
94 return false;
95 }
96 sent += got;
97 p += got;
98 }
99 return true;
100 }
101
102 int16_t SerialIF::Receive(char *pC, uint8_t* buffer, uint8_t* pId, uint16_t *pPacketId)
103 {
104 uint32_t stopOn = millis() + TIMEOUT;
105 int16_t received = 0;
106 int16_t expecting = HEADER_LENGTH;
107 uint8_t header[HEADER_LENGTH];
108 uint8_t* p;
109
110 // Get header
111 p = &header[0];
112 while (millis() < stopOn && received < expecting)
113 {
114 size_t got = Serial.readBytes(p, expecting - received);
115 if (got > (size_t)(expecting - received))
116 {
117 digitalWrite(13, HIGH);
118 return -1;
119 }
120 p += got;
121 received += got;
122 }
123
124 if (received == expecting)
125 {
126 // extract the type character
127 *pC = header[0];
128
129 // get the data size
130 expecting = header[1];
131 if (expecting == 0)
132 {
133 expecting = 256;
134 }
135
136 // get the ID
137 *pId = header[2]; // return to user
138 *pPacketId = (header[4] << 8) | header[5];
139 }
140 else
141 {
142 return -1;
143 }
144
145 // Get the data portion
146 p = buffer;
147 *p = 'x'; // destroy first data
148 received = 0;
149 while (millis() < stopOn && received < expecting)
150 {
151 size_t got = Serial.readBytes(p, expecting - received);
152 if (got > (size_t)(expecting - received))
153 {
154 digitalWrite(13, HIGH);
155 return -1;
156 }
157 received += got;
158 p += got;
159 }
160
161 if (received == expecting)
162 {
163 // ensure the sum is 255
164 uint8_t sum = 0;
165 for (int16_t i = 0; i < HEADER_LENGTH; ++i)
166 {
167 sum += header[i];
168 }
169 for (int16_t i = 0; i < expecting; ++i)
170 {
171 sum += buffer[i];
172 }
173 if (sum != 255)
174 {
175 return -1;
176 }
177 }
178 else
179 {
180 return -1;
181 }
182
183 return received;
184 }
185
186 </arduino>
CPLD.h
1 #ifndef INCLUDE_CPLD_H
2 #define INCLUDE_CPLD_H
3 #include <stdint.h>
4
5 // The CPLD class handles low level access to the CPLD which controls the 39SF020A flash device
6 class CPLD
7 {
8 protected:
9 CPLD();
10
11 // Send CPLD reset sequence
12 void ResetSequence();
13
14 // Update address bits 3:0
15 void UpdateAddress_3_0(uint32_t addr);
16
17 // Update address bits 7:4
18 void UpdateAddress_7_4(uint32_t addr);
19
20 // Update address bits 17:8
21 void UpdateAddress_17_8(uint32_t addr);
22
23 // Update chip control where bits 3-0 are drive, CS*, WR*, and RD*
24 void UpdateChip(int16_t chip);
25
26 // Update the CTRL register that tells which register to pulse data in and out
27 void UpdateCtrl(int16_t ctrl);
28
29 // Swaps a data byte on Din/Dout
30 uint8_t ReadWrite(uint8_t data);
31
32 // Pulse CLK high and low
33 void PulseClk();
34
35 // Pulse nCTRL low and high
36 void PulseCtrl();
37
38 public:
39 // Control pins directly
40 bool DirectWrite(uint16_t mask, uint16_t values);
41
42 // Read current state of pins
43 bool DirectRead(uint16_t mask, uint16_t* pValues);
44
45 private:
46 // Update an arbitrary part of the address bits
47 void UpdateAddress_start_end(uint32_t addr, int16_t startBit, int16_t endBit);
48
49 // Keep track of last control address to know which parts to avoid shifting out
50 int16_t m_lastCtrl;
51
52 public:
53 static const int16_t PIN_nCTRL = 2;
54 static const int16_t PIN_Dout = 3;
55 static const int16_t PIN_Din = 4;
56 static const int16_t PIN_CLK = 5;
57 static const int16_t PIN_ENABLE = 6;
58 };
59
60 #endif
CPLD.cpp
1 #include <arduino.h>
2 #include "CPLD.h"
3
4 // Adds delay if necessary for viewing pins with DMM
5 #define SUPER_SLO_MO()
6
7 #define LAST_CTRL_INIT (-1)
8
9 CPLD::CPLD()
10 {
11 m_lastCtrl = LAST_CTRL_INIT;
12 }
13
14 ///////////////////////////////////////////////////////////////////////////////
15 //
16 // Reset section
17 //
18
19 void CPLD::ResetSequence()
20 {
21 // initialize pins before setting output mode
22 digitalWrite(PIN_ENABLE, HIGH);
23 digitalWrite(PIN_CLK, HIGH);
24 digitalWrite(PIN_nCTRL, HIGH);
25 digitalWrite(PIN_Din, HIGH);
26
27 // set pin modes
28 pinMode(PIN_ENABLE, OUTPUT);
29 pinMode(PIN_nCTRL, OUTPUT);
30 pinMode(PIN_Dout, INPUT);
31 pinMode(PIN_Din, OUTPUT);
32 pinMode(PIN_CLK, OUTPUT);
33
34 // Execute reset sequence
35 PulseClk();
36 PulseClk();
37 digitalWrite(PIN_nCTRL, LOW);
38 delayMicroseconds(1);
39 PulseClk();
40 PulseClk();
41 PulseClk();
42 digitalWrite(PIN_nCTRL, HIGH);
43 digitalWrite(PIN_nCTRL, HIGH);
44 delayMicroseconds(1);
45 SUPER_SLO_MO();
46 digitalWrite(PIN_ENABLE, LOW);
47 delayMicroseconds(1);
48 SUPER_SLO_MO();
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52 //
53 // Address Shift Register section
54 //
55
56 void CPLD::UpdateAddress_3_0(uint32_t addr)
57 {
58 UpdateCtrl(0x01);
59 UpdateAddress_start_end(addr, 3, 0);
60 }
61
62 void CPLD::UpdateAddress_7_4(uint32_t addr)
63 {
64 UpdateCtrl(0x02);
65 UpdateAddress_start_end(addr, 7, 4);
66 }
67
68 void CPLD::UpdateAddress_17_8(uint32_t addr)
69 {
70 UpdateCtrl(0x03);
71 UpdateAddress_start_end(addr, 17, 8);
72 }
73 void CPLD::UpdateAddress_start_end(uint32_t addr, int16_t endBit, int16_t startBit)
74 {
75 int16_t i;
76 for (i = startBit; i <= endBit; ++i)
77 {
78 uint32_t mask = 1L << i;
79 digitalWrite(PIN_Din, (addr & mask) ? HIGH : LOW);
80 digitalWrite(PIN_Din, (addr & mask) ? HIGH : LOW); // delay
81 SUPER_SLO_MO();
82 PulseClk();
83 }
84 }
85
86 // Chip bits are:
87 // 3 drive id not nRD low, or read on rising edge
88 // 2 nCS
89 // 1 nWR
90 // 0 nRD
91 void CPLD::UpdateChip(int16_t chip)
92 {
93 int16_t i;
94 UpdateCtrl(0x07);
95 for (i = 0; i < 4; ++i)
96 {
97 digitalWrite(PIN_Din, (chip & 1) ? HIGH : LOW);
98 digitalWrite(PIN_Din, (chip & 1) ? HIGH : LOW); // delay
99 SUPER_SLO_MO();
100 PulseClk();
101 chip >>= 1;
102 }
103 PulseCtrl();
104 }
105
106 ///////////////////////////////////////////////////////////////////////////////
107 //
108 // CPLD Control section
109 //
110
111 // Control register
112 void CPLD::UpdateCtrl(int16_t ctrl)
113 {
114 int16_t i;
115 digitalWrite(PIN_nCTRL, LOW);
116 SUPER_SLO_MO();
117 if (true || m_lastCtrl != ctrl)
118 {
119 m_lastCtrl = ctrl;
120 for (i = 0; i < 3; ++i)
121 {
122 int16_t bit = ctrl & 1;
123 ctrl = ctrl >> 1;
124 digitalWrite(PIN_Din, bit ? HIGH : LOW);
125 digitalWrite(PIN_Din, bit ? HIGH : LOW); // delay
126 SUPER_SLO_MO();
127 PulseClk();
128 }
129 }
130 else
131 {
132 delayMicroseconds(1);
133 }
134 digitalWrite(PIN_nCTRL, HIGH);
135 SUPER_SLO_MO();
136 }
137
138 // clock exchange 8 bits on 'data'->Din and Dout->return.
139 uint8_t CPLD::ReadWrite(uint8_t data)
140 {
141 int16_t i;
142 uint8_t outData = 0;
143 UpdateCtrl(0x00);
144 for (i = 0; i < 8; ++i)
145 {
146 digitalWrite(PIN_Din, (data & 1) ? HIGH : LOW);
147 digitalWrite(PIN_Din, (data & 1) ? HIGH : LOW); // delay
148 SUPER_SLO_MO();
149 PulseClk();
150 outData >>= 1;
151 if (digitalRead(PIN_Dout) == HIGH)
152 {
153 outData |= 0x80;
154 }
155 data >>= 1;
156 }
157 return outData;
158 }
159
160 // Brings clk high then low
161 void CPLD::PulseClk()
162 {
163 digitalWrite(PIN_CLK, HIGH);
164 digitalWrite(PIN_CLK, HIGH); // delay
165 SUPER_SLO_MO();
166 digitalWrite(PIN_CLK, LOW);
167 digitalWrite(PIN_CLK, LOW); // delay
168 SUPER_SLO_MO();
169 }
170
171 // Brings nCTRL low then high -- Use to strobe bus control
172 void CPLD::PulseCtrl()
173 {
174 digitalWrite(PIN_nCTRL, LOW);
175 digitalWrite(PIN_nCTRL, LOW); // delay
176 SUPER_SLO_MO();
177 digitalWrite(PIN_nCTRL, HIGH);
178 digitalWrite(PIN_nCTRL, HIGH); // delay
179 SUPER_SLO_MO();
180 }
181
182 ///////////////////////////////////////////////////////////////////////////////
183 //
184 // Direct Arduino Pin Access section
185 //
186
187 bool CPLD::DirectWrite(uint16_t mask, uint16_t values)
188 {
189 for (int i = 0; i < 13; i++)
190 {
191 uint16_t bit = 1 << i;
192 if (mask & bit)
193 {
194 digitalWrite(i, (values & bit) ? (HIGH) : (LOW));
195 }
196 }
197 return true;
198 }
199
200 bool CPLD::DirectRead(uint16_t mask, uint16_t* pValues)
201 {
202 *pValues = 0;
203 for (int i = 0; i < 13; i++)
204 {
205 uint16_t bit = 1 << i;
206 if (mask & bit)
207 {
208 if (digitalRead(i))
209 {
210 *pValues |= bit;
211 }
212 }
213 }
214 return true;
215 }
216
217 </arduino>
Bus.h
1 #ifndef INCLUDE_BUS_H
2 #define INCLUDE_BUS_H
3 #include <stdint.h>
4 #include "CPLD.h"
5
6 // The Bus class provides access to the bus on the output of the CPLD
7 class Bus : public CPLD
8 {
9 public:
10 Bus();
11 ~Bus();
12
13 // Sets the input/output pin mode
14 virtual bool EnablePins(bool enable);
15
16 // Resets the Bus
17 virtual bool Reset(bool force);
18
19 // Write data to *ptr.
20 // NOTE: This is a NOT toggle bit operation, just sends data to *ptr
21 // returns true if successful
22 void Write(uint32_t ptr, uint8_t data);
23
24 // Read data at *ptr into *pData
25 // returns true if successful
26 void Read(uint32_t, uint8_t* pData);
27
28 // Read data at last *ptr into *pData
29 // returns true if successful
30 void Read(uint8_t* pData);
31
32 // Updates entire address bus
33 void UpdateAddress(uint32_t addr);
34
35 protected:
36 // Update address bits only on parts that are different
37 void UpdateAddressDiff(uint32_t addr);
38
39 // Pulse RD
40 void PulseRD();
41
42 // Pulse WR
43 void PulseWR();
44
45 private:
46 // Keep track of last programmed address to know which parts to avoid shifting out
47 uint32_t m_lastAddr;
48
49 // Keep track of whether the CPLD has been reset
50 bool m_reset;
51 };
52
53 #endif
Bus.cpp
1 #include <arduino.h>
2 #include "Bus.h"
3
4 #define LAST_ADDR_INIT (0xffffffff)
5
6 Bus::Bus() : CPLD()
7 {
8 m_lastAddr = LAST_ADDR_INIT;
9 m_reset = false;
10 }
11
12 Bus::~Bus()
13 {
14 }
15
16 ///////////////////////////////////////////////////////////////////////////////
17 //
18 // Reset section
19 //
20
21 bool Bus::Reset(bool force)
22 {
23 if (force || !m_reset)
24 {
25 ResetSequence();
26
27 m_lastAddr = LAST_ADDR_INIT;
28 m_reset = true;
29 }
30 return true;
31 }
32
33 bool Bus::EnablePins(bool enable)
34 {
35 if (enable)
36 {
37 pinMode(PIN_ENABLE, OUTPUT);
38 pinMode(PIN_nCTRL, OUTPUT);
39 pinMode(PIN_Dout, INPUT);
40 pinMode(PIN_Din, OUTPUT);
41 pinMode(PIN_CLK, OUTPUT);
42 }
43 else
44 {
45 // TODO when pullups are on board, make all these revert to INPUT
46 pinMode(PIN_ENABLE, INPUT_PULLUP);
47 pinMode(PIN_nCTRL, INPUT_PULLUP);
48 pinMode(PIN_Dout, INPUT);
49 pinMode(PIN_Din, INPUT_PULLUP);
50 pinMode(PIN_CLK, INPUT_PULLUP);
51 }
52 return true;
53 }
54
55
56 ///////////////////////////////////////////////////////////////////////////////
57 //
58 // Basic Operation section
59 //
60
61
62 void Bus::Write(uint32_t addr, uint8_t data)
63 {
64 UpdateAddressDiff(addr);
65 ReadWrite(data);
66 PulseWR();
67 }
68
69 void Bus::Read(uint32_t addr, uint8_t* pData)
70 {
71 UpdateAddressDiff(addr);
72 PulseRD();
73 *pData = ReadWrite(0);
74 }
75
76 void Bus::Read(uint8_t* pData)
77 {
78 PulseRD();
79 *pData = ReadWrite(0);
80 }
81
82 ///////////////////////////////////////////////////////////////////////////////
83 //
84 // Address Shift Register section
85 //
86
87 // Updates entire address bus
88 void Bus::UpdateAddress(uint32_t addr)
89 {
90 UpdateAddress_3_0(addr);
91 UpdateAddress_7_4(addr);
92 UpdateAddress_17_8(addr);
93 }
94
95 // Updates address bus shifting only those shift registers that have changed
96 void Bus::UpdateAddressDiff(uint32_t addr)
97 {
98 if (m_lastAddr == LAST_ADDR_INIT)
99 {
100 UpdateAddress(addr);
101 }
102 else
103 {
104 uint32_t diffs = (uint32_t)(addr ^ m_lastAddr);
105 if (diffs & 0x0000f)
106 {
107 UpdateAddress_3_0(addr);
108 }
109 if (diffs & 0x000f)
110 {
111 UpdateAddress_7_4(addr);
112 }
113 if (diffs & 0x3ff00UL)
114 {
115 UpdateAddress_17_8(addr);
116 }
117 }
118 }
119
120 ///////////////////////////////////////////////////////////////////////////////
121 //
122 // Bus Control Control section
123 //
124
125 // D[7:0] -------------------------
126 // nCS ^^^\_________________/^^^
127 // nRD ^^^\_________________/^^^
128 // nWR ^^^^^^^^^^^^^^^^^^^^^^^^^
129 // read *
130 // Reads when drive goes high (*)
131 void Bus::PulseRD()
132 {
133 UpdateChip(0xa); // CS, RD
134 UpdateChip(0x2); // drive, CS, RD
135 UpdateChip(0xa); // CS, RD
136 UpdateChip(0xf); // done
137 }
138
139 // D[7:0] -[ ]-
140 // nCS ^^^\_________________/^^^
141 // nRD ^^^^^^^^^^^^^^^^^^^^^^^^^
142 // nWR ^^^^^^^\_________/^^^^^^^
143 // Writes when nWR goes low
144 void Bus::PulseWR()
145 {
146 UpdateChip(0x3); // drive, CS
147 UpdateChip(0x1); // drive, CS, WR
148 UpdateChip(0x3); // drive, CS
149 UpdateChip(0xf); // done
150 }
Flash.h
1 #ifndef INCLUDE_FLASH_H
2 #define INCLUDE_FLASH_H
3
4 #include "Bus.h"
5
6 // The Flash class handles application level interface to the flash
7 class Flash
8 {
9 public:
10 Flash(Bus& bus);
11
12 // Resets the CPLD
13 bool ForceReset();
14
15 // Resets the CPLD if it hasn't been reset yet
16 bool Reset();
17
18 // Programs data to *ptr.
19 // NOTE: This is a toggle bit operation
20 // i.e. it puts the flash into byte program mode
21 // and waits for the flash to finish
22 // returns true if successful
23 bool Program(uint32_t addr, uint8_t data);
24
25 // Read data at *ptr into *pData
26 // returns true if successful
27 bool Read(uint32_t addr, uint8_t* pData);
28
29 // Erases 4KB block with addr
30 // NOTE: This is a toggle bit operation
31 // returns true if successful
32 bool EraseSector(uint32_t addr);
33
34 // Erases entire chip
35 // NOTE: This is a toggle bit operation
36 // returns true if successful
37 bool EraseChip();
38
39 protected:
40 // Reads until the toggle bits stop toggling
41 // Returns true if the read data matches expected
42 // Use expected of 0xff for erase operations
43 bool Toggle(uint8_t expected);
44
45 private:
46 // Low level interface
47 Bus m_bus;
48 };
49
50 #endif
Flash.cpp
1 #include <arduino.h>
2 #include "Bus.h"
3 #include "Flash.h"
4
5 Flash::Flash(Bus& bus)
6 {
7 m_bus = bus;
8 }
9
10 ///////////////////////////////////////////////////////////////////////////////
11 //
12 // Byte Access section
13 //
14
15 bool Flash::Program(uint32_t addr, uint8_t data)
16 {
17 m_bus.Write(0x5555, 0xaa);
18 m_bus.Write(0x2aaa, 0x55);
19 m_bus.Write(0x5555, 0xa0);
20 m_bus.Write(addr, data);
21 return Toggle(data);
22 }
23
24 bool Flash::Read(uint32_t addr, uint8_t* pData)
25 {
26 m_bus.Read(addr, pData);
27 return true;
28 }
29
30
31 ///////////////////////////////////////////////////////////////////////////////
32 //
33 // Erase section
34 //
35
36 bool Flash::EraseSector(uint32_t addr)
37 {
38 m_bus.Write(0x5555, 0xaa);
39 m_bus.Write(0x2aaa, 0x55);
40 m_bus.Write(0x5555, 0x80);
41 m_bus.Write(0x5555, 0xaa);
42 m_bus.Write(0x2aaa, 0x55);
43 m_bus.Write(addr, 0x30);
44 return Toggle(0xff);
45 m_bus.Write(0x2aaa, 0xf0);
46 }
47
48 bool Flash::EraseChip()
49 {
50 m_bus.Write(0x5555, 0xaa);
51 m_bus.Write(0x2aaa, 0x55);
52 m_bus.Write(0x5555, 0x80);
53 m_bus.Write(0x5555, 0xaa);
54 m_bus.Write(0x2aaa, 0x55);
55 m_bus.Write(0x5555, 0x10);
56 return Toggle(0xff);
57 }
58
59 ///////////////////////////////////////////////////////////////////////////////
60 //
61 // Reset section
62 //
63
64 bool Flash::Reset()
65 {
66 return m_bus.Reset(false);
67 }
68
69 bool Flash::ForceReset()
70 {
71 return m_bus.Reset(true);
72 }
73
74 ///////////////////////////////////////////////////////////////////////////////
75 //
76 // Support section
77 //
78
79 bool Flash::Toggle(uint8_t expected)
80 {
81 bool toggling = true;
82 uint8_t data0;
83 uint8_t data1;
84 m_bus.Read(&data0);
85 while (toggling)
86 {
87 m_bus.Read(&data1);
88 if ((data1 ^ data0) & 0x40)
89 {
90 // toggle bit toggling
91 data0 = data1; // set up for next toggle check
92 }
93 else
94 {
95 toggling = false;
96 }
97 }
98 return data1 == expected;
99 }
100
101 </arduino>
MCUBus.h
1 #ifndef INCLUDE_MCUBUS_H
2 #define INCLUDE_MCUBUS_H
3 #include <arduino.h>
4 #include "Bus.h"
5
6 // The MCUBus class is used to allow the flash programmer to test the MCU chip before
7 // connecting the CPU and SRAM to the bus.
8 class MCUBus : public Bus
9 {
10 public:
11 MCUBus();
12 ~MCUBus();
13
14 // Sets the input/output pin mode
15 virtual bool EnablePins(bool enable);
16
17 // Resets the Bus
18 virtual bool Reset(bool force);
19
20 // Writes 'data' to 16 bit address 'addr'
21 bool WriteMem(uint16_t addr, uint8_t data);
22
23 // Gets pData from 16 bit address 'addr'
24 bool FetchMem(uint16_t addr, uint8_t *pData);
25
26 // Gets pData from 16 bit address 'addr'
27 bool ReadMem(uint16_t addr, uint8_t *pData);
28
29 // Writes 'data' to io port 'port'
30 bool WriteIO(uint8_t port, uint8_t data);
31
32 // Reads 'data' from io port 'port'
33 bool ReadIO(uint8_t port, uint8_t *pData);
34
35 // Sets the HALT line
36 void HaltLine(bool level);
37
38 // Sets the BUSACK line
39 void BusAckLine(bool level);
40
41 // Sets the IOREQ line
42 void IOReqLine(bool level);
43
44 // Sets the MREQ line
45 void MemReqLine(bool level);
46
47 // Sets the M1 line
48 void M1Line(bool level);
49
50 // Sets the CLK line
51 void Clock(bool level);
52
53 protected:
54 void PulseIORD();
55 void PulseIOWR();
56 void PulseFetch();
57 void PulseMemRD();
58 void PulseMemWR();
59
60 public:
61 static const int PIN_IOREQ = 7;
62 static const int PIN_MREQ = 8;
63 static const int PIN_M1 = 9;
64 static const int PIN_HALT = 10;
65 static const int PIN_BUSACK = 11;
66 static const int PIN_CLOCK = 12;
67 };
68
69 #endif
MCUBus.cpp
1 #include <arduino.h>
2 #include "MCUBus.h"
3
4 //#define SUPER_SLO_MO() delay(1000)
5 #define SUPER_SLO_MO() delay(1)
6 //#define SUPER_SLO_MO()
7
8 MCUBus::MCUBus()
9 {
10 }
11
12 MCUBus::~MCUBus()
13 {
14 }
15
16
17 // Sets the input/output pin mode
18 bool MCUBus::EnablePins(bool enable)
19 {
20 if (enable)
21 {
22 digitalWrite(PIN_HALT, HIGH);
23 digitalWrite(PIN_MREQ, HIGH);
24 digitalWrite(PIN_IOREQ, HIGH);
25 digitalWrite(PIN_M1, HIGH);
26 digitalWrite(PIN_CLOCK, HIGH);
27 digitalWrite(PIN_BUSACK, HIGH);
28
29 pinMode(PIN_HALT, OUTPUT);
30 pinMode(PIN_MREQ, OUTPUT);
31 pinMode(PIN_IOREQ, OUTPUT);
32 pinMode(PIN_M1, OUTPUT);
33 pinMode(PIN_CLOCK, OUTPUT);
34 pinMode(PIN_BUSACK, OUTPUT);
35 }
36 else
37 {
38 // TODO when pullups are on board, make all these revert to INPUT
39 pinMode(PIN_HALT, INPUT_PULLUP);
40 pinMode(PIN_MREQ, INPUT_PULLUP);
41 pinMode(PIN_IOREQ, INPUT_PULLUP);
42 pinMode(PIN_M1, INPUT_PULLUP);
43 pinMode(PIN_CLOCK, INPUT_PULLUP);
44 pinMode(PIN_BUSACK, INPUT_PULLUP);
45 }
46 return Bus::EnablePins(enable);
47 }
48
49 // Resets the Bus
50 bool MCUBus::Reset(bool force)
51 {
52 Clock(HIGH);
53 Clock(LOW);
54 Clock(HIGH);
55 Clock(LOW);
56 Clock(HIGH);
57 Clock(LOW);
58 return Bus::Reset(force);
59 }
60
61
62 bool MCUBus::WriteMem(uint16_t addr, uint8_t data)
63 {
64 UpdateAddressDiff(addr);
65 ReadWrite(data);
66 PulseMemWR();
67 return true;
68 }
69
70 bool MCUBus::FetchMem(uint16_t addr, uint8_t *pData)
71 {
72 UpdateAddressDiff(addr);
73 PulseFetch();
74 *pData = ReadWrite(0);
75 return true;
76 }
77
78 bool MCUBus::ReadMem(uint16_t addr, uint8_t *pData)
79 {
80 UpdateAddressDiff(addr);
81 PulseMemRD();
82 *pData = ReadWrite(0);
83 return true;
84 }
85
86 bool MCUBus::WriteIO(uint8_t port, uint8_t data)
87 {
88 UpdateAddressDiff(port);
89 ReadWrite(data);
90 PulseIOWR();
91 return true;
92 }
93
94 bool MCUBus::ReadIO(uint8_t port, uint8_t *pData)
95 {
96 UpdateAddressDiff(port);
97 PulseIORD();
98 *pData = ReadWrite(0);
99 return true;
100 }
101
102
103 void MCUBus::HaltLine(bool level)
104 {
105 digitalWrite(PIN_HALT, level);
106 }
107
108 void MCUBus::BusAckLine(bool level)
109 {
110 digitalWrite(PIN_BUSACK, level);
111 }
112
113 void MCUBus::IOReqLine(bool level)
114 {
115 digitalWrite(PIN_IOREQ, level);
116 }
117
118 void MCUBus::MemReqLine(bool level)
119 {
120 digitalWrite(PIN_MREQ, level);
121 }
122
123 void MCUBus::M1Line(bool level)
124 {
125 digitalWrite(PIN_M1, level);
126 }
127
128 void MCUBus::Clock(bool level)
129 {
130 digitalWrite(PIN_CLOCK, level);
131 }
132
133 // D[7:0] -------------------------
134 // CLK ^^^^^^\___/^^^^\____/^^^^
135 // nIOREQ ^^^\_________________/^^^
136 // nCS ^^^\_________________/^^^
137 // nRD ^^^\_________________/^^^
138 // nWR ^^^^^^^^^^^^^^^^^^^^^^^^^
139 // read *
140 // Reads when drive goes high (*)
141 void MCUBus::PulseIORD()
142 {
143 Clock(LOW);
144 UpdateChip(0xe); // RD
145 IOReqLine(LOW);
146 SUPER_SLO_MO();
147
148 Clock(HIGH);
149 UpdateChip(0x6); // drive, RD
150 SUPER_SLO_MO();
151
152 Clock(LOW);
153 UpdateChip(0xe); // RD
154 SUPER_SLO_MO();
155
156 Clock(HIGH);
157 SUPER_SLO_MO();
158
159 Clock(LOW);
160 IOReqLine(HIGH);
161 UpdateChip(0xf); // done
162 SUPER_SLO_MO();
163
164 Clock(HIGH);
165 SUPER_SLO_MO();
166
167 }
168 // D[7:0] -[ ]-
169 // CLK ^^^^^^\___/^^^^\____/^^^^
170 // nIOREQ ^^^\_________________/^^^
171 // nCS ^^^\_________________/^^^
172 // nRD ^^^^^^^^^^^^^^^^^^^^^^^^^
173 // nWR ^^^^^^^\_________/^^^^^^^
174 // Writes when nWR goes low
175 void MCUBus::PulseIOWR()
176 {
177 Clock(LOW);
178 UpdateChip(0x7); // drive
179 IOReqLine(LOW);
180 SUPER_SLO_MO();
181
182 Clock(HIGH);
183 UpdateChip(0x5); // drive, WR
184 SUPER_SLO_MO();
185
186 Clock(LOW);
187 UpdateChip(0x7); // drive
188 UpdateChip(0xf); // done
189 SUPER_SLO_MO();
190
191 Clock(HIGH);
192 SUPER_SLO_MO();
193
194 Clock(LOW);
195 IOReqLine(HIGH);
196 SUPER_SLO_MO();
197
198 Clock(HIGH);
199 SUPER_SLO_MO();
200
201 }
202
203 // D[7:0] -------------------------
204 // CLK ^^^^^^\___/^^^^\____/^^^^
205 // nMREQ ^^^\_________________/^^^
206 // nM1 ^^^\_________________/^^^
207 // nCS ^^^\_________________/^^^
208 // nRD ^^^\_________________/^^^
209 // nWR ^^^^^^^^^^^^^^^^^^^^^^^^^
210 // read *
211 // Reads when drive goes high (*)
212 void MCUBus::PulseFetch()
213 {
214 Clock(LOW);
215 M1Line(LOW);
216 UpdateChip(0xe); // RD
217 MemReqLine(LOW);
218 SUPER_SLO_MO();
219
220 Clock(HIGH);
221 UpdateChip(0x6); // drive, RD
222 SUPER_SLO_MO();
223
224 Clock(LOW);
225 UpdateChip(0xe); // RD
226 M1Line(HIGH);
227 SUPER_SLO_MO();
228
229 Clock(HIGH);
230 SUPER_SLO_MO();
231
232 Clock(LOW);
233 MemReqLine(HIGH);
234 UpdateChip(0xf); // done
235 SUPER_SLO_MO();
236
237 Clock(HIGH);
238 SUPER_SLO_MO();
239
240 }
241
242 // D[7:0] -------------------------
243 // CLK ^^^^^^\___/^^^^\____/^^^^
244 // nMREQ ^^^\_________________/^^^
245 // nM1 ^^^^^^^^^^^^^^^^^^^^^^^^^
246 // nCS ^^^\_________________/^^^
247 // nRD ^^^\_________________/^^^
248 // nWR ^^^^^^^^^^^^^^^^^^^^^^^^^
249 // read *
250 // Reads when drive goes high (*)
251 void MCUBus::PulseMemRD()
252 {
253 Clock(LOW);
254 UpdateChip(0xe); // RD
255 MemReqLine(LOW);
256 SUPER_SLO_MO();
257
258 Clock(HIGH);
259 UpdateChip(0x6); // drive, RD
260 SUPER_SLO_MO();
261
262 Clock(LOW);
263 UpdateChip(0xe); // RD
264 SUPER_SLO_MO();
265
266 Clock(HIGH);
267 SUPER_SLO_MO();
268
269 Clock(LOW);
270 MemReqLine(HIGH);
271 UpdateChip(0xf); // done
272 SUPER_SLO_MO();
273
274 Clock(HIGH);
275 SUPER_SLO_MO();
276
277 }
278
279 // D[7:0] -[ ]-
280 // CLK ^^^^^^\___/^^^^\____/^^^^
281 // nMREQ ^^^\_________________/^^^
282 // nCS ^^^\_________________/^^^
283 // nRD ^^^^^^^^^^^^^^^^^^^^^^^^^
284 // nWR ^^^^^^^\_________/^^^^^^^
285 // Writes when nWR goes low
286 void MCUBus::PulseMemWR()
287 {
288 Clock(LOW);
289 UpdateChip(0x7); // drive
290 MemReqLine(LOW);
291 SUPER_SLO_MO();
292
293 Clock(HIGH);
294 UpdateChip(0x5); // drive, WR
295 SUPER_SLO_MO();
296
297 Clock(LOW);
298 UpdateChip(0x7); // drive
299 UpdateChip(0xf); // done
300 SUPER_SLO_MO();
301
302 Clock(HIGH);
303 SUPER_SLO_MO();
304
305 Clock(LOW);
306 MemReqLine(HIGH);
307 SUPER_SLO_MO();
308
309 Clock(HIGH);
310 SUPER_SLO_MO();
311
312 }
Exchanger.h
1 #ifndef INCLUDED_EXCHANGER_H
2 #define INCLUDED_EXCHANGER_H
3
4 #include <arduino.h>
5 #include "SerialIF.h"
6
7 // The exchanger handles communication between the PC and the Arduino
8 class Exchanger {
9 public:
10 Exchanger();
11 ~Exchanger();
12
13 // Expect a command. User supplied buffer. It provides the actual length received. Returns true on success
14 bool WaitForCommand(uint8_t* receiveBuffer256, int* pLengthReceived);
15
16 // Send a response in sendBuffer256. 'lengthToSend' is 1-255 and 0 means 256
17 bool SendResponse(const uint8_t* sendBuffer256, uint8_t lengthToSend);
18
19 // Sends a payload part. packetId is sequential from 0. lengthToSend is 1-255 and 0 means 256
20 bool SendPayload(uint16_t packetId, const uint8_t* sendBuffer256, uint8_t lengthToSend);
21
22 // Waits for a payload part. pLengthReceived is 1-255 and 0 means 256
23 bool WaitForPayload(uint16_t expectedPacketId, uint8_t* receiveBuffer256, uint8_t* pLengthReceived);
24
25 // Sends a ready to indicate ready for the next payload part
26 bool SendReady(uint16_t packetId);
27
28 // Waits for ready to send next packet. buffer is a buffer that can be destroyed
29 bool WaitForReady(uint16_t packetId, uint8_t* buffer);
30
31 // Sends a text string (up to but not including the NUL terminator)
32 bool SendText(const char* text);
33
34 private:
35 SerialIF m_serial;
36 byte m_id;
37 };
38
39 #endif
Exchanger.cpp
1 #include "Exchanger.h"
2
3 Exchanger::Exchanger() : m_serial()
4 {
5 }
6
7 Exchanger::~Exchanger()
8 {
9 }
10
11 ///////////////////////////////////////////////////////////////////////////////
12 //
13 // PC -> Arduiono Receive section
14 //
15
16 bool Exchanger::WaitForCommand(uint8_t* receiveBuffer256, int* pLengthReceived)
17 {
18 bool ok = false;
19 char c;
20 uint16_t packetId;
21 uint16_t length = m_serial.Receive(&c, receiveBuffer256, &m_id, &packetId);
22 if ((c == '>') & (length > 0))
23 {
24 *pLengthReceived = length;
25 ok = true;
26 }
27 return ok;
28 }
29
30 bool Exchanger::WaitForReady(uint16_t expectedPacketId, uint8_t* buffer)
31 {
32 bool ok = false;
33 char c;
34 uint16_t packetId;
35 int recv = m_serial.Receive(&c, buffer, &m_id, &packetId);
36 if (c == '.' && packetId == expectedPacketId && recv == 1)
37 {
38 ok = true;
39 }
40 return ok;
41 }
42
43
44 bool Exchanger::WaitForPayload(uint16_t expectedPacketId, uint8_t* receiveBuffer256, uint8_t* pLengthReceived)
45 {
46 bool ok = false;
47 char c;
48 uint16_t packetId;
49 uint16_t length = m_serial.Receive(&c, receiveBuffer256, &m_id, &packetId);
50 if (c == '$' && length > 0 && packetId == expectedPacketId)
51 {
52 *pLengthReceived = length;
53 ok = true;
54 }
55 return ok;
56 }
57
58
59 ///////////////////////////////////////////////////////////////////////////////
60 //
61 // Arduoino -> PC section
62 //
63
64 bool Exchanger::SendResponse(const uint8_t* sendBuffer256, uint8_t lengthToSend)
65 {
66 return m_serial.Send('<', sendBuffer256, lengthToSend, m_id, 0);
67 }
68
69 bool Exchanger::SendReady(uint16_t packetId)
70 {
71 uint8_t buffer[1];
72 return m_serial.Send('.', buffer, 1, m_id, packetId);
73 }
74
75 bool Exchanger::SendPayload(uint16_t packetId, const uint8_t* sendBuffer256, uint8_t lengthToSend)
76 {
77 int length = lengthToSend;
78 if (length == 0)
79 {
80 length = 256;
81 }
82 bool ok = m_serial.Send('$', sendBuffer256, length, m_id, packetId);
83 return ok;
84 }
85
86 bool Exchanger::SendText(const char* text)
87 {
88 int16_t length = strlen(text);
89 bool ok = m_serial.Send('!', (uint8_t*)text, length, m_id, 0xdead);
90 return ok;
91 }
Interpreter.h
1 #ifndef INCLUDE_INTERPRETER_H
2 #define INCLUDE_INTERPRETER_H
3 #include <stdint.h>
4 #include "MCUBus.h"
5 #include "Flash.h"
6 #include "SerialIF.h"
7 #include "Exchanger.h"
8
9 class Interpreter
10 {
11 public:
12 Interpreter();
13 ~Interpreter();
14
15 // Run the interpreter
16 void Loop();
17
18 // Execute a command
19 bool Execute(const uint8_t* command, int commmandLength, uint8_t* pResponse, int* pResponseLength);
20
21 // Send a diag message up to 100 chars
22 static void DiagnosticText(const char* format, ...);
23
24 protected:
25 bool CRC(uint32_t addr, uint32_t length, uint32_t* pCRC);
26 uint32_t IncrementalCRC(uint32_t crc, uint8_t data);
27
28 private:
29 static Interpreter* m_instance;
30
31 uint16_t m_configuration;
32 uint16_t m_status;
33
34 MCUBus m_bus;
35 SerialIF m_serialIF;
36 Flash m_fp;
37 Exchanger m_exch;
38 uint8_t m_id; // rotating transaction ID
39 };
40
41 #endif
Interpreter.cpp
1 #include <arduino.h>
2 #include <string.h>
3 #include "Interpreter.h"
4 #include "Exchanger.h"
5 #include "Flash.h"
6 #include "CRC32.h"
7 #include "CommandCodeEnum.h"
8 #include "Commands.h"
9 #include "Responses.h"
10
11 #define BLINK_ON_SUCCESS 0
12 #define BLINK_ON_FAILURE 0
13 #define VERBOSE 1
14
15 ///////////////////////////////////////////////////////////////////////////////
16 //
17 // Object section
18 //
19
20 Interpreter::Interpreter() : m_fp(m_bus)
21 {
22 m_status = 0;
23 m_configuration = 0;
24 m_instance = this;
25 }
26
27 Interpreter::~Interpreter()
28 {
29 }
30
31 Interpreter* Interpreter::m_instance;
32
33 void Interpreter::Loop()
34 {
35 uint8_t command[256];
36 uint8_t response[256];
37 while (1)
38 {
39 int receivedLength;
40 int responseLength;
41 if (m_exch.WaitForCommand(command, &receivedLength) > 0)
42 {
43 m_fp.Reset();
44
45 bool ok = Execute(command, receivedLength, response, &responseLength);
46
47 if (ok)
48 {
49 m_exch.SendResponse(response, responseLength);
50 if (BLINK_ON_SUCCESS)
51 {
52 // half second beep bo beep
53 digitalWrite(13, HIGH);
54 delay(200);
55 digitalWrite(13, LOW);
56 delay(100);
57 digitalWrite(13, HIGH);
58 delay(200);
59 digitalWrite(13, LOW);
60 }
61 }
62 else
63 {
64 response[0] = '?';
65 response[1] = 0xde;
66 response[2] = 0xad;
67 response[3] = 0xbe;
68 response[4] = 0xef;
69 m_exch.SendResponse(response, 5);
70 if (BLINK_ON_FAILURE)
71 {
72 // flutter LED
73 for (int16_t i = 0; i < 10; ++i)
74 {
75 digitalWrite(13, HIGH);
76 delay(50);
77 digitalWrite(13, LOW);
78 delay(50);
79 }
80 }
81 }
82 }
83 }
84 }
85
86 void Interpreter::DiagnosticText(const char* format, ...)
87 {
88 #define DIAGNOSTIC_TEXT_SIZE 100
89 char text[DIAGNOSTIC_TEXT_SIZE];
90 va_list ap;
91 va_start(ap, format);
92 vsnprintf(text, DIAGNOSTIC_TEXT_SIZE, format, ap);
93 va_end(ap);
94 m_instance->m_exch.SendText(text);
95 }
96
97 ///////////////////////////////////////////////////////////////////////////////
98 //
99 // Command Dispatch section
100 //
101
102 bool Interpreter::Execute(const uint8_t* command, int commmandLength, uint8_t* pResponse, int* pResponseLength)
103 {
104 bool ok = false;
105
106 switch (command[0])
107 {
108 case NOP:
109 {
110 CmdNOP cmd(command, commmandLength);
111 ok = true;
112 RespNOP resp(cmd, pResponse);
113 resp.SetResult(ok);
114 *pResponseLength = resp.Length();
115 }
116 break;
117 case Status:
118 {
119 CmdStatus cmd(command, commmandLength);
120 ok = true;
121
122 RespStatus resp(cmd, pResponse);
123 uint32_t status = m_configuration;
124 status <<= 16;
125 status |= m_status;
126 resp.SetStatus(status);
127 resp.SetResult(ok);
128 *pResponseLength = resp.Length();
129 }
130 break;
131 case Configure:
132 {
133 CmdConfigure cmd(command, commmandLength);
134 ok = true;
135 m_configuration = (uint16_t)cmd.GetConfig();
136 RespConfigure resp(cmd, pResponse);
137 resp.SetResult(resp.Length());
138 *pResponseLength = resp.Length();
139 }
140 break;
141 case ForceReset:
142 {
143 CmdForceReset cmd(command, commmandLength);
144 ok = m_fp.ForceReset();
145 RespForceReset resp(cmd, pResponse);
146 resp.SetResult(ok);
147 *pResponseLength = resp.Length();
148 }
149 break;
150 case EnablePins:
151 {
152 CmdEnablePins cmd(command, commmandLength);
153 bool enable = cmd.GetEnable();
154 ok = m_bus.EnablePins(enable);
155 RespEnablePins resp(cmd, pResponse);
156 resp.SetResult(ok);
157 *pResponseLength = resp.Length();
158 }
159 break;
160
161 case ReadByte:
162 {
163 CmdReadByte cmd(command, commmandLength);
164 uint8_t data;
165 ok = m_fp.Read(cmd.GetAddress(), &data);
166 RespReadByte resp(cmd, pResponse);
167 resp.SetData(data);
168 resp.SetResult(ok);
169 *pResponseLength = resp.Length();
170 }
171 break;
172 case WriteByte:
173 {
174 CmdWriteByte cmd(command, commmandLength);
175 m_bus.Write(cmd.GetAddress(), cmd.GetData());
176 ok = true;
177 case WriteByte:
178 {
179 CmdWriteByte cmd(command, commmandLength);
180 m_bus.Write(cmd.GetAddress(), cmd.GetData());
181 ok = true;
182 //DiagnosticText("Write byte %05lx <- %02x", cmd.GetAddress(), cmd.GetData());
183 RespWriteByte resp(cmd, pResponse);
184 resp.SetResult(ok);
185 *pResponseLength = resp.Length();
186 }
187 break;
188 case ProgramByte:
189 {
190 CmdProgramByte cmd(command, commmandLength);
191 ok = m_fp.Program(cmd.GetAddress(), cmd.GetData());
192 RespProgramByte resp(cmd, pResponse);
193 resp.SetResult(ok);
194 *pResponseLength = resp.Length();
195 }
196 break;
197
198 case ReadBlock:
199 {
200 CmdReadBlock cmd(command, commmandLength);
201 uint32_t addr = cmd.GetAddress();
202 uint32_t length = cmd.GetLength();
203 uint32_t offset = 0;
204 uint16_t packetId = 0;
205 ok = true;
206
207 while (offset < length && ok)
208 {
209 if (ok)
210 {
211 // wait for ready to send
212 ok = ok && m_exch.WaitForReady(packetId, pResponse);
213
214 // load packet
215 int32_t partLen = length - offset;
216 if (partLen > 256)
217 {
218 partLen = 256;
219 }
220 for (int i = 0; i < partLen; ++i)
221 {
222 uint8_t b;
223 ok = ok && m_fp.Read(addr + offset + i, &b);
224 b = (byte)(addr + offset + i);
225 pResponse[i] = b;
226 }
227
228 // send it out
229 ok = ok && m_exch.SendPayload(packetId, pResponse, partLen);
230
231 // prepare for next packet
232 offset += partLen;
233 packetId++;
234 }
235 }
236 RespReadBlock resp(cmd, pResponse);
237 resp.SetResult(ok);
238 *pResponseLength = resp.Length();
239 }
240 break;
241 case ProgramBlock:
242 {
243 CmdReadBlock cmd(command, commmandLength);
244 uint32_t addr = cmd.GetAddress();
245 uint32_t length = cmd.GetLength();
246 uint32_t offset = 0;
247 uint16_t packetId = 0;
248 uint8_t buffer[256];
249 ok = true;
250 while (offset < length)
251 {
252 if (ok)
253 {
254 uint8_t partLen;
255 ok = ok && m_exch.SendReady(packetId);
256 ok = ok && m_exch.WaitForPayload(packetId, buffer, &partLen);
257 int len = partLen;
258 if (len == 0)
259 {
260 len = 256;
261 }
262
263 // program packet
264 for (int i = 0; i < len; ++i)
265 {
266 uint8_t b = buffer[i];
267 ok = ok && m_fp.Program(addr + offset + i, b);
268 }
269
270 // prepare for next packet
271 offset += len;
272 packetId++;
273 }
274 }
275 RespReadBlock resp(cmd, pResponse);
276 resp.SetResult(ok);
277 *pResponseLength = resp.Length();
278 }
279 break;
280
281 case EraseSector:
282 {
283 CmdEraseSector cmd(command, commmandLength);
284 int sector = cmd.GetSector();
285 int count = cmd.GetCount();
286 ok = sector >= 0 && sector < 64 && count >= 1 && (sector + count) < 64;
287 for (int i = sector; i < sector + count; ++i)
288 {
289 if (ok)
290 {
291 ok = m_fp.EraseSector(sector << 12);
292 }
293 }
294 RespEraseSector resp(cmd, pResponse);
295 resp.SetResult(ok);
296 *pResponseLength = resp.Length();
297 }
298 break;
299 case EraseChip:
300 {
301 CmdEraseChip cmd(command, commmandLength);
302 ok = m_fp.EraseChip();
303 RespEraseChip resp(cmd, pResponse);
304 resp.SetResult(ok);
305 *pResponseLength = resp.Length();
306 }
307 break;
308
309 case VerifyErase:
310 {
311 CmdVerifyErase cmd(command, commmandLength);
312 uint8_t data;
313 uint32_t errorCount = 0;
314 uint32_t addr = cmd.GetAddress();
315 uint32_t length = cmd.GetLength();
316 ok = true;
317 for (uint32_t i = 0; i < length; i++)
318 {
319 ok = ok && m_fp.Read(addr + i, &data);
320 if (data != 0xff)
321 {
322 //DiagnosticText("Error %d at %x", data, addr + i);
323 errorCount++;
324 }
325 }
326 RespVerifyErase resp(cmd, pResponse);
327 resp.SetErrorCount(errorCount);
328 resp.SetResult(ok);
329 *pResponseLength = resp.Length();
330 }
331 break;
332
333 case BlockCRC:
334 {
335 CmdBlockCRC cmd(command, commmandLength);
336 uint8_t data;
337 uint32_t addr = cmd.GetAddress();
338 uint32_t length = cmd.GetLength();
339 uint32_t crc = 0xffffffffUL;
340 ok = true;
341 for (uint32_t i = 0; i < length; i++)
342 {
343 ok = ok && m_fp.Read(addr + length, &data);
344 data = 0xff; // TODO remove after test
345 crc = CRC32::IncrementalCRC(crc, data);
346 }
347 RespBlockCRC resp(cmd, pResponse);
348 resp.SetCRC(crc ^ 0xffffffffUL);
349 resp.SetResult(ok);
350 *pResponseLength = resp.Length();
351 }
352 break;
353
354 case DirectPinRead:
355 {
356 CmdDirectPinRead cmd(command, commmandLength);
357 uint16_t levels;
358 ok = m_bus.DirectRead(cmd.GetMask(), &levels);
359 RespDirectPinRead resp(cmd, pResponse);
360 resp.SetPins(levels);
361 resp.SetResult(ok);
362 *pResponseLength = resp.Length();
363 }
364 break;
365 case DirectPinWrite:
366 {
367 CmdDirectPinWrite cmd(command, commmandLength);
368 ok = m_bus.DirectWrite(cmd.GetMask(), cmd.GetLevels());
369 RespDirectPinWrite resp(cmd, pResponse);
370 resp.SetResult(ok);
371 *pResponseLength = resp.Length();
372 }
373 break;
374 case DirectPinMode:
375 {
376 CmdDirectPinMode cmd(command, commmandLength);
377 uint8_t pin = cmd.GetPin();
378 uint8_t mode = cmd.GetMode();
379 ok = pin < 14 && (mode == INPUT || mode == INPUT_PULLUP || mode == OUTPUT);
380 if (ok)
381 {
382 pinMode(pin, mode);
383 }
384 RespDirectPinMode resp(cmd, pResponse);
385 resp.SetResult(ok);
386 *pResponseLength = resp.Length();
387 }
388 break;
389
390 case ReadMem:
391 {
392 CmdReadMem cmd(command, commmandLength);
393 uint8_t data;
394 ok = m_bus.ReadMem(cmd.GetAddress(), &data);
395 RespReadMem resp(cmd, pResponse);
396 resp.SetData(data);
397 resp.SetResult(ok);
398 *pResponseLength = resp.Length();
399 }
400 break;
401 case FetchMem:
402 {
403 CmdFetchMem cmd(command, commmandLength);
404 uint8_t data;
405 ok = m_bus.FetchMem(cmd.GetAddress(), &data);
406 RespFetchMem resp(cmd, pResponse);
407 resp.SetData(data);
408 resp.SetResult(ok);
409 *pResponseLength = resp.Length();
410 }
411 break;
412 case WriteMem:
413 {
414 CmdWriteMem cmd(command, commmandLength);
415 ok = m_bus.WriteMem(cmd.GetAddress(), cmd.GetData());
416 RespWriteMem resp(cmd, pResponse);
417 resp.SetResult(ok);
418 *pResponseLength = resp.Length();
419 }
420 break;
421 case ReadPort:
422 {
423 CmdReadPort cmd(command, commmandLength);
424 uint8_t data;
425 ok = m_bus.ReadIO(cmd.GetPort(), &data);
426 RespReadPort resp(cmd, pResponse);
427 resp.SetData(data);
428 resp.SetResult(ok);
429 *pResponseLength = resp.Length();
430 }
431 break;
432 case WritePort:
433 {
434 CmdWritePort cmd(command, commmandLength);
435 ok = m_bus.WriteIO(cmd.GetPort(), cmd.GetData());
436 RespWritePort resp(cmd, pResponse);
437 resp.SetResult(ok);
438 *pResponseLength = resp.Length();
439 }
440 break;
441 }
442 return ok;
443 }
444
445
446 <!----->
447 </string>
448 </arduino>
ArgInfo.h
1 #ifndef INCLUDED_ARGINFO_H
2 #define INCLUDED_ARGINFO_H
3 #include <arduino.h>
4 #include "CommandCodeEnum.h"
5
6 struct ArgTypes
7 {
8 CommandCodes code;
9 const char* name;
10 int location;
11 int length;
12 };
13
14 // The ArgInfo class contains the information needed for commands and responses to location
15 // and extract the information in the communication packets
16 class ArgInfo
17 {
18 public:
19 ArgInfo();
20 ~ArgInfo();
21
22 // Gets data from a command
23 bool CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, uint32_t* pData);
24 bool CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, uint16_t* pData);
25 bool CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, uint8_t* pData);
26 bool CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, int* pData);
27 bool CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, bool* pData);
28
29 // Inserts data into a response
30 bool ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, uint32_t data);
31 bool ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, uint16_t data);
32 bool ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, uint8_t data);
33 bool ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, int data);
34 bool ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, bool data);
35
36 // Gets the total length of the command
37 int CommandLength(CommandCodes code);
38
39 // Gets the total length of the response which is the length of the command, the status, and arguments
40 int ResponseLength(CommandCodes code);
41
42 protected:
43 // Gets the location and length of argument #'argNo' for command of 'commandCode'
44 bool GetCommandInfo(CommandCodes code, int argNo, int* pLocation, int* pLength);
45
46 // Gets the location and length of argument #'argNo' for response of 'commandCode'
47 bool GetResponseInfo(CommandCodes code, int argNo, int* pLocation, int* pLength);
48
49 // Gets the actual data at 'location'
50 bool ExtractFrom(const uint8_t* buffer, int location, int length, uint32_t* pData);
51
52 // Inserts the actual data at 'location'
53 bool InsertInto(uint8_t* buffer, int location, int length, uint32_t data);
54
55 // Number of ArgTypes in COMMAND_ARGS
56 static int COMMAND_ARGC;
57
58 // Number of ArgTypes in RESPONSE_ARGS
59 static int RESPONSE_ARGC;
60
61 // Array of info about command arguments
62 static ArgTypes COMMAND_ARGS[];
63
64 // Array of info abaout response arguments
65 static ArgTypes RESPONSE_ARGS[];
66 };
67
68 #endif
69
70 </arduino>
ArgInfo.cpp
1 #include "ArgInfo.h"
2
3
4 #include "Interpreter.h" // TODO for diag
5
6 // locations start at 0. THey will be set in the c'tor
7 ArgTypes ArgInfo::COMMAND_ARGS[] =
8 {
9 { Configure, "Configure", 0, 2 },
10
11 { ReadByte, "Address", 0, 3 },
12
13 { WriteByte, "Address", 0, 3 },
14 { WriteByte, "Data", 0, 1 },
15
16 { ProgramByte, "Address", 0, 3},
17 { ProgramByte, "Data", 0, 1},
18
19 { ReadBlock, "Address", 0, 3},
20 { ReadBlock, "Length", 0, 3},
21
22 { ProgramBlock, "Address", 0, 3},
23 { ProgramBlock, "Length", 0, 3},
24
25 { EraseSector, "Sector", 0, 1},
26 { EraseSector, "Count", 0, 1},
27
28 { VerifyErase, "Address", 0, 3},
29 { VerifyErase, "Length", 0, 3},
30
31 { BlockCRC, "Address", 0, 3},
32 { BlockCRC, "Length", 0, 3},
33
34 { EnablePins, "Pin", 0, 1},
35 { EnablePins, "Mode", 0, 1},
36
37 { DirectPinWrite, "Mask", 0, 2},
38 { DirectPinWrite, "Levels", 0, 2},
39
40 { DirectPinRead, "Mask", 0, 2},
41
42 { ReadMem, "Address", 0, 2},
43
44 { FetchMem, "Address", 0, 2},
45
46 { WriteMem, "Address", 0, 2},
47 { WriteMem, "Data", 0, 1},
48
49 { ReadPort, "Port", 0, 1},
50
51 { WritePort, "Port", 0, 1},
52 { WritePort, "Data", 0, 1},
53 };
54
55 // locations all default to 1. These may not be set in the c'tor
56 ArgTypes ArgInfo::RESPONSE_ARGS[] =
57 {
58 { ReadByte, "Data", 1, 1 },
59 { ReadMem, "Data", 1, 1 },
60 { FetchMem, "Data", 1, 1 },
61 { ReadPort, "Data", 1, 1 },
62
63 { Status, "Status", 1, 4 },
64
65 { VerifyErase, "ErrorCount", 1, 4 },
66
67 { BlockCRC, "CRC", 1, 4 },
68
69 { DirectPinRead, "Levels", 1, 2 },
70 };
71
72 // Gets sizes at compile time
73 int ArgInfo::COMMAND_ARGC = sizeof(COMMAND_ARGS) / sizeof(COMMAND_ARGS[0]);
74 int ArgInfo::RESPONSE_ARGC = sizeof(RESPONSE_ARGS) / sizeof(RESPONSE_ARGS[0]);
75
76 ArgInfo::ArgInfo()
77 {
78 // Figure out locations from sizes
79 CommandCodes lastCommandCode = (CommandCodes)-1;
80 int cumulativeLocation = 1;
81 for (int i = 0; i < COMMAND_ARGC; ++i)
82 {
83 if (COMMAND_ARGS[i].code != lastCommandCode)
84 {
85 // add into response
86 for (int j = 0; j < RESPONSE_ARGC; ++j)
87 {
88 if (RESPONSE_ARGS[j].code == lastCommandCode)
89 {
90 RESPONSE_ARGS[j].location = cumulativeLocation;
91 cumulativeLocation += RESPONSE_ARGS[j].length;
92 }
93 }
94
95 lastCommandCode = COMMAND_ARGS[i].code;
96 cumulativeLocation = 1;
97 }
98 COMMAND_ARGS[i].location = cumulativeLocation;
99 cumulativeLocation += COMMAND_ARGS[i].length;
100 }
101 }
102
103 ArgInfo::~ArgInfo()
104 {
105 }
106
107 int ArgInfo::CommandLength(CommandCodes code)
108 {
109 int cumulativeLength = 1;
110 for (int i = 0; i < COMMAND_ARGC; ++i)
111 {
112 CommandCodes thisCommandCode = COMMAND_ARGS[i].code;
113
114 if (thisCommandCode < code)
115 {
116 }
117 else if (thisCommandCode == code)
118 {
119 cumulativeLength += COMMAND_ARGS[i].length;
120 }
121 else
122 {
123 //break; // not in order--cannot break
124 }
125 }
126 return cumulativeLength;
127 }
128
129 int ArgInfo::ResponseLength(CommandCodes code)
130 {
131 int cumulativeLength = CommandLength(code) + 1; // +1 for result
132 for (int i = 0; i < RESPONSE_ARGC; ++i)
133 {
134 CommandCodes thisCommandCode = RESPONSE_ARGS[i].code;
135
136 if (thisCommandCode < code)
137 {
138 }
139 else if (thisCommandCode == code)
140 {
141 cumulativeLength += RESPONSE_ARGS[i].length;
142 }
143 else
144 {
145 //break; // not in order--cannot break
146 }
147 }
148 return cumulativeLength;
149 }
150
151
152 bool ArgInfo::CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, uint32_t* pData)
153 {
154 int location;
155 int length;
156 uint32_t data32 = 0;
157
158 bool ok = GetCommandInfo(code, argNo, &location, &length);
159
160 if (ok)
161 {
162 ok = ExtractFrom(buffer, location, length, &data32);
163 }
164 if (ok)
165 {
166 *pData = (uint32_t)data32;
167 }
168
169 return ok;
170 }
171
172 bool ArgInfo::CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, uint16_t* pData)
173 {
174 int location;
175 int length;
176 uint32_t data32 = 0;
177
178 bool ok = GetCommandInfo(code, argNo, &location, &length);
179
180 if (ok)
181 {
182 ok = ExtractFrom(buffer, location, length, &data32);
183 }
184 if (ok)
185 {
186 *pData = (uint16_t)data32;
187 }
188
189 return ok;
190 }
191
192 bool ArgInfo::CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, uint8_t* pData)
193 {
194 int location;
195 int length;
196 uint32_t data32 = 0;
197
198 bool ok = GetCommandInfo(code, argNo, &location, &length);
199
200 if (ok)
201 {
202 ok = ExtractFrom(buffer, location, length, &data32);
203 }
204 if (ok)
205 {
206 *pData = (uint8_t)data32;
207 }
208
209 return ok;
210 }
211
212 bool ArgInfo::CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, int* pData)
213 {
214 int location;
215 int length;
216 uint32_t data32 = 0;
217
218 bool ok = GetCommandInfo(code, argNo, &location, &length);
219
220 if (ok)
221 {
222 ok = ExtractFrom(buffer, location, length, &data32);
223 }
224 if (ok)
225 {
226 *pData = (int)data32;
227 }
228
229 return ok;
230 }
231
232 bool ArgInfo::CommandExtract(CommandCodes code, int argNo, const uint8_t* buffer, bool* pData)
233 {
234 int location;
235 int length;
236 uint32_t data32 = 0;
237
238 bool ok = GetCommandInfo(code, argNo, &location, &length);
239
240 if (ok)
241 {
242 ok = ExtractFrom(buffer, location, length, &data32);
243 }
244 if (ok)
245 {
246 *pData = data32 != 0;
247 }
248
249 return ok;
250 }
251
252
253 bool ArgInfo::ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, uint32_t data)
254 {
255 int location;
256 int length;
257 uint32_t data32 = data;
258
259 bool ok = GetResponseInfo(code, argNo, &location, &length);
260 if (ok)
261 {
262 ok = InsertInto(buffer, location, length, data32);
263 }
264 return ok;
265 }
266
267 bool ArgInfo::ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, uint16_t data)
268 {
269 int location;
270 int length;
271 uint32_t data32 = data;
272
273 bool ok = GetResponseInfo(code, argNo, &location, &length);
274 if (ok)
275 {
276 ok = InsertInto(buffer, location, length, data32);
277 }
278 return ok;
279 }
280
281 bool ArgInfo::ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, uint8_t data)
282 {
283 int location;
284 int length;
285 uint32_t data32 = data;
286
287 bool ok = GetResponseInfo(code, argNo, &location, &length);
288 if (ok)
289 {
290 ok = InsertInto(buffer, location, length, data32);
291 }
292 return ok;
293 }
294
295 bool ArgInfo::ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, int data)
296 {
297 int location;
298 int length;
299 uint32_t data32 = data;
300
301 bool ok = GetResponseInfo(code, argNo, &location, &length);
302 if (ok)
303 {
304 ok = InsertInto(buffer, location, length, data32);
305 }
306 return ok;
307 }
308
309 bool ArgInfo::ResponseInsert(CommandCodes code, int argNo, uint8_t* buffer, bool data)
310 {
311 int location;
312 int length;
313 uint32_t data32 = data;
314
315 bool ok = GetResponseInfo(code, argNo, &location, &length);
316 if (ok)
317 {
318 ok = InsertInto(buffer, location, length, data32 ? 1 : 0);
319 }
320 return ok;
321 }
322
323 bool ArgInfo::GetCommandInfo(CommandCodes code, int argNo, int* pLocation, int* pLength)
324 {
325 int i = 0;
326 while (i < COMMAND_ARGC && COMMAND_ARGS[i].code != code)
327 {
328 ++i;
329 }
330 if (i == COMMAND_ARGC)
331 {
332 return false;
333 }
334 int argC = 0;
335 while (i < COMMAND_ARGC && COMMAND_ARGS[i].code == code && argC < argNo)
336 {
337 ++i;
338 ++argC;
339 }
340 if (i == COMMAND_ARGC || COMMAND_ARGS[i].code != code)
341 {
342 return false;
343 }
344 *pLocation = COMMAND_ARGS[i].location;
345 *pLength = COMMAND_ARGS[i].length;
346 return true;
347 }
348
349 bool ArgInfo::GetResponseInfo(CommandCodes code, int argNo, int* pLocation, int* pLength)
350 {
351 int i = 0;
352 while (i < RESPONSE_ARGC && RESPONSE_ARGS[i].code != code)
353 {
354 ++i;
355 }
356 if (i == RESPONSE_ARGC)
357 {
358 return false;
359 }
360 int argC = 0;
361 while (i < RESPONSE_ARGC && RESPONSE_ARGS[i].code == code && argC < argNo)
362 {
363 ++i;
364 ++argC;
365 }
366 if (i == RESPONSE_ARGC || RESPONSE_ARGS[i].code != code)
367 {
368 return false;
369 }
370 *pLocation = RESPONSE_ARGS[i].location;
371 *pLength = RESPONSE_ARGS[i].length;
372 return true;
373 }
374
375 bool ArgInfo::ExtractFrom(const uint8_t* buffer, int location, int length, uint32_t* pData)
376 {
377 bool ok = length <= 4 && location >= 0 && location < 256;
378
379 if (ok)
380 {
381 uint32_t data = 0;
382 for (int i = location; i < location + length; ++i)
383 {
384 data <<= 8;
385 data |= buffer[i];
386 }
387 *pData = data;
388 }
389 return ok;
390 }
391
392 bool ArgInfo::InsertInto(uint8_t* buffer, int location, int length, uint32_t data)
393 {
394 bool ok = length <= 4 && location >= 0 && (location+length) < 256;
395
396 if (ok)
397 {
398 for (int i = location + length - 1; i >= location; --i)
399 {
400 buffer[i] = (uint8_t)data;
401 data >>= 8;
402 }
403 }
404 return ok;
405 }
Commands.h
1 #ifndef INCLUDED_COMMANDS_H
2 #define INCLUDED_COMMANDS_H
3
4 #include <arduino.h>
5 #include "CmdResp.h"
6 #include "ArgInfo.h"
7
8 // Abstract base class for all commands
9 class Command : public CmdResp
10 {
11 public:
12 // Gets the CommandCode for the command
13 CommandCodes Code();
14
15 // Gets the length of the buffer
16 int Length();
17
18 // Gets the buffer
19 const byte* Buffer();
20
21 protected:
22 Command(const byte* buffer, int length);
23
24 const byte* m_buffer;
25 int m_length;
26 //static ArgInfo argInfo;
27 };
28
29 // The rest of these are derived command classes
30
31 class CmdNOP : public Command
32 {
33 public:
34 CmdNOP(const byte* buffer, int length);
35
36 protected:
37 static const CommandCodes MY_CODE = NOP;
38 };
39
40 class CmdStatus : public Command
41 {
42 public:
43 CmdStatus(const byte* buffer, int length);
44
45 protected:
46 static const CommandCodes MY_CODE = Status;
47 };
48
49 class CmdConfigure : public Command
50 {
51 public:
52 CmdConfigure(const byte* buffer, int length);
53
54 uint16_t GetConfig();
55
56 protected:
57 static const CommandCodes MY_CODE = Configure;
58 };
59
60 class CmdForceReset : public Command
61 {
62 public:
63 CmdForceReset(const byte* buffer, int length);
64
65 protected:
66 static const CommandCodes MY_CODE = ForceReset;
67 };
68
69 class CmdEnablePins : public Command
70 {
71 public:
72 CmdEnablePins(const byte* buffer, int length);
73
74 bool GetEnable();
75
76 protected:
77 static const CommandCodes MY_CODE = EnablePins;
78 };
79
80
81 class CmdReadByte : public Command
82 {
83 public:
84 CmdReadByte(const byte* buffer, int length);
85
86 uint32_t GetAddress();
87
88 protected:
89 static const CommandCodes MY_CODE = ReadByte;
90 };
91
92 class CmdWriteByte : public Command
93 {
94 public:
95 CmdWriteByte(const byte* buffer, int length);
96
97 uint32_t GetAddress();
98 uint8_t GetData();
99
100 protected:
101 static const CommandCodes MY_CODE = WriteByte;
102 };
103
104 class CmdProgramByte : public Command
105 {
106 public:
107 CmdProgramByte(const byte* buffer, int length);
108
109 uint32_t GetAddress();
110 uint8_t GetData();
111
112 protected:
113 static const CommandCodes MY_CODE = ProgramByte;
114 };
115
116
117 class CmdReadBlock : public Command
118 {
119 public:
120 CmdReadBlock(const byte* buffer, int length);
121
122 uint32_t GetAddress();
123 uint32_t GetLength();
124
125 protected:
126 static const CommandCodes MY_CODE = ReadBlock;
127 };
128
129 class CmdProgramBlock : public Command
130 {
131 public:
132 CmdProgramBlock(const byte* buffer, int length);
133
134 uint32_t GetAddress();
135 uint32_t GetLength();
136
137 protected:
138 static const CommandCodes MY_CODE = ProgramBlock;
139 };
140
141
142 class CmdEraseSector : public Command
143 {
144 public:
145 CmdEraseSector(const byte* buffer, int length);
146
147 uint8_t GetSector();
148 uint8_t GetCount();
149
150 protected:
151 static const CommandCodes MY_CODE = EraseSector;
152 };
153
154 class CmdEraseChip : public Command
155 {
156 public:
157 CmdEraseChip(const byte* buffer, int length);
158
159 protected:
160 static const CommandCodes MY_CODE = EraseChip;
161 };
162
163 class CmdVerifyErase : public Command
164 {
165 public:
166 CmdVerifyErase(const byte* buffer, int length);
167
168 uint32_t GetAddress();
169 uint32_t GetLength();
170
171 protected:
172 static const CommandCodes MY_CODE = VerifyErase;
173 };
174
175 class CmdBlockCRC : public Command
176 {
177 public:
178 CmdBlockCRC(const byte* buffer, int length);
179
180 uint32_t GetAddress();
181 uint32_t GetLength();
182
183 protected:
184 static const CommandCodes MY_CODE = BlockCRC;
185 };
186
187
188 class CmdDirectPinRead : public Command
189 {
190 public:
191 CmdDirectPinRead(const byte* buffer, int length);
192
193 uint16_t GetMask();
194
195 protected:
196 static const CommandCodes MY_CODE = DirectPinRead;
197 };
198
199 class CmdDirectPinWrite : public Command
200 {
201 public:
202 CmdDirectPinWrite(const byte* buffer, int length);
203
204 uint16_t GetMask();
205 uint16_t GetLevels();
206
207 protected:
208 static const CommandCodes MY_CODE = DirectPinWrite;
209 };
210
211 class CmdDirectPinMode : public Command
212 {
213 public:
214 CmdDirectPinMode(const byte* buffer, int length);
215
216 uint8_t GetPin();
217 uint8_t GetMode();
218
219 protected:
220 static const CommandCodes MY_CODE = DirectPinMode;
221 };
222
223
224 class CmdReadMem : public Command
225 {
226 public:
227 CmdReadMem(const byte* buffer, int length);
228
229 uint16_t GetAddress();
230
231 protected:
232 static const CommandCodes MY_CODE = ReadMem;
233 };
234
235 class CmdFetchMem : public Command
236 {
237 public:
238 CmdFetchMem(const byte* buffer, int length);
239
240 uint16_t GetAddress();
241
242 protected:
243 static const CommandCodes MY_CODE = FetchMem;
244 };
245
246 class CmdWriteMem : public Command
247 {
248 public:
249 CmdWriteMem(const byte* buffer, int length);
250
251 uint16_t GetAddress();
252 uint8_t GetData();
253
254 protected:
255 static const CommandCodes MY_CODE = WriteMem;
256 };
257
258 class CmdReadPort : public Command
259 {
260 public:
261 CmdReadPort(const byte* buffer, int length);
262
263 uint8_t GetPort();
264
265 protected:
266 static const CommandCodes MY_CODE = ReadPort;
267
268 };
269
270 class CmdWritePort : public Command
271 {
272 public:
273 CmdWritePort(const byte* buffer, int length);
274
275 uint8_t GetPort();
276 uint8_t GetData();
277
278 protected:
279 static const CommandCodes MY_CODE = WritePort;
280 };
281
282 #endif
283
284 </arduino>
Commands.cpp
1 #include "Commands.h"
2
3 Command::Command(const byte* buffer, int length) : m_buffer(buffer), m_length(length)
4 {
5 }
6
7 CommandCodes Command::Code()
8 {
9 return (CommandCodes)m_buffer[0];
10 }
11
12 int Command::Length()
13 {
14 return m_length;
15 }
16
17 const byte* Command::Buffer()
18 {
19 return m_buffer;
20 }
21
22 ArgInfo CmdResp::argInfo;
23
24 CmdNOP::CmdNOP(const byte* buffer, int length) : Command(buffer, length) { }
25
26 CmdStatus::CmdStatus(const byte* buffer, int length) : Command(buffer, length) { }
27
28 CmdConfigure::CmdConfigure(const byte* buffer, int length) : Command(buffer, length) { }
29
30 uint16_t CmdConfigure::GetConfig()
31 {
32 uint16_t data;
33 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
34 return data;
35 }
36
37 CmdForceReset::CmdForceReset(const byte* buffer, int length) : Command(buffer, length) { }
38
39 CmdEnablePins::CmdEnablePins(const byte* buffer, int length) : Command(buffer, length) { }
40
41 bool CmdEnablePins::GetEnable()
42 {
43 bool data;
44 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
45 return data;
46 }
47
48 CmdReadByte::CmdReadByte(const byte* buffer, int length) : Command(buffer, length) { }
49
50 uint32_t CmdReadByte::GetAddress()
51 {
52 uint32_t data;
53 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
54 return data;
55 }
56
57 CmdWriteByte::CmdWriteByte(const byte* buffer, int length) : Command(buffer, length) { }
58
59 uint32_t CmdWriteByte::GetAddress()
60 {
61 uint32_t data;
62 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
63 return data;
64 }
65
66 uint8_t CmdWriteByte::GetData()
67 {
68 uint8_t data;
69 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
70 return data;
71 }
72
73
74 CmdProgramByte::CmdProgramByte(const byte* buffer, int length) : Command(buffer, length) { }
75
76 uint32_t CmdProgramByte::GetAddress()
77 {
78 uint32_t data;
79 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
80 return data;
81 }
82
83 uint8_t CmdProgramByte::GetData()
84 {
85 uint8_t data;
86 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
87 return data;
88 }
89
90
91 CmdReadBlock::CmdReadBlock(const byte* buffer, int length) : Command(buffer, length) { }
92
93 uint32_t CmdReadBlock::GetAddress()
94 {
95 uint32_t data;
96 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
97 return data;
98 }
99
100 uint32_t CmdReadBlock::GetLength()
101 {
102 uint32_t data;
103 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
104 return data;
105 }
106
107
108 CmdProgramBlock::CmdProgramBlock(const byte* buffer, int length) : Command(buffer, length) { }
109
110 uint32_t CmdProgramBlock::GetAddress()
111 {
112 uint32_t data;
113 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
114 return data;
115 }
116
117 uint32_t CmdProgramBlock::GetLength()
118 {
119 uint32_t data;
120 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
121 return data;
122 }
123
124 CmdEraseSector::CmdEraseSector(const byte* buffer, int length) : Command(buffer, length) { }
125
126 uint8_t CmdEraseSector::GetSector()
127 {
128 uint8_t data;
129 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
130 return data;
131 }
132
133 uint8_t CmdEraseSector::GetCount()
134 {
135 uint8_t data;
136 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
137 return data;
138 }
139
140 CmdEraseChip::CmdEraseChip(const byte* buffer, int length) : Command(buffer, length) { }
141
142 CmdVerifyErase::CmdVerifyErase(const byte* buffer, int length) : Command(buffer, length) { }
143
144 uint32_t CmdVerifyErase::GetAddress()
145 {
146 uint32_t data;
147 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
148 return data;
149 }
150
151 uint32_t CmdVerifyErase::GetLength()
152 {
153 uint32_t data;
154 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
155 return data;
156 }
157
158 CmdBlockCRC::CmdBlockCRC(const byte* buffer, int length) : Command(buffer, length) { }
159
160 uint32_t CmdBlockCRC::GetAddress()
161 {
162 uint32_t data;
163 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
164 return data;
165 }
166
167 uint32_t CmdBlockCRC::GetLength()
168 {
169 uint32_t data;
170 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
171 return data;
172 }
173
174 CmdDirectPinRead::CmdDirectPinRead(const byte* buffer, int length) : Command(buffer, length) { }
175
176 uint16_t CmdDirectPinRead::GetMask()
177 {
178 uint16_t data;
179 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
180 return data;
181 }
182
183 CmdDirectPinWrite::CmdDirectPinWrite(const byte* buffer, int length) : Command(buffer, length) { }
184
185 uint16_t CmdDirectPinWrite::GetMask()
186 {
187 uint16_t data;
188 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
189 return data;
190 }
191
192 uint16_t CmdDirectPinWrite::GetLevels()
193 {
194 uint16_t data;
195 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
196 return data;
197 }
198
199 CmdDirectPinMode::CmdDirectPinMode(const byte* buffer, int length) : Command(buffer, length) { }
200
201 uint8_t CmdDirectPinMode::GetPin()
202 {
203 uint8_t data;
204 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
205 return data;
206 }
207 uint8_t CmdDirectPinMode::GetMode()
208 {
209 uint8_t data;
210 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
211 return data;
212 }
213
214 CmdReadMem::CmdReadMem(const byte* buffer, int length) : Command(buffer, length) { }
215
216 uint16_t CmdReadMem::GetAddress()
217 {
218 uint16_t data;
219 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
220 return data;
221 }
222
223 CmdFetchMem::CmdFetchMem(const byte* buffer, int length) : Command(buffer, length) { }
224
225 uint16_t CmdFetchMem::GetAddress()
226 {
227 uint16_t data;
228 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
229 return data;
230 }
231
232 CmdWriteMem::CmdWriteMem(const byte* buffer, int length) : Command(buffer, length) { }
233
234 uint16_t CmdWriteMem::GetAddress()
235 {
236 uint16_t data;
237 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
238 return data;
239 }
240 uint8_t CmdWriteMem::GetData()
241 {
242 uint8_t data;
243 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
244 return data;
245 }
246
247 CmdReadPort::CmdReadPort(const byte* buffer, int length) : Command(buffer, length) { }
248
249 uint8_t CmdReadPort::GetPort()
250 {
251 uint8_t data;
252 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
253 return data;
254 }
255
256 CmdWritePort::CmdWritePort(const byte* buffer, int length) : Command(buffer, length) { }
257
258 uint8_t CmdWritePort::GetPort()
259 {
260 uint8_t data;
261 argInfo.CommandExtract(MY_CODE, 0, m_buffer, &data);
262 return data;
263 }
264 uint8_t CmdWritePort::GetData()
265 {
266 uint8_t data;
267 argInfo.CommandExtract(MY_CODE, 1, m_buffer, &data);
268 return data;
269 }
Responses.h
1 #ifndef INCLUDED_RESPONSES_H
2 #define INCLUDED_RESPONSES_H
3
4 #include <arduino.h>
5 #include "Commands.h"
6 #include "CommandCodeEnum.h"
7 #include "CmdResp.h"
8
9 // Abstract base class for all responses
10 class Response : public CmdResp
11 {
12 protected:
13 Response(Command& command, uint8_t* buffer256);
14
15 public:
16 void SetResult(int result);
17 int Length();
18 CommandCodes Code();
19
20 protected:
21 Command& m_command;
22 uint8_t* m_buffer256;
23 //static ArgInfo argInfo;
24 };
25
26 // The rest of these are derived response classes
27
28 class RespNOP : public Response
29 {
30 public:
31 RespNOP(CmdNOP& cmd, uint8_t* buffer256);
32 };
33
34 class RespStatus : public Response
35 {
36 public:
37 RespStatus(CmdStatus& cmd, uint8_t* buffer256);
38
39 bool SetStatus(uint32_t data);
40 };
41
42 class RespConfigure : public Response
43 {
44 public:
45 RespConfigure(CmdConfigure& cmd, uint8_t* buffer256);
46 };
47
48 class RespForceReset : public Response
49 {
50 public:
51 RespForceReset(CmdForceReset& cmd, uint8_t* buffer256);
52 };
53
54 class RespEnablePins : public Response
55 {
56 public:
57 RespEnablePins(CmdEnablePins& cmd, uint8_t* buffer256);
58 };
59
60 class RespReadByte : public Response
61 {
62 public:
63 RespReadByte(CmdReadByte& cmd, uint8_t* buffer256);
64
65 bool SetData(uint8_t data);
66 };
67 class RespWriteByte : public Response
68 {
69 public:
70 RespWriteByte(CmdWriteByte& cmd, uint8_t* buffer256);
71 };
72
73 class RespProgramByte : public Response
74 {
75 public:
76 RespProgramByte(CmdProgramByte& cmd, uint8_t* buffer256);
77 };
78
79 class RespReadBlock : public Response
80 {
81 public:
82 RespReadBlock(CmdReadBlock& cmd, uint8_t* buffer256);
83 };
84
85 class RespProgramBlock : public Response
86 {
87 public:
88 RespProgramBlock(CmdProgramBlock& cmd, uint8_t* buffer256);
89 };
90
91 class RespEraseSector : public Response
92 {
93 public:
94 RespEraseSector(CmdEraseSector& cmd, uint8_t* buffer256);
95 };
96 class RespEraseChip : public Response
97 {
98 public:
99 RespEraseChip(CmdEraseChip& cmd, uint8_t* buffer256);
100 };
101
102 class RespVerifyErase : public Response
103 {
104 public:
105 RespVerifyErase(CmdVerifyErase& cmd, uint8_t* buffer256);
106
107 bool SetErrorCount(uint32_t data);
108 };
109
110 class RespBlockCRC : public Response
111 {
112 public:
113 RespBlockCRC(CmdBlockCRC& cmd, uint8_t* buffer256);
114
115 bool SetCRC(uint32_t crc);
116 };
117
118 class RespDirectPinRead : public Response
119 {
120 public:
121 RespDirectPinRead(CmdDirectPinRead& cmd, uint8_t* buffer256);
122 bool SetPins(uint16_t pins);
123 };
124
125 class RespDirectPinWrite : public Response
126 {
127 public:
128 RespDirectPinWrite(CmdDirectPinWrite& cmd, uint8_t* buffer256);
129 };
130
131 class RespDirectPinMode : public Response
132 {
133 public:
134 RespDirectPinMode(CmdDirectPinMode& cmd, uint8_t* buffer256);
135 };
136
137 class RespReadMem : public Response
138 {
139 public:
140 RespReadMem(CmdReadMem& cmd, uint8_t* buffer256);
141
142 bool SetData(uint8_t data);
143 };
144
145 class RespFetchMem : public Response
146 {
147 public:
148 RespFetchMem(CmdFetchMem& cmd, uint8_t* buffer256);
149
150 bool SetData(uint8_t data);
151 };
152
153 class RespWriteMem : public Response
154 {
155 public:
156 RespWriteMem(CmdWriteMem& cmd, uint8_t* buffer256);
157 };
158
159 class RespReadPort : public Response
160 {
161 public:
162 RespReadPort(CmdReadPort& cmd, uint8_t* buffer256);
163
164 bool SetData(uint8_t data);
165 };
166
167 class RespWritePort : public Response
168 {
169 public:
170 RespWritePort(CmdWritePort& cmd, uint8_t* buffer256);
171 };
172
173
174 #endif
175 </arduino>
Responses.cpp
1 #include "Responses.h"
2
3 Response::Response(Command& command, uint8_t* buffer256) : m_command(command), m_buffer256(buffer256)
4 {
5 memcpy(m_buffer256, m_command.Buffer(), m_command.Length());
6 }
7
8 void Response::SetResult(int result)
9 {
10 int length = Length();
11 m_buffer256[length - 1] = result;
12 }
13
14 int Response::Length()
15 {
16 return argInfo.ResponseLength(m_command.Code());
17 }
18
19 CommandCodes Response::Code()
20 {
21 return m_command.Code();
22 }
23
24 RespNOP::RespNOP(CmdNOP& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
25 RespStatus::RespStatus(CmdStatus& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
26 RespConfigure::RespConfigure(CmdConfigure& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
27 RespForceReset::RespForceReset(CmdForceReset& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
28 RespEnablePins::RespEnablePins(CmdEnablePins& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
29 RespReadByte::RespReadByte(CmdReadByte& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
30 RespWriteByte::RespWriteByte(CmdWriteByte& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
31 RespProgramByte::RespProgramByte(CmdProgramByte& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
32 RespReadBlock::RespReadBlock(CmdReadBlock& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
33 RespProgramBlock::RespProgramBlock(CmdProgramBlock& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
34 RespEraseSector::RespEraseSector(CmdEraseSector& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
35 RespEraseChip::RespEraseChip(CmdEraseChip& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
36 RespVerifyErase::RespVerifyErase(CmdVerifyErase& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
37 RespBlockCRC::RespBlockCRC(CmdBlockCRC& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
38 RespDirectPinRead::RespDirectPinRead(CmdDirectPinRead& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
39 RespDirectPinWrite::RespDirectPinWrite(CmdDirectPinWrite& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
40 RespDirectPinMode::RespDirectPinMode(CmdDirectPinMode& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
41 RespReadMem::RespReadMem(CmdReadMem& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
42 RespFetchMem::RespFetchMem(CmdFetchMem& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
43 RespWriteMem::RespWriteMem(CmdWriteMem& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
44 RespReadPort::RespReadPort(CmdReadPort& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
45 RespWritePort::RespWritePort(CmdWritePort& cmd, uint8_t* buffer256) : Response(cmd, buffer256) {}
46
47 bool RespStatus::SetStatus(uint32_t data)
48 {
49 return argInfo.ResponseInsert(Code(), 0, m_buffer256, data);
50 }
51
52 bool RespReadByte::SetData(uint8_t data)
53 {
54 return argInfo.ResponseInsert(Code(), 0, m_buffer256, data);
55 }
56
57 bool RespReadMem::SetData(uint8_t data)
58 {
59 return argInfo.ResponseInsert(Code(), 0, m_buffer256, data);
60 }
61
62 bool RespFetchMem::SetData(uint8_t data)
63 {
64 return argInfo.ResponseInsert(Code(), 0, m_buffer256, data);
65 }
66
67 bool RespReadPort::SetData(uint8_t data)
68 {
69 return argInfo.ResponseInsert(Code(), 0, m_buffer256, data);
70 }
71
72 bool RespVerifyErase::SetErrorCount(uint32_t data)
73 {
74 return argInfo.ResponseInsert(Code(), 0, m_buffer256, data);
75 }
76
77 bool RespBlockCRC::SetCRC(uint32_t crc)
78 {
79 return argInfo.ResponseInsert(Code(), 0, m_buffer256, crc);
80 }
81
82 bool RespDirectPinRead::SetPins(uint16_t pins)
83 {
84 return argInfo.ResponseInsert(Code(), 0, m_buffer256, pins);
85 }
CmdResp.h
1 #ifndef INCLUDED_CMDRESP_H
2 #define INCLUDED_CMDRESP_H
3
4 #include <arduino.h>
5 #include "ArgInfo.h"
6 class CmdResp
7 {
8 protected:
9 static ArgInfo argInfo;
10 };
11
12 #endif
13
14 </arduino>
CommandCodeEnum.h
1 #ifndef INCLUDED_COMMANDCODEENUM_H
2 #define INCLUDED_COMMANDCODEENUM_H
3
4 enum CommandCodes
5 {
6 NOP = 0x00,
7 Status = 0x01,
8 Configure = 0x02,
9 ForceReset = 0x08,
10 EnablePins = 0x09,
11
12 ReadByte = 0x10,
13 WriteByte = 0x11,
14 ProgramByte = 0x12,
15
16 ReadBlock = 0x20,
17 ProgramBlock = 0x22,
18
19 EraseSector = 0x30,
20 EraseChip = 0x33,
21
22 VerifyErase = 0x40,
23 BlockCRC = 0x41,
24
25 DirectPinRead = 0x80,
26 DirectPinWrite = 0x81,
27 DirectPinMode = 0x82,
28
29 ReadMem = 0x90,
30 FetchMem = 0x91,
31 WriteMem = 0x92,
32 ReadPort = 0x98,
33 WritePort = 0x99
34 };
35
36 #endif