/* MINIL Machine-Code Monitor David Johnson-Davies - www.technoblogy.com - 19th June 2014 CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ // EEPROM library #include // SPI setup #include #define HARDWARE_SPI 1 // const int LATCH_PIN = 0; // Not used const int DATA_PIN = 1; // data in const int CLOCK_PIN = 2; // shift register clock // Matrix keypad setup const int Matrix = A3; const int Button = A2; const int LED = 0; const int SmallestGap = 28; const int nButtons = 16; int AnalogVals[] = {1023, 679, 639, 587, 558, 505, 477, 446, 407, 367, 322, 263, 202, 170, 130, 93, 0}; int Buttons[] = { -1, 1, 4, 7, 14, 2, 3, 10, 5, 6, 11, 8, 9, 0, 12, 15, 13}; // Seven segment display setup const int Clear_Display = 0x76; const int Decimal_Control = 0x77; const int Cursor_Control = 0x79; const int Brightness_Control = 0x7A; // MINIL setup unsigned int Register[8]; void setup(void) { SPI.begin(); SPI.setDataMode(0); pinMode(Button, INPUT_PULLUP); ClearDisplay(); delay(1000); } // Display colon void ClearDisplay () { SPI.transfer(Brightness_Control); SPI.transfer(255); SPI.transfer(Clear_Display); } // Display a 2 digit hex number void DisplayTwo(int n) { SPI.transfer((n>>4) & 0xFF); SPI.transfer(n & 0x0F); } // Display a four digit hex number void Display(int n) { SPI.transfer(Decimal_Control); SPI.transfer(0); SPI.transfer(Cursor_Control); SPI.transfer(0); int i=16; do { i = i - 4; SPI.transfer((n>>i) & 0x0F); } while (i != 0); } // Display colon void DisplayColon () { SPI.transfer(Decimal_Control); SPI.transfer(0x10); } // Display running void DisplayRunning () { SPI.transfer(Clear_Display); SPI.transfer(Decimal_Control); SPI.transfer(0x0F); } // Display Go void DisplayGo () { SPI.transfer(Cursor_Control); SPI.transfer(0); SPI.transfer(Decimal_Control); SPI.transfer(0x10); SPI.transfer('G'); SPI.transfer('o'); SPI.transfer(' '); SPI.transfer(' '); } // Display Error void DisplayError () { SPI.transfer(Cursor_Control); SPI.transfer(0); SPI.transfer('E'); SPI.transfer('r'); } // Returns the keypad character or -1 if no button pressed char ReadKeypad() { int val; do val = analogRead(Matrix); while (val != analogRead(Matrix)); val = val + SmallestGap/2; for (int i=0; i<=nButtons; i++) { if (val >= AnalogVals[i]) return Buttons[i]; } } // Wait until release keypad key void WaitReleaseKey() { do delay(100); while (ReadKeypad() != -1); } // Read button boolean ReadButton () { return (digitalRead(Button) == LOW); } // Waits until button up, or 1 second boolean LongPress () { long time = millis(); do { delay(100); if (millis()-time > 1000) return true; } while (ReadButton()); return false; } // Reads a specified number of key presses and display them // Returns -1 immediately if button was pressed, or result // Uses long so can return an unsigned int or -1 long GetData (int keys) { long Input = 0; int Nibble; boolean Press; for (int i=0; i> 4) & 0x07; if ((Inst & 0x80) != 0) { // Jump instructions Jump = Inst & 0x3F; if (((Inst & 0x40) == 0) == ZeroFlag) PC = Jump; } else if (Type == 0) { // Load Instruction Register[Reg] = Register[Inst & 0x07]; } else if (Type == 0x08) { // Special Instructions Special = Inst & 0x0F; Value = Register[Reg]; if ((Special == 0x0A) || (Special == 0x0D)) { // Decrement or Add1 and convert to BCD if (Special == 0x0A) Sign = 1; else Sign = -1; Value = Value + Sign; for (int i=0; i<16; i=i+4) { // Binary-coded decimal correction - must be a neater way! if ((Value & (unsigned int)(0xF< (unsigned int)(0x9<>8) & 0x0F)*100 + ((Value>>4) & 0x0F)*10 + (Value & 0x0F); analogWrite(LED,255-Value); } else if (Special == 0x0C) { // Clear Register[Reg] = 0; } else if (Special == 0x0E) { // Display and enter Display(Value); do { Word = GetData(4); if (Word != -1) Register[Reg] = Word; } while (Word != -1); LongPress(); DisplayRunning(); } else { // Invalid special instruction DisplayError(); DisplayTwo(Special); do ; while (!ReadButton()); } } } while (!ReadButton()); } void loop() { unsigned int PC, Value; boolean Command; long Word; char Reg; analogWrite(LED,255); DisplayGo(); do ; while (ReadButton()); Word = GetData(1); WaitReleaseKey(); if (Word <= 7) { Reg = Word; Value = Register[Reg]; // Display register contents Display(Value); do { Word = GetData(4); if (Word != -1) Register[Reg] = Word; } while (Word != -1); } else if (Word == 14) { // * = Data input PC = 0; do { do { Word = EEPROM.read(PC); ClearDisplay(); DisplayColon(); DisplayTwo(PC); DisplayTwo(Word); // Wait for key Word = GetData(2); if (Word != -1) EEPROM.write(PC, Word); } while (Word != -1); Command = LongPress(); PC++; } while (!Command); } else if (Word == 15) { // # = Run Program Run(); } }