dsalzman / HD44780-decoder

Arduino Library for decoding HD44780 protocol. This is useful when you want to extract information from a proprietary system that uses an HD44780 LCD.
MIT License
3 stars 1 forks source link

What Arduino Board are you using? #1

Open Porshe2010 opened 2 years ago

Porshe2010 commented 2 years ago

What Arduino Board are you using?

jatsoca commented 2 years ago

Hi try this code for Arduino 1.

/*

// Control signals Arduino uno uint8_t rs = 3;// D3 uint8_t enable = 2;//D2 Digital Pins With Interrupts uint8_t rw = 4;//D4

// Data lines uint8_t d4 = 8;//B0 uint8_t d5 = 9;//B1 uint8_t d6 = 10;//B2 uint8_t d7 = 11;//B3

void decode(void);

bool gotUpNib = false;

uint8_t lowerNibble; uint8_t upperNibble;

uint8_t command;

int dataPinValues;

char LCD[32] = { 32 };

uint8_t charIndex = 0;

void setup() { Serial.begin(9600); Serial.println("HD44870 Decoder Starting..."); pinMode(rs, INPUT); pinMode(enable, INPUT); pinMode(rw, INPUT); pinMode(d4, INPUT);//_PULLDOWN R10K pinMode(d5, INPUT);//_PULLDOWN R10K pinMode(d6, INPUT);//_PULLDOWN R10K pinMode(d7, INPUT);//_PULLDOWN R10K

attachInterrupt(enable, decode, RISING);

}

void loop() {

// delay(500);
// Serial.println("LCD Screen:");
// for(int i = 0; i < 16; i++){
//      Serial.print(LCD[i]);
// }
// Serial.println();
// for(int j = 16; j < 32; j++){
//      Serial.print(LCD[j]);
// }
// Serial.println();

}

void decode(){ // command received if((PIND & (1<<PD3)) == 0){ //my_var = (PINB & (1<<PB2)) if(gotUpNib == false){ upperNibble = (PINB & 0B00001111); // upperNibble = (PINB & 0B0000000011110000) >> 4; gotUpNib = true; return; }else{ lowerNibble = (PINB & 0B00001111); //lowerNibble = (PINB & 0B0000000011110000) >> 4; command = (upperNibble << 4) | lowerNibble; gotUpNib = false; evalCommand(command); // Serial.println(); // Serial.print("Command: "); // Serial.println(command, HEX); return; } } // print character received if((PIND & (1<<PD3)) == 1){ if(gotUpNib == false){ upperNibble = (PINB & 0B00001111); gotUpNib = true; // Serial.print("upper: "); // Serial.println(upperNibble, BIN); return;

    }
    else{
        lowerNibble = (PINB & 0B00001111);
        gotUpNib = false;
        LCD[charIndex] = (char) (upperNibble << 4 | lowerNibble);
        Serial.print( LCD[charIndex]);
        charIndex = (charIndex + 1) % 31;
        // Serial.print("lower: ");
        // Serial.println(lowerNibble, BIN);
    }

}

}

const uint8_t LCD_CLEAR = 0x01; const uint8_t LCD_CLEAR_MASK = 0xFF;

const uint8_t LCD_SETDDRAMADDR = 0x80; const uint8_t LCD_SETDDRAMADDR_MASK = 0x80;

void evalCommand(uint8_t command){ if((command & LCD_CLEAR_MASK) == LCD_CLEAR){ for(int i = 0; i < 32; i++){LCD[i]=32;} charIndex = 0; return; } if((command & LCD_SETDDRAMADDR_MASK) == LCD_SETDDRAMADDR){ if((command & 0x7f) < 16){ charIndex = (command & 0x7f); }else{ charIndex = (command & 0x7f) - 48; } return; }

}

jatsoca commented 2 years ago

Hello, I have tested the program "LCD1602_sniffer_V0_06.zip" with the arduino nano and it has worked well. I made a small modification so that it does not detect the 8-bit bus. Here are the tests.

[https://forum.arduino.cc/t/lcd-1602-and-similar-databus-sniffer/675769?u=manting]

`//Sniffer LCD

include "Fifo.h"

Fifo queue(50); volatile uint16_t errorCount = 0; // indicates Queue overflows if the queue is not cleared fast enough in the loop()

char sBuff[50]; // for sprintf

enum class State : uint8_t { startUp, getInitSequence, mode4bit, mode8bit };

State state = State::startUp; State oldState; uint32_t stateEnteredAtMs;

// expandedBuf byte 0 is control information ( RS [bit1] and RW [bit0] from the LCD and an error flag [bit7] // expandedBuf byte 1 This is LCD D7 to D0. In 4 bit mode, it is concatenated out of two 4bit nibbles. uint16_t expandedBuf = 0;

void setState(State newState) { // handles state transitions Serial.print(F(">>Setting state to = ")); Serial.println((int)newState); oldState = state; state = newState; stateEnteredAtMs = millis(); }

void readLcdBus() { // ports D and B are put on queue when LCD enable is falling. // called from external interrupt uint16_t buf = PIND; buf <<= 8; buf |= PINB; if (!queue.isfull()) queue.push(buf); else { errorCount++; // queue overflow } }

bool analyse(uint16_t portDB) {

bool expandedBufIsValid = false; // function return value static uint8_t count = 0; // used in 4 bit mode to determine if we are reading the high or low bits.

static bool errorFound = false;

static uint8_t consecutiveInitSequenceCount = 0;

// connection // 8 bit mode only // Lcd - - E RS RW D7 D6 D5 D4 D3 D2 D1 D0 - - - // Arduino pin 0 1 2 3 4 5 6 7 8 9 10 11 12 13 - - // Port D0 D1 D2 D3 D4 D5 D6 D7 B0 B1 B2 B3 B4 B5 B6 B7

// bulk read of ports (copy from function input parameter) uint8_t pinD = (portDB >> 8) & 0xFF; uint8_t pinB = (portDB)&0xFF;

bool functionSet8bit = (pinD & 0b10000000) && !(pinD & 0b01111000) && (pinB & 0b00000001); bool functionSet4bit = (pinD & 0b10000000) && !(pinD & 0b01111000) && !(pinB & 0b00000001);

// process 4 bit data

if (count % 2 == 0) { // first pass expandedBuf = 0;

bitWrite(expandedBuf, 9, bitRead(pinD, 3));  // RS
bitWrite(expandedBuf, 8, bitRead(pinD, 4));  // RW
bitWrite(expandedBuf, 7, bitRead(pinD, 5));  // D7
bitWrite(expandedBuf, 6, bitRead(pinD, 6));  // D6
bitWrite(expandedBuf, 5, bitRead(pinD, 7));  // D5
bitWrite(expandedBuf, 4, bitRead(pinB, 0));  // D4

} else { // second pass bitWrite(expandedBuf, 15, errorFound); bitWrite(expandedBuf, 3, bitRead(pinD, 5)); // D7 (D3) bitWrite(expandedBuf, 2, bitRead(pinD, 6)); // D6 (D2) bitWrite(expandedBuf, 1, bitRead(pinD, 7)); // D5 (D1) bitWrite(expandedBuf, 0, bitRead(pinB, 0)); // D4 (D0)

// second pass complete so release the data
expandedBufIsValid = true;

} count++; return expandedBufIsValid; }

void setup() { Serial.begin(115200); Serial.println("starting sniffer ...");

// setState(State::getInitSequence);

// LCD "E" (arduino pin 2) is the Enable and we use the falling edge attachInterrupt(digitalPinToInterrupt(2), readLcdBus, FALLING); }

void loop() { static uint32_t lastLoopAtMs = 0;

if (millis() - lastLoopAtMs > 3000) { // print out errors occasionally //Serial.print("errorCount= "); //Serial.println(errorCount); //Serial.println(F("Still waiting for data LCD . . . ")); lastLoopAtMs = millis(); }

if (!queue.isempty_locked()) { if (analyse(queue.pop_locked())) { // here if expandedBuf is ready to be read

  static char charBuffer[80] = { ' ' };  // for presenting a stream of characters obtained from the LCD data bus.
  static uint8_t charBufferIndex = 0;
  bool isChar = ((0b00000011 & (expandedBuf >> 8)) == 0b10);  // RS == 1 and R/W = 0 (crude test for a character)

  if (isChar) {
    char prCh;
    uint8_t expBuf = expandedBuf & 0xFF;
    (expBuf >= 0x20 && expBuf < 0x7F) ? prCh = expBuf : prCh = '.';
    snprintf(sBuff, 50, "control  data 0x%02X  0x%02X  \'%c\'", (expandedBuf >> 8) & 0xFF, expandedBuf & 0xFF, prCh);
    if (charBufferIndex + 1 < sizeof(charBuffer)) {
      charBuffer[charBufferIndex++] = prCh;  // just the data part
      charBuffer[charBufferIndex] = 0;       // clean ahead
    }
  } else {
    snprintf(sBuff, 50, "control  data 0x%02X  0x%02X ", (expandedBuf >> 8) & 0xFF, expandedBuf & 0xFF);
    if (charBufferIndex > 0) {
      // dump charBuffer
      Serial.print(">>>>>>>>>");
      Serial.println(charBuffer);
      Serial.println();
      charBufferIndex = 0;
    }
  }
  //Serial.println(sBuff);
}

} } // loop() ` ![ARDIONO NANO](https://user-images.githubusercontent.com/37673938/168170752-cda7a8b2-04d2-48c4-b19b-05a7f4f498 PROGRAM SNIFFER 14.jpeg)