Restructured code into serveral source files
This commit is contained in:
parent
7756a85bb9
commit
9abaa69d1e
6 changed files with 185 additions and 150 deletions
|
@ -4,72 +4,8 @@
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
class Pin
|
#include "Pin.h"
|
||||||
{
|
#include "ShiftRegister.h"
|
||||||
public:
|
|
||||||
volatile uint8_t *m_port;
|
|
||||||
uint8_t m_pin;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Pin(volatile uint8_t *port, uint8_t pin)
|
|
||||||
: m_port(port)
|
|
||||||
, m_pin(pin)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulse()
|
|
||||||
{
|
|
||||||
*m_port |= (1 << m_pin);
|
|
||||||
*m_port &= ~(1 << m_pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(bool value)
|
|
||||||
{
|
|
||||||
if (value == true)
|
|
||||||
{
|
|
||||||
*m_port |= (1 << m_pin);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*m_port &= ~(1 << m_pin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void toggle()
|
|
||||||
{
|
|
||||||
*m_port ^= (1 << m_pin);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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)
|
|
||||||
: m_shiftClockPin(shiftClockPort, shiftClockPin)
|
|
||||||
, m_dataPin(dataPort, dataPin)
|
|
||||||
, m_latchClockPin(latchClockPort, latchClockPin)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void output(int8_t value)
|
|
||||||
{
|
|
||||||
for (int8_t bitIdx = 7; bitIdx >= 0; --bitIdx)
|
|
||||||
{
|
|
||||||
m_dataPin.set(value & (1 << bitIdx));
|
|
||||||
m_shiftClockPin.pulse();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_latchClockPin.pulse();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
@ -77,13 +13,13 @@ int main(void)
|
||||||
|
|
||||||
ShiftRegister shiftRegister(&PORTA, PA1, &PORTA, PA3, &PORTA, PA2);
|
ShiftRegister shiftRegister(&PORTA, PA1, &PORTA, PA3, &PORTA, PA2);
|
||||||
Pin ledPin(&PORTA, PA0);
|
Pin ledPin(&PORTA, PA0);
|
||||||
|
|
||||||
// lcd initialization goes here
|
// lcd initialization goes here
|
||||||
|
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
ledPin.toggle();
|
ledPin.toggle();
|
||||||
_delay_ms(125);
|
_delay_ms(125);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,15 +28,15 @@
|
||||||
<eraseonlaunchrule>0</eraseonlaunchrule>
|
<eraseonlaunchrule>0</eraseonlaunchrule>
|
||||||
<AsfFrameworkConfig>
|
<AsfFrameworkConfig>
|
||||||
<framework-data xmlns="">
|
<framework-data xmlns="">
|
||||||
<options />
|
<options />
|
||||||
<configurations />
|
<configurations />
|
||||||
<files />
|
<files />
|
||||||
<documentation help="" />
|
<documentation help="" />
|
||||||
<offline-documentation help="" />
|
<offline-documentation help="" />
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.29.0" />
|
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.29.0" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</framework-data>
|
</framework-data>
|
||||||
</AsfFrameworkConfig>
|
</AsfFrameworkConfig>
|
||||||
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
|
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
|
||||||
<com_atmel_avrdbg_tool_stk500>
|
<com_atmel_avrdbg_tool_stk500>
|
||||||
|
@ -56,86 +56,98 @@
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<ToolchainSettings>
|
<ToolchainSettings>
|
||||||
<AvrGccCpp>
|
<AvrGccCpp>
|
||||||
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
||||||
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
||||||
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
||||||
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
||||||
<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>
|
<avrgcc.compiler.symbols.DefSymbols>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>NDEBUG</Value>
|
<Value>NDEBUG</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcc.compiler.symbols.DefSymbols>
|
</avrgcc.compiler.symbols.DefSymbols>
|
||||||
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
<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>
|
<avrgcccpp.compiler.symbols.DefSymbols>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>NDEBUG</Value>
|
<Value>NDEBUG</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcccpp.compiler.symbols.DefSymbols>
|
</avrgcccpp.compiler.symbols.DefSymbols>
|
||||||
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
|
<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.linker.libraries.Libraries>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>libm</Value>
|
<Value>libm</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcccpp.linker.libraries.Libraries>
|
</avrgcccpp.linker.libraries.Libraries>
|
||||||
</AvrGccCpp>
|
</AvrGccCpp>
|
||||||
</ToolchainSettings>
|
</ToolchainSettings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
<ToolchainSettings>
|
<ToolchainSettings>
|
||||||
<AvrGccCpp>
|
<AvrGccCpp>
|
||||||
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
||||||
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
||||||
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
||||||
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
||||||
<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>
|
<avrgcc.compiler.symbols.DefSymbols>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>DEBUG</Value>
|
<Value>DEBUG</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcc.compiler.symbols.DefSymbols>
|
</avrgcc.compiler.symbols.DefSymbols>
|
||||||
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
|
<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.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>
|
<avrgcccpp.compiler.symbols.DefSymbols>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>DEBUG</Value>
|
<Value>DEBUG</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcccpp.compiler.symbols.DefSymbols>
|
</avrgcccpp.compiler.symbols.DefSymbols>
|
||||||
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
|
<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.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.linker.libraries.Libraries>
|
||||||
<ListValues>
|
<ListValues>
|
||||||
<Value>libm</Value>
|
<Value>libm</Value>
|
||||||
</ListValues>
|
</ListValues>
|
||||||
</avrgcccpp.linker.libraries.Libraries>
|
</avrgcccpp.linker.libraries.Libraries>
|
||||||
<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>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="LCD.cpp">
|
<Compile Include="LCD.cpp">
|
||||||
<SubType>compile</SubType>
|
<SubType>compile</SubType>
|
||||||
</Compile>
|
</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>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
||||||
</Project>
|
</Project>
|
31
LCD/LCD/Pin.cpp
Normal file
31
LCD/LCD/Pin.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "Pin.h"
|
||||||
|
|
||||||
|
Pin::Pin(volatile uint8_t *port, uint8_t pin) : m_port(port)
|
||||||
|
, m_pin(pin)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pin::pulse()
|
||||||
|
{
|
||||||
|
*m_port |= (1 << m_pin);
|
||||||
|
*m_port &= ~(1 << m_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pin::set(bool value)
|
||||||
|
{
|
||||||
|
if (value == true)
|
||||||
|
{
|
||||||
|
*m_port |= (1 << m_pin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*m_port &= ~(1 << m_pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pin::toggle()
|
||||||
|
{
|
||||||
|
*m_port ^= (1 << m_pin);
|
||||||
|
}
|
||||||
|
|
17
LCD/LCD/Pin.h
Normal file
17
LCD/LCD/Pin.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
class Pin
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
volatile uint8_t *m_port;
|
||||||
|
uint8_t m_pin;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Pin(volatile uint8_t *port, uint8_t pin);
|
||||||
|
|
||||||
|
void pulse();
|
||||||
|
void set(bool value);
|
||||||
|
void toggle();
|
||||||
|
};
|
20
LCD/LCD/ShiftRegister.cpp
Normal file
20
LCD/LCD/ShiftRegister.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#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
LCD/LCD/ShiftRegister.h
Normal file
19
LCD/LCD/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);
|
||||||
|
};
|
Loading…
Reference in a new issue