Forward I2C input to KS0066 LCD

This commit is contained in:
mandlm 2016-01-26 14:49:20 +01:00
parent 1757c1a550
commit 8c6d9a4806
6 changed files with 420 additions and 74 deletions

227
TWI/TWI/KS0066.cpp Normal file
View 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
View 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
View 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
View 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);
};

View file

@ -7,6 +7,8 @@
#include <util/twi.h> #include <util/twi.h>
#include "Pin.h" #include "Pin.h"
#include "ShiftRegister.h"
#include "KS0066.h"
void I2C_init(uint8_t address) void I2C_init(uint8_t address)
{ {
@ -23,7 +25,9 @@ void I2C_stop(void)
TWCR &= ~( (1<<TWEA) | (1<<TWEN) ); TWCR &= ~( (1<<TWEA) | (1<<TWEN) );
} }
volatile uint8_t dataBuffer; char displayBuffer[32];
volatile uint8_t displayBufferIdx = 0;
volatile bool writeDisplay = false;
ISR(TWI_vect) ISR(TWI_vect)
{ {
@ -34,12 +38,12 @@ ISR(TWI_vect)
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break; break;
case TW_SR_DATA_ACK: case TW_SR_DATA_ACK:
dataBuffer = TWDR; displayBuffer[displayBufferIdx++] = TWDR;
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break; break;
case TW_ST_SLA_ACK: case TW_SR_STOP:
TWDR = dataBuffer + 1; writeDisplay = true;
TWCR |= (1<<TWIE) | (1<<TWINT) | (0<<TWEA) | (1<<TWEN); TWCR |= (1<<TWIE) | (1<<TWEA) | (1<<TWEN);
break; break;
default: default:
// if none of the above apply prepare TWI to be addressed again // if none of the above apply prepare TWI to be addressed again
@ -50,14 +54,42 @@ ISR(TWI_vect)
int main(void) int main(void)
{ {
DDRD |= (1 << PD6); DDRD |= (1 << PD6);
DDRC |= (1 << PC4) | (1 << PC3) | (1 << PC2);
Pin statusLed(&PORTD, PD6); Pin statusLed(&PORTD, PD6);
statusLed.set(false); 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); I2C_init(0x23);
sei(); sei();
while(1) 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);
}
} }
} }

View file

@ -63,31 +63,20 @@
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> <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.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned> <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.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum> <avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings> <avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.linker.libraries.Libraries> <avrgcccpp.compiler.miscellaneous.OtherFlags>-std=c++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
<ListValues> <avrgcccpp.linker.libraries.Libraries><ListValues><Value>libm</Value></ListValues></avrgcccpp.linker.libraries.Libraries>
<Value>libm</Value> <avrgcc.compiler.symbols.DefSymbols><ListValues><Value>NDEBUG</Value></ListValues></avrgcc.compiler.symbols.DefSymbols>
</ListValues> <avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
</avrgcccpp.linker.libraries.Libraries> <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> </AvrGccCpp>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
@ -101,33 +90,22 @@
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures> <avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> <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.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> <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> <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned> <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.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum> <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.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.linker.libraries.Libraries> <avrgcccpp.compiler.miscellaneous.OtherFlags>-std=c++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
<ListValues> <avrgcccpp.linker.libraries.Libraries><ListValues><Value>libm</Value></ListValues></avrgcccpp.linker.libraries.Libraries>
<Value>libm</Value> <avrgcc.compiler.symbols.DefSymbols><ListValues><Value>DEBUG</Value></ListValues></avrgcc.compiler.symbols.DefSymbols>
</ListValues> <avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
</avrgcccpp.linker.libraries.Libraries> <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.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp> </AvrGccCpp>
</ToolchainSettings> </ToolchainSettings>
@ -136,12 +114,24 @@
<Compile Include="environment.h"> <Compile Include="environment.h">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="KS0066.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="KS0066.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="Pin.cpp"> <Compile Include="Pin.cpp">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="Pin.h"> <Compile Include="Pin.h">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="ShiftRegister.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="ShiftRegister.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="TWI.cpp"> <Compile Include="TWI.cpp">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>