590 lines
12 KiB
C
590 lines
12 KiB
C
|
#include "HD44780.h"
|
||
|
|
||
|
//----- Auxiliary data --------------------------//
|
||
|
#define _Byte2Ascii(Value) (Value = Value + '0')
|
||
|
|
||
|
#if (LCD_Size == 801)
|
||
|
#define __LCD_Rows 1
|
||
|
#define __LCD_Columns 8
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#elif (LCD_Size == 802)
|
||
|
#define __LCD_Rows 2
|
||
|
#define __LCD_Columns 8
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#define __LCD_LineStart_2 0x40
|
||
|
#elif (LCD_Size == 1601)
|
||
|
#define __LCD_Rows 1
|
||
|
#define __LCD_Columns 16
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#if (LCD_Type == B)
|
||
|
#define __LCD_LINESTART_1B 0x40
|
||
|
#endif
|
||
|
#elif (LCD_Size == 1602)
|
||
|
#define __LCD_Rows 2
|
||
|
#define __LCD_Columns 16
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#define __LCD_LineStart_2 0x40
|
||
|
#elif (LCD_Size == 1604)
|
||
|
#define __LCD_Rows 4
|
||
|
#define __LCD_Columns 16
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#define __LCD_LineStart_2 0x40
|
||
|
#define __LCD_LineStart_3 0x10
|
||
|
#define __LCD_LineStart_4 0x50
|
||
|
#elif (LCD_Size == 2001)
|
||
|
#define __LCD_Rows 1
|
||
|
#define __LCD_Columns 20
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#elif (LCD_Size == 2002)
|
||
|
#define __LCD_Rows 2
|
||
|
#define __LCD_Columns 20
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#define __LCD_LineStart_2 0x40
|
||
|
#elif (LCD_Size == 2004)
|
||
|
#define __LCD_Rows 4
|
||
|
#define __LCD_Columns 20
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#define __LCD_LineStart_2 0x40
|
||
|
#define __LCD_LineStart_3 0x14
|
||
|
#define __LCD_LineStart_4 0x54
|
||
|
#elif (LCD_Size == 4001)
|
||
|
#define __LCD_Rows 1
|
||
|
#define __LCD_Columns 40
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#elif (LCD_Size == 4002)
|
||
|
#define __LCD_Rows 2
|
||
|
#define __LCD_Columns 40
|
||
|
#define __LCD_LineStart_1 0x00
|
||
|
#define __LCD_LineStart_2 0x40
|
||
|
#endif
|
||
|
//-----------------------------------------------//
|
||
|
|
||
|
//----- Prototypes ----------------------------//
|
||
|
static void LCD_SendCommandHigh(uint8_t Command);
|
||
|
static void LCD_Send(uint8_t Data);
|
||
|
static uint8_t LCD_Read(void);
|
||
|
static inline void Pulse_En(void);
|
||
|
static void Int2bcd(int32_t Value, char *BCD);
|
||
|
//---------------------------------------------//
|
||
|
|
||
|
//----- Functions -------------//
|
||
|
//Setup LCD.
|
||
|
void LCD_Setup(void)
|
||
|
{
|
||
|
//LCD pins = Outputs
|
||
|
PinMode(LCD_D4, Output);
|
||
|
PinMode(LCD_D5, Output);
|
||
|
PinMode(LCD_D6, Output);
|
||
|
PinMode(LCD_D7, Output);
|
||
|
PinMode(LCD_RS, Output);
|
||
|
PinMode(LCD_RW, Output);
|
||
|
PinMode(LCD_EN, Output);
|
||
|
|
||
|
//LCD pins = 0
|
||
|
DigitalWrite(LCD_D4, Low);
|
||
|
DigitalWrite(LCD_D5, Low);
|
||
|
DigitalWrite(LCD_D6, Low);
|
||
|
DigitalWrite(LCD_D7, Low);
|
||
|
DigitalWrite(LCD_RS, Low);
|
||
|
DigitalWrite(LCD_RW, Low);
|
||
|
DigitalWrite(LCD_EN, Low);
|
||
|
|
||
|
//----- Soft reset -----
|
||
|
//1. Wait for more than 15ms
|
||
|
_delay_ms(__LCD_Delay_1);
|
||
|
//2. Command 32: LCD 8-bit mode
|
||
|
LCD_SendCommandHigh(__LCD_CMD_FunctionSet | __LCD_CMD_8BitMode);
|
||
|
//3. Wait for more than 4.1ms
|
||
|
_delay_ms(__LCD_Delay_2);
|
||
|
//4. Command 32: LCD 8-bit mode
|
||
|
LCD_SendCommandHigh(__LCD_CMD_FunctionSet | __LCD_CMD_8BitMode);
|
||
|
//5. Wait for more than 100us
|
||
|
_delay_ms(__LCD_Delay_3);
|
||
|
//6. Command 32: LCD 8-bit mode, for the 3rd time
|
||
|
LCD_SendCommandHigh(__LCD_CMD_FunctionSet | __LCD_CMD_8BitMode);
|
||
|
//7. Wait for more than 100us
|
||
|
_delay_ms(__LCD_Delay_4);
|
||
|
|
||
|
//----- Initialization -----
|
||
|
//1. Command 32: LCD mode
|
||
|
LCD_SendCommandHigh(__LCD_CMD_FunctionSet | __LCD_CMD_4BitMode);
|
||
|
//2. Command 32: LCD mode and size
|
||
|
LCD_SendCommand(__LCD_CMD_FunctionSet | __LCD_CMD_4BitMode | __LCD_CMD_2Line | __LCD_CMD_5x8Dots);
|
||
|
//3. Command 8: Display On, Cursor off, Blinking Off
|
||
|
LCD_SendCommand(__LCD_CMD_DisplayControl | __LCD_CMD_DisplayOn | __LCD_CMD_CursorOff | __LCD_CMD_BlinkOff);
|
||
|
//4. Command 4: Auto increment, No shifting
|
||
|
LCD_SendCommand(__LCD_CMD_EntryModeSet | __LCD_CMD_EntryIncrement | __LCD_CMD_EntryNoShift);
|
||
|
//5. Command 1: Clear display, cursor at home
|
||
|
LCD_SendCommand(__LCD_CMD_ClearDisplay);
|
||
|
}
|
||
|
|
||
|
//Send command to LCD.
|
||
|
void LCD_SendCommand(uint8_t Command)
|
||
|
{
|
||
|
LCD_WaitBusy();
|
||
|
|
||
|
DigitalWrite(LCD_RS, Low);
|
||
|
LCD_Send(Command);
|
||
|
}
|
||
|
|
||
|
//Send data to LCD.
|
||
|
void LCD_SendData(char c)
|
||
|
{
|
||
|
LCD_WaitBusy();
|
||
|
|
||
|
DigitalWrite(LCD_RS, High);
|
||
|
LCD_Send((uint8_t)(c));
|
||
|
}
|
||
|
|
||
|
//Wait until busy flag is cleared.
|
||
|
void LCD_WaitBusy(void)
|
||
|
{
|
||
|
uint8_t busy = 0;
|
||
|
|
||
|
PinMode(LCD_D4, Input); //D7:D4 = Inputs
|
||
|
PinMode(LCD_D5, Input);
|
||
|
PinMode(LCD_D6, Input);
|
||
|
PinMode(LCD_D7, Input);
|
||
|
DigitalWrite(LCD_RS, Low); //RS=0
|
||
|
DigitalWrite(LCD_RW, High); //RW=1
|
||
|
|
||
|
do
|
||
|
{
|
||
|
//High nibble comes first
|
||
|
DigitalWrite(LCD_EN, High);
|
||
|
_delay_us(__LCD_Pulse_us);
|
||
|
busy &= ~(1<<__LCD_BusyFlag);
|
||
|
busy |= (DigitalRead(LCD_D7)<<__LCD_BusyFlag);
|
||
|
DigitalWrite(LCD_EN, Low);
|
||
|
|
||
|
//Low nibble follows
|
||
|
Pulse_En();
|
||
|
}
|
||
|
while(BitCheck(busy, __LCD_BusyFlag));
|
||
|
|
||
|
PinMode(LCD_D4, Output); //D7:D4 = Outputs
|
||
|
PinMode(LCD_D5, Output);
|
||
|
PinMode(LCD_D6, Output);
|
||
|
PinMode(LCD_D7, Output);
|
||
|
DigitalWrite(LCD_RW, Low); //RW = 0
|
||
|
}
|
||
|
|
||
|
//Build character in LCD CGRAM from data in SRAM.
|
||
|
void LCD_BuildChar(char *Data, uint8_t Position)
|
||
|
{
|
||
|
if (Position < 0)
|
||
|
return;
|
||
|
if (Position >= 8)
|
||
|
return;
|
||
|
|
||
|
Point_t p = LCD_GetP();
|
||
|
uint8_t i;
|
||
|
|
||
|
//Every character in CGRAM needs 8bytes
|
||
|
LCD_SendCommand(__LCD_CMD_SetCGRAMAddress | (Position<<3));
|
||
|
|
||
|
//Save the character byte-by-byte
|
||
|
for (i = 0 ; i < 8 ; i++)
|
||
|
LCD_SendData(Data[i]);
|
||
|
|
||
|
//Return to the DDRAM position
|
||
|
LCD_GotoXY(p.X, p.Y);
|
||
|
}
|
||
|
|
||
|
//Build character in LCD CGRAM from data in Flash memory.
|
||
|
void LCD_BuildChar_P(const char *Data, uint8_t Position)
|
||
|
{
|
||
|
if (Position < 0)
|
||
|
return;
|
||
|
if (Position >= 8)
|
||
|
return;
|
||
|
|
||
|
Point_t p = LCD_GetP();
|
||
|
uint8_t i;
|
||
|
|
||
|
//Every character in CGRAM needs 8bytes
|
||
|
LCD_SendCommand(__LCD_CMD_SetCGRAMAddress | (Position<<3));
|
||
|
|
||
|
//Save the character byte-by-byte
|
||
|
for (i = 0 ; i < 8 ; i++)
|
||
|
LCD_SendData(pgm_read_byte(Data[i]));
|
||
|
|
||
|
//Return to the DDRAM position
|
||
|
LCD_GotoXY(p.X, p.Y);
|
||
|
}
|
||
|
|
||
|
//Clear display.
|
||
|
void LCD_Clear(void)
|
||
|
{
|
||
|
LCD_SendCommand(__LCD_CMD_ClearDisplay);
|
||
|
}
|
||
|
|
||
|
//Clear line.
|
||
|
void LCD_ClearLine(uint8_t Line)
|
||
|
{
|
||
|
uint8_t i = 0;
|
||
|
|
||
|
LCD_GotoXY(0, Line);
|
||
|
while(i <= __LCD_Columns)
|
||
|
{
|
||
|
LCD_SendData(' ');
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Go to specified position.
|
||
|
void LCD_GotoXY(uint8_t X, uint8_t Y)
|
||
|
{
|
||
|
if ((X < __LCD_Columns) && (Y < __LCD_Rows))
|
||
|
{
|
||
|
uint8_t addr = 0;
|
||
|
switch (Y)
|
||
|
{
|
||
|
#if ((defined(__LCD_LineStart_4)) || (defined(__LCD_LineStart_3)) || (defined(__LCD_LineStart_2)) || (defined(__LCD_LineStart_1)))
|
||
|
case (0):
|
||
|
addr = __LCD_LineStart_1;
|
||
|
#if ((LCD_Size == 1601) && (LCD_Type == B))
|
||
|
if (X >= (__LCD_Columns>>1))
|
||
|
{
|
||
|
X -= __LCD_Columns>>1;
|
||
|
addr = __LCD_LINESTART_1B;
|
||
|
}
|
||
|
#endif
|
||
|
break;
|
||
|
#endif
|
||
|
#if ((defined(__LCD_LineStart_4)) || (defined(__LCD_LineStart_3)) || (defined(__LCD_LineStart_2)))
|
||
|
case (1):
|
||
|
addr = __LCD_LineStart_2;
|
||
|
break;
|
||
|
#endif
|
||
|
#if ((defined(__LCD_LineStart_4)) || (defined(__LCD_LineStart_3)))
|
||
|
case (2):
|
||
|
addr = __LCD_LineStart_3;
|
||
|
break;
|
||
|
#endif
|
||
|
#if (defined(__LCD_LineStart_4))
|
||
|
case (3):
|
||
|
addr = __LCD_LineStart_4;
|
||
|
break;
|
||
|
#endif
|
||
|
}
|
||
|
addr = __LCD_CMD_SetDDRAMAddress | (addr | X);
|
||
|
LCD_SendCommand(addr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Get current position.
|
||
|
Point_t LCD_GetP(void)
|
||
|
{
|
||
|
Point_t p;
|
||
|
|
||
|
p.X = LCD_Read();
|
||
|
p.Y = 0;
|
||
|
#if (__LCD_Rows == 1)
|
||
|
#if ((LCD_Size == 1601) && (LCD_Type == B))
|
||
|
if (p.X >= __LCD_LINESTART_1B)
|
||
|
p.X = p.X - __LCD_LINESTART_1B + (__LCD_Columns>>1);
|
||
|
#endif
|
||
|
#elif (__LCD_Rows == 2)
|
||
|
if (p.X >= __LCD_LineStart_2)
|
||
|
{
|
||
|
p.X -= __LCD_LineStart_2;
|
||
|
p.Y = 1;
|
||
|
}
|
||
|
#elif (__LCD_Rows == 3)
|
||
|
if (p.X >= __LCD_LineStart_2)
|
||
|
{
|
||
|
p.X -= __LCD_LineStart_2;
|
||
|
p.Y = 1;
|
||
|
}
|
||
|
else if (p.X >= __LCD_LineStart_3)
|
||
|
{
|
||
|
p.X -= __LCD_LineStart_3;
|
||
|
p.Y = 2;
|
||
|
}
|
||
|
#elif (__LCD_Rows == 4)
|
||
|
if (p.X >= __LCD_LineStart_4)
|
||
|
{
|
||
|
p.X -= __LCD_LineStart_4;
|
||
|
p.Y = 3;
|
||
|
}
|
||
|
else if (p.X >= __LCD_LineStart_2)
|
||
|
{
|
||
|
p.X -= __LCD_LineStart_2;
|
||
|
p.Y = 1;
|
||
|
}
|
||
|
else if (p.X >= __LCD_LineStart_3)
|
||
|
{
|
||
|
p.X -= __LCD_LineStart_3;
|
||
|
p.Y = 2;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
//Get X position.
|
||
|
uint8_t LCD_GetX(void)
|
||
|
{
|
||
|
return LCD_GetP().X;
|
||
|
}
|
||
|
|
||
|
//Get Y position.
|
||
|
uint8_t LCD_GetY(void)
|
||
|
{
|
||
|
return LCD_GetP().Y;
|
||
|
}
|
||
|
|
||
|
//Print character.
|
||
|
void LCD_PrintChar(char Character)
|
||
|
{
|
||
|
LCD_SendData(Character);
|
||
|
}
|
||
|
|
||
|
//Print string from SRAM.
|
||
|
void LCD_PrintString(char *Text)
|
||
|
{
|
||
|
while(*Text)
|
||
|
LCD_SendData(*Text++);
|
||
|
}
|
||
|
|
||
|
//Print string from Flash memory.
|
||
|
void LCD_PrintString_P(const char *Text)
|
||
|
{
|
||
|
char r = pgm_read_byte(Text++);
|
||
|
while(r)
|
||
|
{
|
||
|
LCD_SendData(r);
|
||
|
r = pgm_read_byte(Text++);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Print integer.
|
||
|
void LCD_PrintInteger(int32_t Value)
|
||
|
{
|
||
|
if (Value == 0 )
|
||
|
{
|
||
|
LCD_PrintChar('0');
|
||
|
}
|
||
|
else if ((Value > INT32_MIN ) && (Value <= INT32_MAX))
|
||
|
{
|
||
|
//int32_max + sign + null = 12 bytes
|
||
|
char arr[12] = { '\0' };
|
||
|
|
||
|
//Convert integer to array (returns in reversed order)
|
||
|
Int2bcd(Value, arr);
|
||
|
|
||
|
//Print
|
||
|
LCD_PrintString(arr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Print double.
|
||
|
void LCD_PrintDouble(double Value, uint32_t Tens)
|
||
|
{
|
||
|
if (Value == 0)
|
||
|
{
|
||
|
//Print characters individually so no string is stored into RAM.
|
||
|
LCD_PrintChar('0');
|
||
|
LCD_PrintChar('.');
|
||
|
LCD_PrintChar('0');
|
||
|
}
|
||
|
else if ((Value >= (-2147483647)) && (Value < 2147483648))
|
||
|
{
|
||
|
//Print sign
|
||
|
if (Value < 0)
|
||
|
{
|
||
|
Value = -Value;
|
||
|
LCD_PrintChar('-');
|
||
|
}
|
||
|
|
||
|
//Print integer part
|
||
|
LCD_PrintInteger(Value);
|
||
|
|
||
|
//Print dot
|
||
|
LCD_PrintChar('.');
|
||
|
|
||
|
//Print decimal part
|
||
|
LCD_PrintInteger((Value - (uint32_t)(Value)) * Tens);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Send only high nibble to LCD.
|
||
|
static void LCD_SendCommandHigh(uint8_t Data)
|
||
|
{
|
||
|
DigitalWrite(LCD_RS, Low);
|
||
|
|
||
|
//Send the high nibble
|
||
|
DigitalWrite(LCD_D4, BitCheck(Data, 4));
|
||
|
DigitalWrite(LCD_D5, BitCheck(Data, 5));
|
||
|
DigitalWrite(LCD_D6, BitCheck(Data, 6));
|
||
|
DigitalWrite(LCD_D7, BitCheck(Data, 7));
|
||
|
Pulse_En();
|
||
|
}
|
||
|
|
||
|
//Send data to LCD.
|
||
|
static void LCD_Send(uint8_t Data)
|
||
|
{
|
||
|
//Send the high nibble
|
||
|
DigitalWrite(LCD_D4, BitCheck(Data, 4));
|
||
|
DigitalWrite(LCD_D5, BitCheck(Data, 5));
|
||
|
DigitalWrite(LCD_D6, BitCheck(Data, 6));
|
||
|
DigitalWrite(LCD_D7, BitCheck(Data, 7));
|
||
|
Pulse_En();
|
||
|
|
||
|
//Low nibble comes after
|
||
|
DigitalWrite(LCD_D4, BitCheck(Data, 0));
|
||
|
DigitalWrite(LCD_D5, BitCheck(Data, 1));
|
||
|
DigitalWrite(LCD_D6, BitCheck(Data, 2));
|
||
|
DigitalWrite(LCD_D7, BitCheck(Data, 3));
|
||
|
Pulse_En();
|
||
|
}
|
||
|
|
||
|
//Read status from LCD.
|
||
|
static uint8_t LCD_Read(void)
|
||
|
{
|
||
|
uint8_t status = 0;
|
||
|
|
||
|
LCD_WaitBusy();
|
||
|
|
||
|
PinMode(LCD_D4, Input); //D7:D4 = Inputs
|
||
|
PinMode(LCD_D5, Input);
|
||
|
PinMode(LCD_D6, Input);
|
||
|
PinMode(LCD_D7, Input);
|
||
|
DigitalWrite(LCD_RS, Low); //RS = 0
|
||
|
DigitalWrite(LCD_RW, High); //RW = 1
|
||
|
|
||
|
//High nibble comes first
|
||
|
DigitalWrite(LCD_EN, High);
|
||
|
_delay_us(__LCD_Pulse_us);
|
||
|
status |= DigitalRead(LCD_D4)<<4;
|
||
|
status |= DigitalRead(LCD_D5)<<5;
|
||
|
status |= DigitalRead(LCD_D6)<<6;
|
||
|
DigitalWrite(LCD_EN, Low);
|
||
|
|
||
|
//Low nibble follows
|
||
|
DigitalWrite(LCD_EN, High);
|
||
|
_delay_us(__LCD_Pulse_us);
|
||
|
status |= DigitalRead(LCD_D4);
|
||
|
status |= DigitalRead(LCD_D5)<<1;
|
||
|
status |= DigitalRead(LCD_D6)<<2;
|
||
|
status |= DigitalRead(LCD_D7)<<3;
|
||
|
DigitalWrite(LCD_EN, Low);
|
||
|
|
||
|
PinMode(LCD_D4, Output); //D7:D4 = Outputs
|
||
|
PinMode(LCD_D5, Output);
|
||
|
PinMode(LCD_D6, Output);
|
||
|
PinMode(LCD_D7, Output);
|
||
|
DigitalWrite(LCD_RW, Low); //RW = 0
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
//Sends pulse to PIN_EN of LCD.
|
||
|
static inline void Pulse_En(void)
|
||
|
{
|
||
|
DigitalWrite(LCD_EN, High);
|
||
|
_delay_us(__LCD_Pulse_us);
|
||
|
DigitalWrite(LCD_EN, Low);
|
||
|
}
|
||
|
|
||
|
//Converts integer value to BCD.
|
||
|
static void Int2bcd(int32_t Value, char BCD[])
|
||
|
{
|
||
|
uint8_t isNegative = 0;
|
||
|
|
||
|
BCD[0] = BCD[1] = BCD[2] =
|
||
|
BCD[3] = BCD[4] = BCD[5] =
|
||
|
BCD[6] = BCD[7] = BCD[8] =
|
||
|
BCD[9] = BCD[10] = '0';
|
||
|
|
||
|
if (Value < 0)
|
||
|
{
|
||
|
isNegative = 1;
|
||
|
Value = -Value;
|
||
|
}
|
||
|
|
||
|
while (Value > 1000000000)
|
||
|
{
|
||
|
Value -= 1000000000;
|
||
|
BCD[1]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 100000000)
|
||
|
{
|
||
|
Value -= 100000000;
|
||
|
BCD[2]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 10000000)
|
||
|
{
|
||
|
Value -= 10000000;
|
||
|
BCD[3]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 1000000)
|
||
|
{
|
||
|
Value -= 1000000;
|
||
|
BCD[4]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 100000)
|
||
|
{
|
||
|
Value -= 100000;
|
||
|
BCD[5]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 10000)
|
||
|
{
|
||
|
Value -= 10000;
|
||
|
BCD[6]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 1000)
|
||
|
{
|
||
|
Value -= 1000;
|
||
|
BCD[7]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 100)
|
||
|
{
|
||
|
Value -= 100;
|
||
|
BCD[8]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 10)
|
||
|
{
|
||
|
Value -= 10;
|
||
|
BCD[9]++;
|
||
|
}
|
||
|
|
||
|
while (Value >= 1)
|
||
|
{
|
||
|
Value -= 1;
|
||
|
BCD[10]++;
|
||
|
}
|
||
|
|
||
|
uint8_t i = 0;
|
||
|
//Find first non zero digit
|
||
|
while (BCD[i] == '0')
|
||
|
i++;
|
||
|
|
||
|
//Add sign
|
||
|
if (isNegative)
|
||
|
{
|
||
|
i--;
|
||
|
BCD[i] = '-';
|
||
|
}
|
||
|
|
||
|
//Shift array
|
||
|
uint8_t end = 10 - i;
|
||
|
uint8_t offset = i;
|
||
|
i = 0;
|
||
|
while (i <= end)
|
||
|
{
|
||
|
BCD[i] = BCD[i + offset];
|
||
|
i++;
|
||
|
}
|
||
|
BCD[i] = '\0';
|
||
|
}
|
||
|
//-----------------------------//
|