1
/***************************************************************************
2
* Copyright (C) 2016 by santiago González *
3
* santigoro@gmail.com *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 3 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, see <http://www.gnu.org/licenses/>. *
18
***************************************************************************/
20
#include "itemlibrary.h"
21
#include "connector.h"
22
#include "simulator.h"
25
static const char* Ks0108_properties[] = {
26
QT_TRANSLATE_NOOP("App::Property","CS Active Low")
30
Component* Ks0108::construct( QObject* parent, QString type, QString id )
32
return new Ks0108( parent, type, id );
35
LibraryItem* Ks0108::libraryItem()
37
return new LibraryItem(
45
Ks0108::Ks0108( QObject* parent, QString type, QString id )
46
: Component( parent, type, id )
47
, eElement( (id+"-eElement") )
48
, m_pinRst( 270, QPoint(-56, 56), id+"-PinRst" , 0, this )
49
, m_pinCs2( 270, QPoint(-48, 56), id+"-PinCs2" , 0, this )
50
, m_pinCs1( 270, QPoint(-40, 56), id+"-PinCs1" , 0, this )
51
, m_pinEn ( 270, QPoint( 32, 56), id+"-PinEn" , 0, this )
52
, m_pinRW ( 270, QPoint( 40, 56), id+"-PinRW" , 0, this )
53
, m_pinDC ( 270, QPoint( 48, 56), id+"-PinDC" , 0, this )
55
Q_UNUSED( Ks0108_properties );
59
m_area = QRectF( -74, -52, 148, 100 );
62
m_pinRst.setLabelText( " RST" );
63
m_pinCs1.setLabelText( " CS1" );
64
m_pinCs2.setLabelText( " CS2" );
65
m_pinDC.setLabelText( " RS" );
66
m_pinRW.setLabelText( " RW" );
67
m_pinEn.setLabelText( " En" );
69
m_dataPin.resize( 8 );
70
m_dataeSource.resize( 8 );
75
for( int i=0; i<8; i++ )
77
QString pinId = id+"-dataPin"+QString::number(i);
78
m_dataPin[i] = new Pin( 270, QPoint(-32+(7-i)*8, pinY), pinId , 0, this );
79
m_dataPin[i]->setLabelText( " D"+QString::number(i) );
81
pinId.append(QString("-eSource"));
82
m_dataeSource[i] = new eSource( pinId, m_dataPin[i] );
83
m_dataeSource[i]->setVoltHigh( 5 );
84
m_dataeSource[i]->setImp( high_imp );
86
m_pin[i] = m_dataPin[i];
90
m_pin[10] = &m_pinCs1;
95
m_pdisplayImg = new QImage( 128, 64, QImage::Format_MonoLSB );
96
m_pdisplayImg->setColor( 1, qRgb(0,0,0));
97
m_pdisplayImg->setColor( 0, qRgb(200,215,180) );
99
Simulator::self()->addToUpdateList( this );
101
setLabelPos( -32,-68, 0);
111
eNode* enode = m_pinEn.getEnode();// Register for Scl changes callback
112
if( enode ) enode->voltChangedCallback( this );
114
enode = m_pinRst.getEnode(); // Register for Rst changes callback
115
if( enode ) enode->voltChangedCallback( this );
118
void Ks0108::initialize()
126
void Ks0108::voltChanged() // Called when En Pin changes
128
if( m_pinRst.getVolt()<2.5 ) reset(); // Reset Pin is Low
129
else m_reset = false;
131
bool Write = ( m_pinRW.getVolt()<2.5 ); // Read or Write
132
if( m_Write != Write ) // Set Read or Write Impedances
136
if( Write ) imped = high_imp; // Data bus as Input
137
else imped = 40; // Data bus as Output
139
for( int i=0; i<8; i++ )
141
m_dataeSource[i]->setOut( false );
142
m_dataeSource[i]->setImp( imped );
146
bool Scl = (m_pinEn.getVolt()>2.5);
148
if ( Scl && !m_lastScl ) // This is a clock Rising Edge
151
if( Write ) return; // Only Read in Rising Edge
153
else if( !Scl && m_lastScl ) // This is a clock Falling edge
156
if( !Write ) return; // Only Write in Falling Edge
166
//qDebug()<<"Reading "<<m_input;
167
for( int pin=0; pin<8; pin++ ) // Read input
168
if( m_dataPin[pin]->getVolt()>2.5 )
170
//qDebug()<<pin<<pow( 2, pin );
171
m_input += pow( 2, pin );
173
//qDebug()<<"Data = "<<m_input;
176
m_Cs1 = (m_pinCs1.getVolt()>2.5); // Half 1 selected?
177
m_Cs2 = (m_pinCs2.getVolt()>2.5); // Half 2 selected?
178
if( !m_Cs1 & !m_Cs2 ) m_Cs2 = true;
186
if( (m_pinDC.getVolt()>2.5) ) // Data
188
if( m_reset ) return; // Can't erite data while Reset
189
if( Write ) writeData( m_input ); // Write Data
190
else ReadData(); // Read Data
194
if( Write )proccessCommand( m_input ); // Write Command
195
else ReadStatus(); // Read Status
199
void Ks0108::ReadData()
202
if( m_Cs1 ) data = m_aDispRam[m_addrX1][m_addrY1];
203
if( m_Cs2 ) data = m_aDispRam[m_addrX2][m_addrY2+64];
204
//qDebug() << "Ks0108::ReadData()" << data;
205
for( int i=0; i<8; i++ )
207
//qDebug() << "Ks0108::ReadData()" << i<<(data & 1)<<((data & 1)==1);
208
m_dataeSource[i]->setOut( ((data & 1)==1) );
209
m_dataeSource[i]->stampOutput();
214
void Ks0108::ReadStatus()
216
for( int i=0; i<8; i++ )
220
if ( i == 4 ) out = m_reset;
221
else if( i == 5 ) out = !m_dispOn;
223
m_dataeSource[i]->setOut( out );
224
m_dataeSource[i]->stampOutput();
228
void Ks0108::writeData( int data )
230
//qDebug() << "Ks0108::writeData "<<data <<m_Cs1<<m_Cs2;
233
//qDebug() << "Ks0108::writeData 1 "<<m_addrX1 <<m_addrY1<<data;
234
m_aDispRam[m_addrX1][m_addrY1] = data; // Write Half 1
238
//qDebug() << "Ks0108::writeData 2 "<<m_addrX2 <<m_addrY2<<data;
239
m_aDispRam[m_addrX2][m_addrY2+64] = data; // Write Half 2
244
void Ks0108::proccessCommand( int command )
246
//qDebug() << "Ks0108::proccessCommand: " << command;
247
if( command<62 ) { return; } // Not Valid
248
if( command<64 ) { dispOn( command & 1 ) ; return; } //0011111. // Display On/Off internal status &Ram not affected
249
if( command<128 ) { setYaddr( command & 63 ); return; } //01...... // Set Y address
250
if( command<184 ) { return; } // Not Valid
251
if( command<192 ) { setXaddr( command & 7 ); return; } //10111... // Set X address
252
else { startLin( command & 63 ); return; } //11...... // Set Display Start Line
254
void Ks0108::dispOn( int state )
256
m_dispOn = (state > 0);
259
void Ks0108::setYaddr( int addr )
261
//qDebug() << "Ks0108::setYaddr "<<addr <<m_Cs1<<m_Cs2;
262
if( m_Cs1 ) m_addrY1 = addr ;
263
if( m_Cs2 ) m_addrY2 = addr ;
266
void Ks0108::setXaddr( int addr )
268
//qDebug() << "Ks0108::setXaddr "<<addr <<m_Cs1<<m_Cs2;
269
if( m_Cs1 ) m_addrX1 = addr ;
270
if( m_Cs2 ) m_addrX2 = addr ;
273
void Ks0108::startLin( int line )
278
void Ks0108::clearLcd()
280
m_pdisplayImg->fill(0);
283
void Ks0108::clearDDRAM()
285
for(int row=0;row<8;row++)
286
for( int col=0;col<128;col++ )
287
m_aDispRam[row][col] = 0;
290
void Ks0108::incrementPointer()
331
void Ks0108::remove()
333
for( int i=0; i<8; i++ ) delete m_dataeSource[i];
335
delete m_pdisplayImg;
336
Simulator::self()->remFromUpdateList( this );
341
void Ks0108::updateStep()
343
if( !m_dispOn ) m_pdisplayImg->fill(0); // Display Off
346
for(int row=0;row<8;row++)
348
for( int col=0;col<128;col++ )
350
char abyte = m_aDispRam[row][col];
351
for( int bit=0; bit<8; bit++ )
353
m_pdisplayImg->setPixel(col,row*8+bit,(abyte & 1) );
362
void Ks0108::paint( QPainter* p, const QStyleOptionGraphicsItem* option, QWidget* widget )
364
Component::paint( p, option, widget );
366
QPen pen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
369
p->setBrush( QColor(50, 70, 100) );
370
p->drawRoundedRect( m_area,2,2 );
371
p->setBrush( QColor(200, 220, 180) );
372
p->drawRoundedRect( -70, -48, 140, 76, 8, 8 );
373
p->drawImage(-64,-42,*m_pdisplayImg );
376
#include "moc_ks0108.cpp"