Reading from HD44780-based LCDs

Keeping in mind the fact that I do not use the Arduino sketch editor (too crummy for me to work on) and that I code directly in C using some of the wiring extensions.

This is how the LCD struct is declared:

typedef enum _bmode {
      BIT_MODE_4      =4,
      BIT_MODE_8      =8
} bmode;

typedef struct _LCD {
      int datapin[8];
      int rs_pin;
      int rw_pin;
      int enable_pin;
      bmode bitmode;
} LCD;

This implementation is how I'd get data from the LCD.

Since the LCD has only 8 data channels, an 8 bit integer (char type) is enough to hold the data. This is the same implementation I had written a while back and that fails (corrupts the LCD screen display).

#include <inttypes.h>
#include "WProgram.h"
//some other include that aren't relevant to our issue.
// some interfacing code that has nothing to do with this: lcd_sendRaw()


uint8_t lcd_getRaw(LCD *l, uint8_t rs_mode){
      digitalWrite(l->rs_pin, rs_mode);
      digitalWrite(l->rw_pin, HIGH);

      uint8_t retVal = 0;

      for (int i = 0; i < l->bitmode; i++){
            pinMode(l->datapin[i], INPUT);
            retVal |= (digitalRead(l->datapin[i]) << i);
            pinMode(l->datapin[i], OUTPUT);
      }

      if (l->bitmode == BIT_MODE_4){
            retVal <<= 4; //obtained high nibble, must obtain low.

            digitalWrite(l->enable_pin, HIGH);
            digitalWrite(l->enable_pin, LOW);

            for (int i = 0; i < 4; i++){
                  pinMode(l->datapin[i], INPUT);
                  retVal |= (digitalRead(l->datapin[i]) << i);
                  pinMode(l->datapin[i], OUTPUT);
            }
      }

      digitalWrite(l->enable_pin, HIGH);
      digitalWrite(l->enable_pin, LOW);

      return retVal;
}

This function gets called whenever we need to get the status flag or any address. The status flag is simply obtaining by bitshifting 7 places to the left

busy_flag =  lcd_getRaw(lcd, LOW) >> 7;

The address counter is obtained by just anding with dec127 (b01111111).

address_counter = lcd_getRaw(lcd, LOW) & 127;

Reading data from CGRAM or DDRAM is done by calling lcd_getRaw() with a HIGH value for the rs pin

data = lcd_getRaw(lcd, HIGH);

This, however, fails, and the output is corrupted for some reason. Perhaps I made something overflow somewhere, I don't know. The code looks fine to me, in case anybody has any suggestions, please, let me know.