Forward I2C input to KS0066 LCD
This commit is contained in:
parent
1757c1a550
commit
8c6d9a4806
227
TWI/TWI/KS0066.cpp
Normal file
227
TWI/TWI/KS0066.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
#include "KS0066.h"
|
||||
|
||||
#include <util/delay.h>
|
||||
|
||||
KS0066::KS0066()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KS0066::KS0066(ShiftRegister &shiftRegister)
|
||||
{
|
||||
setShiftRegister(shiftRegister);
|
||||
}
|
||||
|
||||
void KS0066::setShiftRegister(ShiftRegister &shiftRegister)
|
||||
{
|
||||
m_shiftRegister = &shiftRegister;
|
||||
|
||||
initDisplay();
|
||||
}
|
||||
|
||||
void KS0066::initDisplay()
|
||||
{
|
||||
_delay_ms(30);
|
||||
|
||||
execute((1 << m_db5) | 1 << m_db4);
|
||||
_delay_ms(5);
|
||||
execute((1 << m_db5) | 1 << m_db4);
|
||||
_delay_us(100);
|
||||
execute((1 << m_db5) | 1 << m_db4);
|
||||
execute((1 << m_db5));
|
||||
|
||||
functionSet(false, true, true);
|
||||
|
||||
onOffControl(true, false, false);
|
||||
displayClear();
|
||||
|
||||
entryMode(true, false);
|
||||
|
||||
sendString("ready.");
|
||||
}
|
||||
|
||||
void KS0066::functionSet(bool interface8bit, bool twoLine, bool displayFont)
|
||||
{
|
||||
uint8_t command = 0b00100000;
|
||||
|
||||
if (interface8bit)
|
||||
{
|
||||
command |= (1 << 4);
|
||||
}
|
||||
|
||||
if (twoLine)
|
||||
{
|
||||
command |= (1 << 3);
|
||||
}
|
||||
|
||||
if (displayFont)
|
||||
{
|
||||
command |= (1 << 2);
|
||||
}
|
||||
|
||||
sendCommand(command);
|
||||
|
||||
_delay_us(53);
|
||||
}
|
||||
|
||||
void KS0066::onOffControl(bool displayOn, bool cursorOn, bool blinkingOn)
|
||||
{
|
||||
uint8_t command = 0b00001000;
|
||||
|
||||
if (displayOn)
|
||||
{
|
||||
command |= (1 << 2);
|
||||
}
|
||||
|
||||
if (cursorOn)
|
||||
{
|
||||
command |= (1 << 1);
|
||||
}
|
||||
|
||||
if (blinkingOn)
|
||||
{
|
||||
command |= (1 << 0);
|
||||
}
|
||||
|
||||
sendCommand(command);
|
||||
|
||||
_delay_us(53);
|
||||
}
|
||||
|
||||
void KS0066::displayClear()
|
||||
{
|
||||
uint8_t command = 0b00000001;
|
||||
|
||||
sendCommand(command);
|
||||
|
||||
_delay_ms(2.16);
|
||||
}
|
||||
|
||||
void KS0066::entryMode(bool incrementMode, bool entireShift)
|
||||
{
|
||||
uint8_t command = 0b00000100;
|
||||
|
||||
if (incrementMode)
|
||||
{
|
||||
command |= (1 << 1);
|
||||
}
|
||||
|
||||
if (entireShift)
|
||||
{
|
||||
command |= (1 << 0);
|
||||
}
|
||||
|
||||
sendCommand(command);
|
||||
|
||||
_delay_us(53);
|
||||
}
|
||||
|
||||
void KS0066::setCursorPos(uint8_t line, uint8_t column)
|
||||
{
|
||||
sendCommand(0b10000000 + column + (line * 40));
|
||||
}
|
||||
|
||||
void KS0066::sendCommand(uint8_t data)
|
||||
{
|
||||
sendByte(data, true);
|
||||
}
|
||||
|
||||
void KS0066::sendChar(char c)
|
||||
{
|
||||
sendByte(c, false);
|
||||
|
||||
_delay_us(53);
|
||||
}
|
||||
|
||||
void KS0066::sendString(const char *string)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
while (string != nullptr && *string != 0 && count < (m_lines * m_columns))
|
||||
{
|
||||
if (count % m_columns == 0)
|
||||
{
|
||||
setCursorPos(count / m_columns, 0);
|
||||
}
|
||||
sendChar(*string);
|
||||
string++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
void KS0066::sendByte(uint8_t data, bool isCommand)
|
||||
{
|
||||
uint8_t registerValue = 0;
|
||||
|
||||
if (!isCommand)
|
||||
{
|
||||
registerValue |= (1 << m_rs);
|
||||
}
|
||||
|
||||
if (data & (1 << 7))
|
||||
{
|
||||
registerValue |= (1 << m_db7);
|
||||
}
|
||||
|
||||
if (data & (1 << 6))
|
||||
{
|
||||
registerValue |= (1 << m_db6);
|
||||
}
|
||||
|
||||
if (data & (1 << 5))
|
||||
{
|
||||
registerValue |= (1 << m_db5);
|
||||
}
|
||||
|
||||
if (data & (1 << 4))
|
||||
{
|
||||
registerValue |= (1 << m_db4);
|
||||
}
|
||||
|
||||
execute(registerValue);
|
||||
|
||||
registerValue &= (1 << m_rs);
|
||||
|
||||
if (data & (1 << 3))
|
||||
{
|
||||
registerValue |= (1 << m_db7);
|
||||
}
|
||||
|
||||
if (data & (1 << 2))
|
||||
{
|
||||
registerValue |= (1 << m_db6);
|
||||
}
|
||||
|
||||
if (data & (1 << 1))
|
||||
{
|
||||
registerValue |= (1 << m_db5);
|
||||
}
|
||||
|
||||
if (data & (1 << 0))
|
||||
{
|
||||
registerValue |= (1 << m_db4);
|
||||
}
|
||||
|
||||
execute(registerValue);
|
||||
}
|
||||
|
||||
void KS0066::execute(uint8_t registerValue)
|
||||
{
|
||||
registerValue |= (1 << m_e);
|
||||
m_shiftRegister->output(registerValue);
|
||||
_delay_us(2);
|
||||
|
||||
registerValue &= ~(1 << m_e);
|
||||
m_shiftRegister->output(registerValue);
|
||||
}
|
||||
|
||||
void KS0066::set(const char *string)
|
||||
{
|
||||
displayClear();
|
||||
sendString(string);
|
||||
}
|
||||
|
||||
void KS0066::clear()
|
||||
{
|
||||
displayClear();
|
||||
}
|
||||
|
55
TWI/TWI/KS0066.h
Normal file
55
TWI/TWI/KS0066.h
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "environment.h"
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "ShiftRegister.h"
|
||||
|
||||
class KS0066
|
||||
{
|
||||
private:
|
||||
ShiftRegister *m_shiftRegister;
|
||||
|
||||
static const uint8_t m_rs = 1;
|
||||
static const uint8_t m_rw = 2;
|
||||
static const uint8_t m_e = 3;
|
||||
static const uint8_t m_db4 = 4;
|
||||
static const uint8_t m_db5 = 5;
|
||||
static const uint8_t m_db6 = 6;
|
||||
static const uint8_t m_db7 = 7;
|
||||
|
||||
uint8_t m_lines = 2;
|
||||
uint8_t m_columns = 16;
|
||||
|
||||
public:
|
||||
KS0066();
|
||||
KS0066(ShiftRegister &shiftRegister);
|
||||
|
||||
void setShiftRegister(ShiftRegister &shiftRegister);
|
||||
|
||||
void clear();
|
||||
|
||||
void set(const char *string);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void initDisplay();
|
||||
|
||||
void functionSet(bool interface8bit, bool twoLine, bool displayOn);
|
||||
void onOffControl(bool displayOn, bool cursorOn, bool blinkingOn);
|
||||
void entryMode(bool incrementMode, bool entireShift);
|
||||
void displayClear();
|
||||
|
||||
void setCursorPos(uint8_t line, uint8_t column);
|
||||
|
||||
void sendCommand(uint8_t data);
|
||||
|
||||
void sendChar(char c);
|
||||
void sendString(const char *string);
|
||||
|
||||
void sendByte(uint8_t data, bool isCommand);
|
||||
|
||||
void execute(uint8_t registerValue);
|
||||
};
|
23
TWI/TWI/ShiftRegister.cpp
Normal file
23
TWI/TWI/ShiftRegister.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "ShiftRegister.h"
|
||||
|
||||
ShiftRegister::ShiftRegister(volatile uint8_t *shiftClockPort, uint8_t shiftClockPin,
|
||||
volatile uint8_t *dataPort, uint8_t dataPin,
|
||||
volatile uint8_t *latchClockPort, uint8_t latchClockPin)
|
||||
: m_shiftClockPin(shiftClockPort, shiftClockPin)
|
||||
, m_dataPin(dataPort, dataPin)
|
||||
, m_latchClockPin(latchClockPort, latchClockPin)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ShiftRegister::output(int8_t value)
|
||||
{
|
||||
for (int8_t bitIdx = 7; bitIdx >= 0; --bitIdx)
|
||||
{
|
||||
m_dataPin.set(value & (1 << bitIdx));
|
||||
m_shiftClockPin.pulse();
|
||||
}
|
||||
|
||||
m_latchClockPin.pulse();
|
||||
}
|
||||
|
19
TWI/TWI/ShiftRegister.h
Normal file
19
TWI/TWI/ShiftRegister.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "Pin.h"
|
||||
|
||||
class ShiftRegister
|
||||
{
|
||||
Pin m_shiftClockPin;
|
||||
Pin m_dataPin;
|
||||
Pin m_latchClockPin;
|
||||
|
||||
public:
|
||||
ShiftRegister(volatile uint8_t *shiftClockPort, uint8_t shiftClockPin,
|
||||
volatile uint8_t *dataPort, uint8_t dataPin,
|
||||
volatile uint8_t *latchClockPort, uint8_t latchClockPin);
|
||||
|
||||
void output(int8_t value);
|
||||
};
|
@ -7,6 +7,8 @@
|
||||
#include <util/twi.h>
|
||||
|
||||
#include "Pin.h"
|
||||
#include "ShiftRegister.h"
|
||||
#include "KS0066.h"
|
||||
|
||||
void I2C_init(uint8_t address)
|
||||
{
|
||||
@ -23,7 +25,9 @@ void I2C_stop(void)
|
||||
TWCR &= ~( (1<<TWEA) | (1<<TWEN) );
|
||||
}
|
||||
|
||||
volatile uint8_t dataBuffer;
|
||||
char displayBuffer[32];
|
||||
volatile uint8_t displayBufferIdx = 0;
|
||||
volatile bool writeDisplay = false;
|
||||
|
||||
ISR(TWI_vect)
|
||||
{
|
||||
@ -34,12 +38,12 @@ ISR(TWI_vect)
|
||||
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
||||
break;
|
||||
case TW_SR_DATA_ACK:
|
||||
dataBuffer = TWDR;
|
||||
displayBuffer[displayBufferIdx++] = TWDR;
|
||||
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
|
||||
break;
|
||||
case TW_ST_SLA_ACK:
|
||||
TWDR = dataBuffer + 1;
|
||||
TWCR |= (1<<TWIE) | (1<<TWINT) | (0<<TWEA) | (1<<TWEN);
|
||||
case TW_SR_STOP:
|
||||
writeDisplay = true;
|
||||
TWCR |= (1<<TWIE) | (1<<TWEA) | (1<<TWEN);
|
||||
break;
|
||||
default:
|
||||
// if none of the above apply prepare TWI to be addressed again
|
||||
@ -50,14 +54,42 @@ ISR(TWI_vect)
|
||||
int main(void)
|
||||
{
|
||||
DDRD |= (1 << PD6);
|
||||
DDRC |= (1 << PC4) | (1 << PC3) | (1 << PC2);
|
||||
|
||||
Pin statusLed(&PORTD, PD6);
|
||||
statusLed.set(false);
|
||||
|
||||
DDRD |= (1 << PD5);
|
||||
TCCR1A = (1<<WGM10) | (1<<COM1A1); // PWM, phase correct, 8 bit.
|
||||
TCCR1B = (1<<CS11) | (1<<CS10); // Prescaler 64 = Enable counter
|
||||
OCR1A = 0;
|
||||
|
||||
DDRD &= ~(1 << PD3);
|
||||
PORTD |= (1 << PD3);
|
||||
|
||||
ShiftRegister shiftRegister(&PORTC, PC4, &PORTC, PC2, &PORTC, PC3);
|
||||
|
||||
KS0066 lcd(shiftRegister);
|
||||
|
||||
statusLed.set(true);
|
||||
|
||||
I2C_init(0x23);
|
||||
sei();
|
||||
|
||||
while(1)
|
||||
{
|
||||
if (writeDisplay == true)
|
||||
{
|
||||
displayBuffer[displayBufferIdx] = 0;
|
||||
lcd.set(displayBuffer);
|
||||
writeDisplay = false;
|
||||
displayBufferIdx = 0;
|
||||
}
|
||||
|
||||
if (!(PIND & (1 << PD3)))
|
||||
{
|
||||
OCR1A = ((OCR1A + 1) * 2) % 255;
|
||||
_delay_ms(300);
|
||||
}
|
||||
}
|
||||
}
|
@ -63,32 +63,21 @@
|
||||
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
|
||||
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||
<avrgcc.compiler.symbols.DefSymbols>
|
||||
<ListValues>
|
||||
<Value>NDEBUG</Value>
|
||||
</ListValues>
|
||||
</avrgcc.compiler.symbols.DefSymbols>
|
||||
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
||||
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
||||
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
||||
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
||||
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||
<avrgcccpp.compiler.symbols.DefSymbols>
|
||||
<ListValues>
|
||||
<Value>NDEBUG</Value>
|
||||
</ListValues>
|
||||
</avrgcccpp.compiler.symbols.DefSymbols>
|
||||
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
|
||||
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
|
||||
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
|
||||
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
|
||||
<avrgcccpp.linker.libraries.Libraries>
|
||||
<ListValues>
|
||||
<Value>libm</Value>
|
||||
</ListValues>
|
||||
</avrgcccpp.linker.libraries.Libraries>
|
||||
</AvrGccCpp>
|
||||
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=c++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
|
||||
<avrgcccpp.linker.libraries.Libraries><ListValues><Value>libm</Value></ListValues></avrgcccpp.linker.libraries.Libraries>
|
||||
<avrgcc.compiler.symbols.DefSymbols><ListValues><Value>NDEBUG</Value></ListValues></avrgcc.compiler.symbols.DefSymbols>
|
||||
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
||||
<avrgcccpp.compiler.symbols.DefSymbols><ListValues><Value>NDEBUG</Value></ListValues></avrgcccpp.compiler.symbols.DefSymbols>
|
||||
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
|
||||
</AvrGccCpp>
|
||||
</ToolchainSettings>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
@ -101,47 +90,48 @@
|
||||
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
|
||||
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||
<avrgcc.compiler.symbols.DefSymbols>
|
||||
<ListValues>
|
||||
<Value>DEBUG</Value>
|
||||
</ListValues>
|
||||
</avrgcc.compiler.symbols.DefSymbols>
|
||||
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
|
||||
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
||||
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
||||
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
|
||||
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
||||
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||
<avrgcccpp.compiler.symbols.DefSymbols>
|
||||
<ListValues>
|
||||
<Value>DEBUG</Value>
|
||||
</ListValues>
|
||||
</avrgcccpp.compiler.symbols.DefSymbols>
|
||||
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
|
||||
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
|
||||
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
|
||||
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
|
||||
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
|
||||
<avrgcccpp.linker.libraries.Libraries>
|
||||
<ListValues>
|
||||
<Value>libm</Value>
|
||||
</ListValues>
|
||||
</avrgcccpp.linker.libraries.Libraries>
|
||||
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=c++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
|
||||
<avrgcccpp.linker.libraries.Libraries><ListValues><Value>libm</Value></ListValues></avrgcccpp.linker.libraries.Libraries>
|
||||
<avrgcc.compiler.symbols.DefSymbols><ListValues><Value>DEBUG</Value></ListValues></avrgcc.compiler.symbols.DefSymbols>
|
||||
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
|
||||
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
|
||||
<avrgcccpp.compiler.symbols.DefSymbols><ListValues><Value>DEBUG</Value></ListValues></avrgcccpp.compiler.symbols.DefSymbols>
|
||||
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
|
||||
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
|
||||
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
|
||||
</AvrGccCpp>
|
||||
</AvrGccCpp>
|
||||
</ToolchainSettings>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="environment.h">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="KS0066.cpp">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="KS0066.h">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Pin.cpp">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Pin.h">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ShiftRegister.cpp">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ShiftRegister.h">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TWI.cpp">
|
||||
<SubType>compile</SubType>
|
||||
</Compile>
|
||||
|
Reference in New Issue
Block a user