lcd.cpp (4841B)
1 #include "lcd.h" 2 3 #include <cassert> 4 5 #include "mc68k/logging.h" 6 7 #define LOG MCLOG 8 9 namespace hwLib 10 { 11 LCD::LCD() = default; 12 13 std::optional<uint8_t> LCD::exec(bool registerSelect, bool read, uint8_t g) 14 { 15 bool changed = false; 16 bool cgRamChanged = false; 17 18 std::optional<uint8_t> result; 19 20 if(!read) 21 { 22 if(!registerSelect) 23 { 24 if(g == 0x01) 25 { 26 LOG("LCD Clear Display"); 27 m_dramData.fill(' '); 28 changed = true; 29 } 30 else if(g == 0x02) 31 { 32 LOG("LCD Return Home"); 33 m_dramAddr = 0; 34 m_cursorPos = 0; 35 } 36 else if((g & 0xfc) == 0x04) 37 { 38 const int increment = (g >> 1) & 1; 39 const int shift = g & 1; 40 LOG("LCD Entry Mode Set, inc=" << increment << ", shift=" << shift); 41 42 m_addrIncrement = increment ? 1 : -1; 43 } 44 else if((g & 0xf8) == 0x08) 45 { 46 const int displayOnOff = (g >> 2) & 1; 47 const int cursorOnOff = (g >> 1) & 1; 48 const int cursorBlinking = g & 1; 49 50 LOG("LCD Display ON/OFF, display=" << displayOnOff << ", cursor=" << cursorOnOff << ", blinking=" << cursorBlinking); 51 52 m_displayOn = displayOnOff != 0; 53 m_cursorOn = cursorOnOff != 0; 54 m_cursorBlinking = cursorBlinking != 0; 55 } 56 else if((g & 0xf3) == 0x10) 57 { 58 const int scrl = (g >> 2) & 3; 59 60 LOG("LCD Cursor/Display Shift, scrl=" << scrl); 61 m_cursorShift = static_cast<CursorShiftMode>(scrl); 62 } 63 else if((g & 0xec) == 0x28) 64 { 65 const int dl = (g >> 4) & 1; 66 const int ft = g & 3; 67 68 LOG("LCD Function Set, dl=" << dl << ", ft=" << ft); 69 m_dataLength = static_cast<DataLength>(dl); 70 m_fontTable = static_cast<FontTable>(ft); 71 } 72 else if(g & (1<<7)) 73 { 74 const int addr = g & 0x7f; 75 // LOG("LCD Set DDRAM address, addr=" << addr); 76 m_dramAddr = addr; 77 m_addressMode = AddressMode::DDRam; 78 } 79 else if(g & (1<<6)) 80 { 81 const int acg = g & 0x3f; 82 83 // LOG("LCD Set CGRAM address, acg=" << acg); 84 m_cgramAddr = acg; 85 m_addressMode = AddressMode::CGRam; 86 } 87 else 88 { 89 LOG("LCD unknown command"); 90 assert(false); 91 } 92 } 93 else 94 { 95 if(m_addressMode == AddressMode::CGRam) 96 { 97 // changed = true; 98 // LOG("LCD write data to CGRAM addr " << m_cgramAddr << ", data=" << static_cast<int>(g)); 99 100 if (m_cgramData[m_cgramAddr] != g) 101 { 102 m_cgramData[m_cgramAddr] = g; 103 cgRamChanged = true; 104 } 105 106 m_cgramAddr += m_addrIncrement; 107 108 /* 109 if((m_cgramAddr & 0x7) == 0) 110 { 111 std::stringstream ss; 112 ss << "CG RAM character " << (m_cgramAddr/8 - 1) << ':' << '\n'; 113 ss << "##################" << '\n'; 114 for(auto i = m_cgramAddr - 8; i < m_cgramAddr - 1; ++i) 115 { 116 ss << '#'; 117 for(int x=7; x >= 0; --x) 118 { 119 if(m_cgramData[i] & (1<<x)) 120 ss << "[]"; 121 else 122 ss << " "; 123 } 124 ss << '#' << '\n'; 125 } 126 ss << "##################" << '\n'; 127 const auto s(ss.str()); 128 LOG(s); 129 } 130 */ 131 } 132 else 133 { 134 // LOG("LCD write data to DDRAM addr " << m_dramAddr << ", data=" << static_cast<int>(g) << ", char=" << static_cast<char>(g)); 135 136 const auto old = m_dramData; 137 138 if(m_dramAddr >= 20 && m_dramAddr < 0x40) 139 { 140 for(size_t i=1; i<=20; ++i) 141 m_dramData[i-1] = m_dramData[i]; 142 m_dramData[19] = static_cast<char>(g); 143 } 144 else if(m_dramAddr > 0x53) 145 { 146 for(size_t i=21; i<=40; ++i) 147 m_dramData[i-1] = m_dramData[i]; 148 149 m_dramData[39] = static_cast<char>(g); 150 } 151 else 152 { 153 if(m_dramAddr < 20) 154 m_dramData[m_dramAddr] = static_cast<char>(g); 155 else 156 m_dramData[m_dramAddr - 0x40 + 20] = static_cast<char>(g); 157 } 158 159 if(m_dramAddr != 20 && m_dramAddr != 0x54) 160 m_dramAddr += m_addrIncrement; 161 162 if(m_dramData != old) 163 changed = true; 164 } 165 } 166 } 167 else 168 { 169 if(registerSelect) 170 { 171 LOG("LCD read data from CGRAM or DDRAM"); 172 if(m_addressMode == AddressMode::CGRam) 173 result = m_cgramData[m_cgramAddr]; 174 else 175 result = m_dramData[m_dramAddr]; 176 } 177 else 178 { 179 LOG("LCD read busy flag & address"); 180 if(m_addressMode == AddressMode::CGRam) 181 { 182 result = static_cast<uint8_t>(m_cgramAddr); 183 } 184 else 185 { 186 auto a = m_dramAddr; 187 if(a > 0x53) 188 a = 0x53; 189 if(a == 20) 190 a = 19; 191 result = static_cast<uint8_t>(m_dramAddr); 192 } 193 } 194 } 195 196 if(changed && m_changeCallback) 197 m_changeCallback(); 198 199 if(cgRamChanged && m_cgRamChangeCallback) 200 m_cgRamChangeCallback(); 201 202 return result; 203 } 204 205 bool LCD::getCgData(std::array<uint8_t, 8>& _data, uint32_t _charIndex) const 206 { 207 const auto idx = _charIndex * 8; 208 if(idx + 8 >= getCgRam().size()) 209 return false; 210 211 uint32_t j = 0; 212 213 for(auto i = idx; i<idx+8; ++i) 214 _data[j++] = getCgRam()[i]; 215 216 return true; 217 } 218 }