Reply - Raw
Replies:
// S6B0108/KS0108 LCD test code.
// Arduino MEGA.
// Data bus wired to PORT A.
// Control signals wired to PORT C.
//
// Documents used for reference:
//  - http://www.pighixxx.com/test/pinouts/boards/mega.pdf
//  - http://www.cec-mc.ru/data/files/File/PDF/PG12864-H.PDF
//  - https://openlabpro.com/guide/ks0108-graphic-lcd-interfacing-pic18f4550-part-2/
//
// Copyright (c) 2017 Odd Stråbø <oddstr13@openshell.no>
// License: MIT - https://opensource.org/licenses/MIT
//

const uint8_t DI_b  = 0;
const uint8_t RW_b  = 1;
const uint8_t E_b   = 2;
const uint8_t CS1_b = 3;
const uint8_t CS2_b = 4;

const uint8_t DI  = _BV(DI_b);  // HIGH == Data, LOW == Instruction
const uint8_t RW  = _BV(RW_b);  // HIGH == Read, LOW == Write
const uint8_t E   = _BV(E_b);   // LOW -> HIGH == Clock
const uint8_t CS1 = _BV(CS1_b); // LOW == Select
const uint8_t CS2 = _BV(CS2_b); // LOW == Select


const bool REG_INSTRUCTION = 0;
const bool REG_DATA        = 1;
const bool RW_READ         = 1;
const bool RW_WRITE        = 0;

const uint8_t STATUS_BUSY  = _BV(7);
const uint8_t STATUS_ONOFF = _BV(5);
const uint8_t STATUS_RESET = _BV(4);

void lcd_write(bool reg, const uint8_t data) {
  DDRA = 0; // Input
  // Clear everything but CS1 and CS2, then set DI(reg)
  PORTC = (PORTC & (CS1 | CS2)) | reg << DI_b;
  
  PORTC &= CS1 | CS2;
  PORTC |= reg << DI_b;

  DDRA = 0xff; // Output
  PORTA = data;
  
  delayMicroseconds(2);
  PORTC |= E;
  delayMicroseconds(2);
  PORTC &= ~E;
  delayMicroseconds(2);

  DDRA = 0; // Input
}

uint8_t lcd_read(bool reg) {
  DDRA = 0; // Input
  // Clear everything but CS1 and CS2, then set RW and DI(reg)
  PORTC = (PORTC & (CS1 | CS2)) | RW | reg << DI_b;
  
  delayMicroseconds(2);
  PORTC |= E;
  delayMicroseconds(2);
  uint8_t data = PINA;
  PORTC &= ~E;
  delayMicroseconds(2);

  return data;
}

void lcd_on() {
  lcd_write(REG_INSTRUCTION, 0b00111111);
}

void lcd_off() {
  lcd_write(REG_INSTRUCTION, 0b00111110);
}

uint8_t readStatus() {
  return lcd_read(REG_INSTRUCTION);
}

void lcd_set_page_address(uint8_t addr) {
  // address 0-63
  lcd_write(REG_INSTRUCTION, 0b01000000 | (addr & 0b111111));
}

void lcd_select_page(uint8_t page) {
  // page 0-7
  lcd_write(REG_INSTRUCTION, 0b10111000 | (page & 0b111));
}

void setup() {
  Serial.begin(115200);
  Serial.println("Setup start.");
  // put your setup code here, to run once:
  DDRA = 0; // PA Input
  DDRC = 0;
  PORTC = DI | CS1; // Default; Data Write on 2nd segment(CS2)
  DDRC = DI | RW | E | CS1 | CS2;

  lcd_on();
  
  lcd_select_page(0);
  lcd_set_page_address(0);
  
  Serial.println("Setup end.");
}

uint8_t seq = 0;
void loop() {
  //PORTC
  lcd_write(REG_DATA, seq);
  seq++;
  delay(50);
}