Add arduino skecthes
This commit is contained in:
parent
b2eeaa2785
commit
4d77b77daf
194
arduino/kbd/kbd.ino
Normal file
194
arduino/kbd/kbd.ino
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// keyboard wiring diagram: https://www.minuszerodegrees.net/5150/misc/5150_keyboard_reset.jpg
|
||||||
|
|
||||||
|
constexpr int kClockPin = PC6;
|
||||||
|
constexpr int kDataPin = PC4;
|
||||||
|
|
||||||
|
constexpr int kBitDelayMicros = 100;
|
||||||
|
constexpr int kCodeDelayMicros = 200;
|
||||||
|
constexpr int kKeyDelayMicros = 100;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
Serial.begin(115200);
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
|
||||||
|
pinMode(kClockPin, INPUT);
|
||||||
|
pinMode(kDataPin, INPUT);
|
||||||
|
|
||||||
|
Serial.println("kbd 0.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0. reset
|
||||||
|
// 0.0. clock line will be held low externally for 20 ms
|
||||||
|
// when back up, keyboard needs to clock 0xAA as a response
|
||||||
|
//
|
||||||
|
// 1. operation
|
||||||
|
// 1.0. just directly clock out scan codes of pressed keys
|
||||||
|
|
||||||
|
void sendCode(int code) {
|
||||||
|
Serial.printf("sending code 0x%02x\n", code);
|
||||||
|
// preconditions: clock and data pins are INPUT
|
||||||
|
|
||||||
|
while (digitalRead(kDataPin) == LOW || digitalRead(kClockPin) == LOW) {
|
||||||
|
// wait. we're not allowed to send
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(kDataPin, LOW);
|
||||||
|
digitalWrite(kClockPin, LOW);
|
||||||
|
|
||||||
|
pinMode(kClockPin, OUTPUT);
|
||||||
|
delayMicroseconds(kBitDelayMicros);
|
||||||
|
pinMode(kClockPin, INPUT);
|
||||||
|
// delayMicroseconds(kDelayMicros);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if ((code & (1 << i)) == 0) {
|
||||||
|
// send a 0
|
||||||
|
pinMode(kDataPin, OUTPUT);
|
||||||
|
} // else do nothing, it's already a 1
|
||||||
|
delayMicroseconds(kBitDelayMicros);
|
||||||
|
|
||||||
|
pinMode(kClockPin, OUTPUT);
|
||||||
|
delayMicroseconds(kBitDelayMicros);
|
||||||
|
pinMode(kDataPin, INPUT);
|
||||||
|
pinMode(kClockPin, INPUT);
|
||||||
|
}
|
||||||
|
delayMicroseconds(kCodeDelayMicros);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
kReady,
|
||||||
|
kMaybeReset,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr int kResetDelay = 19;
|
||||||
|
|
||||||
|
State state = State::kReady;
|
||||||
|
int lastclocklow = 0;
|
||||||
|
|
||||||
|
constexpr int kLetterCodes[] = {
|
||||||
|
0x1E, // 'a'
|
||||||
|
0x30,
|
||||||
|
0x2E,
|
||||||
|
0x20,
|
||||||
|
0x12,
|
||||||
|
0x21,
|
||||||
|
0x22,
|
||||||
|
0x23,
|
||||||
|
0x17,
|
||||||
|
0x24,
|
||||||
|
0x25,
|
||||||
|
0x26,
|
||||||
|
0x32,
|
||||||
|
0x31,
|
||||||
|
0x18,
|
||||||
|
0x19,
|
||||||
|
0x10,
|
||||||
|
0x13,
|
||||||
|
0x1F,
|
||||||
|
0x14,
|
||||||
|
0x16,
|
||||||
|
0x2F,
|
||||||
|
0x11,
|
||||||
|
0x2D,
|
||||||
|
0x15,
|
||||||
|
0x2c,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr int kNumberCodes[] = {
|
||||||
|
0x0B, // '0'
|
||||||
|
0x02,
|
||||||
|
0x03,
|
||||||
|
0x04,
|
||||||
|
0x05,
|
||||||
|
0x06,
|
||||||
|
0x07,
|
||||||
|
0x08,
|
||||||
|
0x09,
|
||||||
|
0x0A,
|
||||||
|
};
|
||||||
|
|
||||||
|
void sendNormalCode(int code) {
|
||||||
|
sendCode(code);
|
||||||
|
sendCode(code | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendShiftCode(int code) {
|
||||||
|
sendCode(42); // left shift
|
||||||
|
sendNormalCode(code);
|
||||||
|
sendCode(42 | 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendAsciiChar(int c) {
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
return sendNormalCode(kLetterCodes[c - 'a']);
|
||||||
|
} else if (c >= '0' && c <= '9') {
|
||||||
|
return sendNormalCode(kNumberCodes[c - '0']);
|
||||||
|
} else if (c >= 'A' && c <= 'Z') {
|
||||||
|
return sendShiftCode(kLetterCodes[c - 'A']);
|
||||||
|
}
|
||||||
|
switch (c) {
|
||||||
|
case '-': return sendNormalCode(12);
|
||||||
|
case '=': return sendNormalCode(13);
|
||||||
|
case '[': return sendNormalCode(26);
|
||||||
|
case ']': return sendNormalCode(27);
|
||||||
|
case ';': return sendNormalCode(39);
|
||||||
|
case '\'': return sendNormalCode(40);
|
||||||
|
case ',': return sendNormalCode(51);
|
||||||
|
case '.': return sendNormalCode(52);
|
||||||
|
case '/': return sendNormalCode(53);
|
||||||
|
case ' ': return sendNormalCode(57);
|
||||||
|
case '\n': return sendNormalCode(28);
|
||||||
|
|
||||||
|
case '!': return sendShiftCode(2);
|
||||||
|
case '@': return sendShiftCode(3);
|
||||||
|
case '#': return sendShiftCode(4);
|
||||||
|
case '$': return sendShiftCode(5);
|
||||||
|
case '%': return sendShiftCode(6);
|
||||||
|
case '^': return sendShiftCode(7);
|
||||||
|
case '&': return sendShiftCode(8);
|
||||||
|
case '*': return sendShiftCode(9);
|
||||||
|
case '(': return sendShiftCode(10);
|
||||||
|
case ')': return sendShiftCode(11);
|
||||||
|
case '_': return sendShiftCode(12);
|
||||||
|
case '+': return sendShiftCode(13);
|
||||||
|
|
||||||
|
case '{': return sendShiftCode(26);
|
||||||
|
case '}': return sendShiftCode(27);
|
||||||
|
case ':': return sendShiftCode(39);
|
||||||
|
case '"': return sendShiftCode(40);
|
||||||
|
case '<': return sendShiftCode(51);
|
||||||
|
case '>': return sendShiftCode(52);
|
||||||
|
case '?': return sendShiftCode(53);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
static int led_counter = 0;
|
||||||
|
static int led = HIGH;
|
||||||
|
if (led_counter > 400000) {
|
||||||
|
led_counter = 0;
|
||||||
|
led = (led == HIGH) ? LOW : HIGH;
|
||||||
|
digitalWrite(LED_BUILTIN, led);
|
||||||
|
}
|
||||||
|
led_counter += 1;
|
||||||
|
|
||||||
|
int clockp = digitalRead(kClockPin);
|
||||||
|
if (state == State::kReady && clockp == LOW) {
|
||||||
|
state = State::kMaybeReset;
|
||||||
|
lastclocklow = millis();
|
||||||
|
} else if (state == State::kMaybeReset) {
|
||||||
|
if (clockp == HIGH && millis() - lastclocklow > kResetDelay) {
|
||||||
|
delay(1);
|
||||||
|
state = State::kReady;
|
||||||
|
sendCode(0xaa);
|
||||||
|
Serial.println("Reset!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Serial.available() > 0) {
|
||||||
|
int c = Serial.read();
|
||||||
|
sendAsciiChar(c);
|
||||||
|
//delayMicroseconds(kKeyDelayMicros);
|
||||||
|
}
|
||||||
|
}
|
272
arduino/programmer/programmer.ino
Normal file
272
arduino/programmer/programmer.ino
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
#define LV(x) ((x) ? HIGH : LOW)
|
||||||
|
|
||||||
|
// pinout sorta like this: https://myoldcomputer.nl/Files/Datasheet/2364-Commodore.pdf
|
||||||
|
|
||||||
|
const int kDataPins[] = {
|
||||||
|
PA12,
|
||||||
|
PA11,
|
||||||
|
PB12,
|
||||||
|
PB11,
|
||||||
|
PB2,
|
||||||
|
PB1,
|
||||||
|
PB15,
|
||||||
|
PB14,
|
||||||
|
};
|
||||||
|
|
||||||
|
const int kAddressPins[] = {
|
||||||
|
D15,
|
||||||
|
D14,
|
||||||
|
D12,
|
||||||
|
D11,
|
||||||
|
D10,
|
||||||
|
D9,
|
||||||
|
D8,
|
||||||
|
D7,
|
||||||
|
D6,
|
||||||
|
D5,
|
||||||
|
D4,
|
||||||
|
D3,
|
||||||
|
D2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const int kOutputEnablePin = PC9;
|
||||||
|
const int kWriteEnablePin = PC8;
|
||||||
|
|
||||||
|
void setData(int direction) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
pinMode(kDataPins[i], direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
setData(INPUT);
|
||||||
|
|
||||||
|
for (int i = 0; i < 13; i++) {
|
||||||
|
pinMode(kAddressPins[i], OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(kOutputEnablePin, OUTPUT);
|
||||||
|
digitalWrite(kOutputEnablePin, HIGH);
|
||||||
|
|
||||||
|
pinMode(kWriteEnablePin, OUTPUT);
|
||||||
|
digitalWrite(kWriteEnablePin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
int readData() {
|
||||||
|
int out = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (digitalRead(kDataPins[i]) == HIGH) {
|
||||||
|
out += (1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(int data) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
digitalWrite(kDataPins[i], LV(data & (1 << i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeAddress(int address) {
|
||||||
|
for (int i = 0; i < 13; i++) {
|
||||||
|
digitalWrite(kAddressPins[i], LV(address & (1 << i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int read(int address) {
|
||||||
|
writeAddress(address);
|
||||||
|
delayMicroseconds(1);
|
||||||
|
digitalWrite(kOutputEnablePin, LOW);
|
||||||
|
delayMicroseconds(1);
|
||||||
|
int out = readData();
|
||||||
|
digitalWrite(kOutputEnablePin, HIGH);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(int address, int data) {
|
||||||
|
writeAddress(address);
|
||||||
|
delayMicroseconds(1);
|
||||||
|
digitalWrite(kWriteEnablePin, LOW);
|
||||||
|
writeData(data);
|
||||||
|
delayMicroseconds(1);
|
||||||
|
digitalWrite(kWriteEnablePin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void chiperase() {
|
||||||
|
write(0x5555, 0xaa);
|
||||||
|
write(0x2aaa, 0x55);
|
||||||
|
write(0x5555, 0x80);
|
||||||
|
|
||||||
|
write(0x5555, 0xaa);
|
||||||
|
write(0x2aaa, 0x55);
|
||||||
|
write(0x5555, 0x10);
|
||||||
|
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int kBufferSize = 256;
|
||||||
|
int address = 0;
|
||||||
|
int led_counter = 0;
|
||||||
|
int led = HIGH;
|
||||||
|
char buffer[kBufferSize] = {};
|
||||||
|
int buffer_size = 0;
|
||||||
|
|
||||||
|
const char* kSampleData = "this is a blarg";
|
||||||
|
|
||||||
|
int readnibble(const char c) {
|
||||||
|
if (c >= '0' && c <= '9') return c - '0';
|
||||||
|
if (c >= 'A' && c <= 'F') return 10 + c - 'A';
|
||||||
|
if (c >= 'a' && c <= 'f') return 10 + c - 'a';
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readint8(const char* buffer) {
|
||||||
|
int n1 = readnibble(buffer[0]);
|
||||||
|
int n2 = readnibble(buffer[1]);
|
||||||
|
if (n1 < 0 || n2 < 0) return -1;
|
||||||
|
return (n1 << 4) + n2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readint16(const char* buffer) {
|
||||||
|
int i1 = readint8(buffer);
|
||||||
|
int i2 = readint8(buffer + 2);
|
||||||
|
if (i1 < 0 || i2 < 0) return -1;
|
||||||
|
return (i1 << 8) + i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readpage(const char* buffer, char page[64]) {
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
int b = readint8(&buffer[i*2]);
|
||||||
|
if (b < 0) {
|
||||||
|
Serial.printf("error: wrong hex character %c%c\n", buffer[i*2], buffer[i*2+1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
page[i] = b;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int writepage(int address, const char page[64]) {
|
||||||
|
int start = micros();
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
write(address + i, page[i]);
|
||||||
|
}
|
||||||
|
int end = micros();
|
||||||
|
delay(10);
|
||||||
|
|
||||||
|
return end - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump16(int address) {
|
||||||
|
address = address & 0x1ff0;
|
||||||
|
|
||||||
|
char buff[16];
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
buff[i] = read(address + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("%04x:", address);
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
Serial.printf(" %02x", buff[i]);
|
||||||
|
}
|
||||||
|
Serial.print(" ");
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (buff[i] >= 33 && buff[i] <= 127) {
|
||||||
|
Serial.printf("%c", buff[i]);
|
||||||
|
} else {
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void runcmd(const char* buffer, int size) {
|
||||||
|
int cmd = buffer[0];
|
||||||
|
|
||||||
|
if (size < 1) {
|
||||||
|
dump16(address);
|
||||||
|
address += 16;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == '0') {
|
||||||
|
address = 0;
|
||||||
|
} else if (cmd == 'a') {
|
||||||
|
if (size < 5) {
|
||||||
|
Serial.println("error: incomplete address command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
address = readint16(buffer + 1);
|
||||||
|
} else if (cmd == 'w') {
|
||||||
|
if (size < 1 + 4 + 2) {
|
||||||
|
Serial.println("error: incomplete write command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int address = readint16(buffer + 1);
|
||||||
|
int data = readint8(buffer + 5);
|
||||||
|
setData(OUTPUT);
|
||||||
|
write(address, data);
|
||||||
|
delay(10);
|
||||||
|
setData(INPUT);
|
||||||
|
Serial.printf("wrote data at 0x%04x\n", address);
|
||||||
|
dump16(address & 0x1ff0);
|
||||||
|
} else if (cmd == 'p') {
|
||||||
|
if (size < 1 + 4 + 128) {
|
||||||
|
Serial.println("error: incomplete page command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int address = readint16(buffer + 1) & 0x1fc0;
|
||||||
|
char page[64];
|
||||||
|
if (readpage(buffer + 5, page) != 0) return;
|
||||||
|
setData(OUTPUT);
|
||||||
|
int elapsed = writepage(address, page);
|
||||||
|
setData(INPUT);
|
||||||
|
Serial.printf("wrote page at 0x%04x in %d us\n", address, elapsed);
|
||||||
|
dump16(address);
|
||||||
|
dump16(address + 16);
|
||||||
|
dump16(address + 32);
|
||||||
|
dump16(address + 48);
|
||||||
|
} else if (cmd == 's') {
|
||||||
|
int addr = address & 0x1ff0;
|
||||||
|
Serial.printf("writing sample data to 0x%04x\n", addr);
|
||||||
|
setData(OUTPUT);
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
write(addr + i, kSampleData[i]);
|
||||||
|
}
|
||||||
|
setData(INPUT);
|
||||||
|
} else if (cmd == 'e') {
|
||||||
|
setData(OUTPUT);
|
||||||
|
chiperase();
|
||||||
|
setData(INPUT);
|
||||||
|
Serial.println("chip erased");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (led_counter > 200000) {
|
||||||
|
led_counter = 0;
|
||||||
|
led = (led == HIGH) ? LOW : HIGH;
|
||||||
|
digitalWrite(LED_BUILTIN, led);
|
||||||
|
}
|
||||||
|
led_counter += 1;
|
||||||
|
|
||||||
|
if (Serial.available()) {
|
||||||
|
char c = Serial.read();
|
||||||
|
if (c == '\n') {
|
||||||
|
buffer[buffer_size] = 0;
|
||||||
|
runcmd(buffer, buffer_size);
|
||||||
|
buffer_size = 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
} else {
|
||||||
|
buffer[buffer_size] = c;
|
||||||
|
buffer_size = min(kBufferSize - 1, buffer_size + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
281
arduino/ramcheck/ramcheck.ino
Normal file
281
arduino/ramcheck/ramcheck.ino
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
// See RAM chip pinout here: https://www.digchip.com/datasheets/parts/datasheet/922/MK4116-pdf.php
|
||||||
|
|
||||||
|
const PinName kAddressPins[] = {
|
||||||
|
PA_7,
|
||||||
|
PC_7,
|
||||||
|
PB_6,
|
||||||
|
PB_10,
|
||||||
|
PA_8,
|
||||||
|
PA_9,
|
||||||
|
PB_4,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinName kRasPin = PA_6;
|
||||||
|
const PinName kWritePin = PB_9;
|
||||||
|
const PinName kDinPin = PB_8;
|
||||||
|
const PinName kDoutPin = PA_10;
|
||||||
|
const PinName kCasPin = PB_3;
|
||||||
|
|
||||||
|
void Timer1Isr();
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
pinMode(pinNametoDigitalPin(kAddressPins[i]), OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(pinNametoDigitalPin(kRasPin), OUTPUT);
|
||||||
|
pinMode(pinNametoDigitalPin(kCasPin), OUTPUT);
|
||||||
|
pinMode(pinNametoDigitalPin(kWritePin), OUTPUT);
|
||||||
|
pinMode(pinNametoDigitalPin(kDoutPin), INPUT);
|
||||||
|
pinMode(pinNametoDigitalPin(kDinPin), OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(pinNametoDigitalPin(kRasPin), HIGH);
|
||||||
|
digitalWrite(pinNametoDigitalPin(kCasPin), HIGH);
|
||||||
|
digitalWrite(pinNametoDigitalPin(kWritePin), HIGH);
|
||||||
|
|
||||||
|
// Instantiate HardwareTimer object. Thanks to 'new' instanciation, HardwareTimer is not destructed when setup() function is finished.
|
||||||
|
HardwareTimer *MyTim = new HardwareTimer(TIM1);
|
||||||
|
|
||||||
|
MyTim->setOverflow(1400, MICROSEC_FORMAT);
|
||||||
|
MyTim->attachInterrupt(Timer1Isr);
|
||||||
|
MyTim->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LV(x) ((x) ? HIGH : LOW)
|
||||||
|
|
||||||
|
void writeAddress(int address) {
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
digitalWriteFast(kAddressPins[i], LV(address & (1 << i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int read(int address) {
|
||||||
|
int row = address >> 7;
|
||||||
|
int col = address & 0x7f;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
|
||||||
|
writeAddress(row);
|
||||||
|
digitalWriteFast(kRasPin, LOW);
|
||||||
|
writeAddress(col);
|
||||||
|
digitalWriteFast(kCasPin, LOW);
|
||||||
|
delayMicroseconds(1); // tCAS ish
|
||||||
|
int out = digitalReadFast(kDoutPin);
|
||||||
|
|
||||||
|
digitalWriteFast(kCasPin, HIGH);
|
||||||
|
digitalWriteFast(kRasPin, HIGH);
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(int address, int data) {
|
||||||
|
int row = address >> 7;
|
||||||
|
int col = address & 0x7f;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
|
||||||
|
writeAddress(row);
|
||||||
|
digitalWriteFast(kRasPin, LOW);
|
||||||
|
digitalWriteFast(kWritePin, LOW);
|
||||||
|
digitalWriteFast(kDinPin, LV(data));
|
||||||
|
writeAddress(col);
|
||||||
|
digitalWriteFast(kCasPin, LOW);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) asm volatile(""); // extra delay
|
||||||
|
digitalWriteFast(kWritePin, HIGH);
|
||||||
|
delayMicroseconds(1); // tCAS ish
|
||||||
|
|
||||||
|
digitalWriteFast(kCasPin, HIGH);
|
||||||
|
digitalWriteFast(kRasPin, HIGH);
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void writepage(int address, const uint8_t data[16]) {
|
||||||
|
int row = address >> 7;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
|
||||||
|
writeAddress(row);
|
||||||
|
digitalWriteFast(kRasPin, LOW);
|
||||||
|
for (int col = 0; col < 128; col++) {
|
||||||
|
int b = data[col >> 3] & (1 << (col % 8));
|
||||||
|
digitalWriteFast(kDinPin, LV(b));
|
||||||
|
digitalWriteFast(kWritePin, LOW);
|
||||||
|
writeAddress(col);
|
||||||
|
digitalWriteFast(kCasPin, LOW);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) asm volatile(""); // extra delay
|
||||||
|
digitalWriteFast(kWritePin, HIGH);
|
||||||
|
delayMicroseconds(1); // tCAS ish
|
||||||
|
|
||||||
|
digitalWriteFast(kCasPin, HIGH);
|
||||||
|
}
|
||||||
|
digitalWriteFast(kRasPin, HIGH);
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void readpage(int address, uint8_t data[16]) {
|
||||||
|
int row = address >> 7;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
|
||||||
|
writeAddress(row);
|
||||||
|
digitalWriteFast(kRasPin, LOW);
|
||||||
|
for (int col = 0; col < 128; col++) {
|
||||||
|
uint8_t& out = data[col >> 3];
|
||||||
|
|
||||||
|
writeAddress(col);
|
||||||
|
digitalWriteFast(kCasPin, LOW);
|
||||||
|
delayMicroseconds(1); // tCAS ish
|
||||||
|
int b = digitalReadFast(kDoutPin);
|
||||||
|
out >>= 1;
|
||||||
|
if (b == HIGH) out |= 0x80;
|
||||||
|
digitalWriteFast(kCasPin, HIGH);
|
||||||
|
}
|
||||||
|
digitalWriteFast(kRasPin, HIGH);
|
||||||
|
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
int writeread(int address, int value) {
|
||||||
|
write(address, value);
|
||||||
|
return read(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshrow(int row) {
|
||||||
|
writeAddress(row);
|
||||||
|
digitalWriteFast(kRasPin, LOW);
|
||||||
|
delayMicroseconds(1);
|
||||||
|
digitalWriteFast(kRasPin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void refreshall() {
|
||||||
|
for (int row = 0; row < 128; row++) {
|
||||||
|
refreshrow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer1Isr() {
|
||||||
|
refreshall();
|
||||||
|
}
|
||||||
|
|
||||||
|
int check01(int address) {
|
||||||
|
if (writeread(address, 0) != 0) return -1;
|
||||||
|
if (writeread(address, 1) != 1) return -2;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkrow(int row) {
|
||||||
|
int row_address = row << 7;
|
||||||
|
for (int i = 0; i < 128; i++) {
|
||||||
|
int ret = check01(row_address + i);
|
||||||
|
if (ret != 0) {
|
||||||
|
Serial.printf("failure at 0x%04x: %d\n", row_address + i, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int address = 0x007f;
|
||||||
|
int led_count = 0;
|
||||||
|
int led = 0;
|
||||||
|
char cmd = '\0';
|
||||||
|
|
||||||
|
const int kLedInterval = 1000000;
|
||||||
|
|
||||||
|
const uint8_t kSampleData[16] = {
|
||||||
|
'b', 'l', 'a', 'r', 'g', ',', ' ', 'c',
|
||||||
|
'e', 'c', 'i', ' ', 'e', 's', 't', '!',
|
||||||
|
};
|
||||||
|
|
||||||
|
void dump16(int address) {
|
||||||
|
address &= 0x3f80;
|
||||||
|
uint8_t data[16];
|
||||||
|
readpage(address, data);
|
||||||
|
|
||||||
|
Serial.printf("%04x:", address);
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
Serial.printf(" %02x", data[i]);
|
||||||
|
}
|
||||||
|
Serial.print(" ");
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (data[i] < 33 || data[i] > 126) {
|
||||||
|
Serial.print(".");
|
||||||
|
} else {
|
||||||
|
Serial.printf("%c", data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void filltest() {
|
||||||
|
uint8_t data[16];
|
||||||
|
for (int row = 0; row < 128; row++) {
|
||||||
|
snprintf(reinterpret_cast<char*>(data), 16, "testing row %03d", row);
|
||||||
|
writepage(row << 7, data);
|
||||||
|
}
|
||||||
|
for (int row = 0; row < 128; row++) {
|
||||||
|
readpage(row << 7, data);
|
||||||
|
if (atoi(reinterpret_cast<char*>(&data[12])) != row) {
|
||||||
|
Serial.printf("error in row %d\n", row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.println("fill test ok.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void runcmd(char cmd) {
|
||||||
|
uint8_t dat[16];
|
||||||
|
|
||||||
|
if (cmd == 'p') {
|
||||||
|
writepage(address, kSampleData);
|
||||||
|
dump16(address);
|
||||||
|
} else if (cmd == '\0') {
|
||||||
|
address += 128;
|
||||||
|
dump16(address);
|
||||||
|
} else if (cmd == '0') {
|
||||||
|
address = 0;
|
||||||
|
dump16(address);
|
||||||
|
} else if (cmd == 'f') {
|
||||||
|
filltest();
|
||||||
|
} else if (cmd == 't') {
|
||||||
|
for (int row = 0; row < 128; row++) {
|
||||||
|
Serial.printf("row %d... ", row);
|
||||||
|
int ret = checkrow(row);
|
||||||
|
if (ret != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Serial.println("ok!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
if (led_count > kLedInterval) {
|
||||||
|
digitalWrite(LED_BUILTIN, LV(led % 2));
|
||||||
|
led += 1;
|
||||||
|
led_count = 0;
|
||||||
|
}
|
||||||
|
led_count += 1;
|
||||||
|
|
||||||
|
if (Serial.available()) {
|
||||||
|
char c = Serial.read();
|
||||||
|
if (c == '\n') {
|
||||||
|
runcmd(cmd);
|
||||||
|
cmd = '\0';
|
||||||
|
} else {
|
||||||
|
cmd = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user