-
Notifications
You must be signed in to change notification settings - Fork 0
/
repl.c
232 lines (195 loc) · 7.6 KB
/
repl.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
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include "pico/stdlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "neopixel.h"
#include "hardware/gpio.h"
#define QTPY_BOOT_PIN 21
// sio base is 0xd0000000
// gpio input offset is 0x00000004
// full register address is 0xd0000004
typedef struct {
long timeStamp;
uint32_t target_address;
uint32_t address_content;
uint32_t write_content;
uint32_t mask_value;
bool isRead;
bool isAddress;
bool isMask;
char addressChars[8];
char contentChars[8];
} ReplStatus;
void render_to_console(ReplStatus status, char inputChars[]) {
// adjust console window height to match 'frame size'
for (uint8_t i=0; i<10; i++) {
printf("\n");
}
printf("Current Register: 0x%08x\n", status.target_address);
printf("Value: 0x%08x\n", status.address_content);
printf("Read Mode?: %d\n", status.isRead);
printf("input: %s \n", inputChars);
printf("write_content: 0x%08x \n", status.write_content);
printf("Mask Value: 0x%08x \n", status.mask_value);
printf("Current Input is Address: %d \n", status.isAddress);
printf("Current Input is Mask: %d \n", status.isMask);
printf("Current timeStamp is: %d \n",status.timeStamp);
}
uint32_t get_register_content(uint32_t address){
volatile uint32_t *register_address;
volatile uint32_t full_register_value;
register_address = (volatile uint32_t *) address;
full_register_value = (uint32_t)*register_address;
return full_register_value;
}
void set_register_content(uint32_t address, uint32_t value, uint32_t mask){
volatile uint32_t *register_address;
volatile uint32_t current_reg_value;
volatile uint32_t value_after_masking;
uint32_t currentBit;
uint32_t currentMaskBit;
uint32_t currentDataBit;
uint32_t finalDataBit;
uint32_t finalWholeData=0;
register_address = (volatile uint32_t *) address; //pointer
current_reg_value = (uint32_t)*register_address; //value
value_after_masking = (*register_address ^ value) & mask;
if(current_reg_value != value){
if(address >= 0xd0000000 && address <= 0xd000017c){//register is SIO register, only 32-bit whole register write allowed
for(int i = 0; i<32; i++){
currentBit = current_reg_value % 2;
currentDataBit = value % 2;
currentMaskBit = mask % 2;
if(currentMaskBit == 1){
finalDataBit = currentDataBit;
}else{
finalDataBit = currentBit;
}
finalWholeData = finalWholeData + pow(2,i)*finalDataBit;
mask= mask/2;
current_reg_value = current_reg_value/2;
value = value/2;
}
*register_address = finalWholeData;
}else{
//hw_xor_bits(register_address, value_after_masking);
//*(io_rw_32 *) hw_xor_alias_untyped((volatile void *) register_address) = value_after_masking;
*(io_rw_32 *) ((void *)(REG_ALIAS_XOR_BITS | (uintptr_t)(register_address))) = value_after_masking;
}
}
}
uint32_t get_uint32_from_string(char charArray[]){
int p = 0;
int power = 7;
uint32_t result = 0x00000000;
uint32_t currentBitNumber = 0x0;
int currentnumber = 0;
while(p < 8){
if(charArray[p]){
if(charArray[p] >= '0' && charArray[p] <= '9'){
currentnumber = (charArray[p] - '0');
}else{
currentnumber = (charArray[p] - 'A') + 10;
}
currentBitNumber = (uint32_t)currentnumber * (pow(0x10, power));
result = result + currentBitNumber;
p++;
power--;
}
}
return result;
}
int main() {
stdio_init_all();
gpio_init(QTPY_BOOT_PIN);
gpio_set_dir(QTPY_BOOT_PIN, 0);
volatile char inputchars[9];
volatile char readOrWrite;
volatile char inputch;
volatile uint32_t register_value;
volatile uint32_t register_address;
int counter = 0;
ReplStatus status;
status.timeStamp = 0;
status.target_address = 0x00000000;
status.address_content = 0x00000000;
status.isRead = true;
status.isAddress = true;
status.isMask = false;
inputchars[8] = '\0';
while (true) {
// keep grabbing data from the console if the array is not full
if(counter < 8){
inputch = getchar_timeout_us(0); // don't block main loop
//mode selection
if(inputch == 'R'|| inputch == 'r'){
status.isRead = true;
}else if (inputch == 'W' || inputch == 'w'){
status.isRead = false;
}else{
// if the input is not the mode control and it is a valid hex number, then save it in the array
if((inputch <='9'&& inputch >='0')|| (inputch >= 'A' && inputch <= 'F')){
inputchars[counter] = inputch;
counter++;
}else{
sleep_ms(10);
}
}
}else{
if(status.isAddress){
// the array is full, get the uin32 address from the char array.
status.target_address = get_uint32_from_string(inputchars);
if(status.target_address %4 !=0){
status.target_address = 0;
}
}else if(status.isMask){
status.mask_value = get_uint32_from_string(inputchars);
}else{
status.write_content = get_uint32_from_string(inputchars);
}
// reset the array
while(counter > 0){
inputchars[counter-1] = ' ';
counter--;
}
// process the input content and save it to the correct place
// if last time it is address, then next step is the mask
if(status.isAddress){
status.isAddress = false;
status.isMask = true;
}else if(status.isMask && status.isRead){// if last time it is mask and mode is reading, next step s address
status.isAddress = true;
status.isMask = false;
}else if(status.isMask && (!status.isRead)){// if last time it is mask and mode is writing, next step is content
status.isAddress = false;
status.isMask = false;
}else if((!status.isAddress)&&(!status.isMask)){// if last time it is content, next step is address
status.isAddress = true;
status.isMask = false;
}else{
status.isAddress = true;
status.isMask = false;
}
// finally, counter is 0, inputchars will be cleared. The data is saved in the status
}
// apply mask
if(status.isRead){
status.address_content = get_register_content(status.target_address);
if(status.mask_value == 0){
status.address_content = 0;
}else if(status.mask_value){
status.address_content = status.address_content&status.mask_value;
}
}else{
if(status.isAddress == true){
set_register_content(status.target_address, status.write_content, status.mask_value);
}
status.address_content = get_register_content(status.target_address);
}
render_to_console(status, inputchars);
sleep_ms(100); // don't DDOS the serial console
status.timeStamp = status.timeStamp + 1;
}
return 0;
}