Digital 2 channel 10 Amp Meter
History
This project is a 2 channels amp meter. Those channels are completely isolated up to 2000 volts. I'm sure you don't need isolation like this but it could be very interesting to measure the charge current for 110V AC input or on the output of something like 12V DC. That is, it provides auto detection for AC or DC current. The main part of this project is the current sensor ZMC10 a cool DIP 14, which supports up to 10 A. The current is measured inside by hall effect sensor. I had used a graphic LCD to show very big numbers of the read current and max peek value, DC or AC
Ok now, this was supposed to be simple, but I had to overcome a
lot of problems doing this project. First the datasheet of the ZMC10
have a big 2 pages!
How an IC like that can have 2 pages documentation when LED
datasheet have more than 15 pages? Not having proper documentation
was my biggest challenge. First the slope is non linear I had to
make calibration at first to use it from 0 to 10 amps. The software
calculates the slope from 0 to 1, 1 to 2, 2 to 3, with the formula
Y2 - Y1 / X2 - X1 | B = Y - M * X | X = Y - B / M | Y = M
* X + B. After I faced another problem, any metal pieces from 2
inches will completely false the reading. For example, if your
charge is 5 A. Moving a screw driver at 2 inches of the ZMC10 you
will give something like 1A or less. The other problem that I had
faced is if the 2 sensors are closed to each other the current will
interfere and will give you false reading. I had to rebuild another
PCB for that to separate each channel. Also at 0 A the sensor will
not give you zero, you must calculate the offset from one part to
the other since the values are not the same. In last all the
values, slopes and offset are not the same if the current pass from
A to B or B to A. I think this caused enough problems for a simple
amp meter.
The MCU has two jobs: measure (calculate) the value from the analog board and display that value. I drove the LCD in graphical mode. I had written the character generator for fonts 1x, 2x and 4x other function like draw line, square, clear screen and more. Also the MCU board has the power supply for itself and for the analog part.
Features
|
|
2 Channel |
|
|
From 0 to 10amp |
|
|
Resolution of 0.1amp |
|
|
Isolation between each channel of 2000 volt |
|
|
Automatic AD/DC detection |
|
|
Very big LCD and character |
Pictures
Click to enlarge
|
Analog part 1 of 2 |
Graphic LCD with a SED1330 |
MCU board mounted on back of the LCD |
Click to enlarge
|
Analog part 1 of 2 |
Final work in right position |
Final work in slope position |
Sources codes & Schematics
-Schematic of the Digital part
//*****************************************************************************
// AmpVoltMeter
// Version 10.0 Janv 2007
//
// 1.0 -> New code
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
//
R E T U R N S T A C K 6 4
//
X T A L 16 MHZ
//
BootLoader of 1024 word
//
//*****************************************************************************
//
//
F U S E B I T
//
//( )7 ( )6
(X)BL12 (X)BL11 ( )BL02 ( )BL01
( )Lock2 ( )Lock1
//( )7 ( )6
( ) ( ) ( )
( )M103C ( )WDTON ( )
//( )RSTDIS ( )WDON (X)SPIEN(X)CKOPT
(X)EESAVE ( )BOOTSZ1 (X)BOOTSZ0 (X)BOOTRST
//(X)BODLEV (X)BODEN ( )SUT1 ( )SUT0
( )CKSEL3 ( )CKSEL2 ( )CKSEL1 ( )CKSEL0
//
//*****************************************************************************
//
P I N U S A G E
//
// PA0 -> Key Switch SW7
// PA1 -> Key Switch SW8
// PA2 -> Key Switch SW9
// PA3 -> Key Switch SW1
// PA4 -> Key Switch SW2
// PA5 -> Key Switch SW3
// PA6 -> Key Switch SW4
// PA7 -> Key Switch SW5
//
// PB0 -> n/c
// PB1 -> n/c
// PB2 -> n/c
// PB3 -> n/c
// PB4 -> n/c
// PB5 -> n/c
// PB6 -> LCD BackLight
// PB7 -> Piezo
//
// PC0 -> LCD Data bit 0
// PC1 -> LCD Data bit 1
// PC2 -> LCD Data bit 2
// PC3 -> LCD Data bit 3
// PC4 -> LCD Data bit 4
// PC5 -> LCD Data bit 5
// PC6 -> LCD Data bit 6
// PC7 -> LCD Data bit 7
//
// PD0 -> n/c
// PD1 -> n/c
// PD2 -> RS485 RX
// PD3 -> RS485 TX
// PD4 -> RS485 TXE
// PD5 -> LCD RESET
// PD6 -> LCD RD
// PD7 -> LCD WR
//
// PE0 -> n/c
// PE1 -> n/c
// PE2 -> n/c
// PE3 -> n/c
// PE4 -> n/c
// PE5 -> n/c
// PE6 -> n/c
// PE7 -> n/c
//
// PF0 -> n/c
// PF1 -> n/c
// PF2 -> n/c
// PF3 -> n/c
// PF4 -> n/c
// PF5 -> n/c
// PF6 -> Key Switch SW10
// PF7 -> Key Switch SW6
//
// PG0 -> LCD A0
// PG1 -> n/c
// PG2 -> n/c
// PG3 -> n/c
// PG4 -> n/c
//*****************************************************************************
//
T I M E R U S A G E
//
// Timer 0 is use by TaskManager
// Timer 1 is use for Sound generetor
1.265KHz
// Timer 2 not use
// Timer 3 not use
//
//*****************************************************************************
//*****************************************************************************
//
I N C L U D E
//*****************************************************************************
#include <iom32v.h>
#include <shortnametype.h>
#include <macros.h>
#include <stdlib.h>
#include <STRING.H>
#include <stdio.h>
#include <eeprom.h>
#include "TaskManager.h"
//*****************************************************************************
//
D E F I N E
//*****************************************************************************
#define VERSION
100
#define DEVICE
1280
#define XTAL
8000000
// ADC
#define ADC0
(1<<REFS0) + 0
#define ADC1
(1<<REFS0) + 1
#define ADC2
(1<<REFS0) + 2
#define ADC3
(1<<REFS0) + 3
#define ADC4
(1<<REFS0) + 4
#define ADC5
(1<<REFS0) + 5
#define ADC6
(1<<REFS0) + 6
#define ADC7
(1<<REFS0) + 7
// LCD
#define LCDDATA_DDR
DDRC
#define LCDDATA_PIN
PINC
#define LCDDATA_PORT
PORTC
#define LCDCTRL_DDR
DDRD
#define LCDCTRL_PIN
PIND
#define LCDCTRL_PORT
PORTD
#define LCD_A0
(1<<PD4)
#define LCD_WR
(1<<PD5)
#define LCD_RD
(1<<PD6)
#define LCD_RES
(1<<PD7)
#define LCD_X
256
#define LCD_Y
128
#define LCD_XTAL
6000000
#define FONT_1X
1
#define FONT_2X
2
#define FONT_4X
4
// Switch
#define SWITCH_DDR
DDRB
#define SWITCH_PIN
PINB
#define SWITCH_PORT
PORTB
#define LEFT
0x01
#define RIGHT
0x02
#define BOTH
0x03
// Eprom
#define SLOPE1
0
#define SLOPE2
50
#define SLOPE3
100
#define SLOPE4
150
#define FOWARD
0
#define REVERSE
1
// Interrupt
#define INT_DDR
DDRD
#define INT_PIN
PIND
#define INT_PORT
PORTD
#define INT_INPUT_0
0x04
#define INT_INPUT_1
0x08
// AC/DC
#define AC
TRUE
#define DC
FALSE
//**************************************
//
P R O T O T LCD_Y P E
//**************************************
void InitCode(void);
void RedrawTick(void);
void Delay(ushort
Del);
void IntInit(void);
void SplashScreen(void);
void DrawScreen(void);
void DrawDC1(void);
void DrawDC2(void);
void DrawAC1(void);
void DrawAC2(void);
void LoadSlope(ushort
Polarity);
void CalculateMB(void);
void Calibration(void);
void PrintAmp1(int
X, int Y,
uint Value, int Size,
ushort ACDC);
void PrintAmp2(int
X, int Y,
uint Value, int Size,
ushort ACDC);
// Slope
float SlopeGetM
(float X1,
float Y1, float X2,
float Y2);
float SlopeGetB
(float X,
float Y, float M);
float SlopeGetX
(float Y,
float B, float M);
float SlopeGetY
(float X,
float B, float M);
// LCD
void LCDInit(void);
void LCDWriteData(ushort
byte);
void LCDWriteCmd(ushort
byte);
ushort LCDReadData(void);
void LCDClrSCR(void);
void LCDGotoXY(ushort,
ushort);
void LCDWriteString(char
*ptr);
void LCDWriteConstString(const
char *ptr);
void LCDCursor(ushort
LCDCursor);
void LCDTextBox(int
x, int y,
int length,int
stat);
void LCDDelay2ms(void);
void LCDDelay1us(void);
void LCDGraphClrSCR(void);
void LCDGraphGotoXY(ushort
x, ushort y);
void LcdGraphString
(ushort X,
ushort Y, ushort Size,
char *Ptr );
void LcdGraphConstString
(ushort X,
ushort Y, ushort Size,
const char *Ptr );
void LcdGraphChr(ushort
X, ushort Y,
ushort Size, char Ch);
void LCDGraphSetRamPointer(int
Address);
void LCDGraphPix(int
x, int y,
ushort stat);
void LCDGraphBox(int
x1, int y1,
int x2, int y2,int
stat);
void LCDGraphLine(int
x1, int y1,
int x2, int y2);
// ADC
void ADInit(void);
void AD_interrupt(void);
// Switch
void SwitchInit(void);
void SwitchScan(void);
// AD/DC
void Int_0_AC(void);
void Int_1_AC(void);
void CheckAC(void);
//*****************************************************************************
//
C O N S T A N T
//*****************************************************************************
static const ushort FontLookup
[][7]
=
{
{
0x00, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00 },
// Space
{ 0x04,
0x04,
0x04,
0x04,
0x04,
0x00,
0x04 },
// !
{ 0x0A,
0x0A,
0x0A,
0x00,
0x00,
0x00,
0x00 },
// "
{ 0x0A,
0x0A,
0x1F,
0x0A,
0x1F,
0x0A,
0x0A },
// #
{
0x04,
0x0F,
0x14,
0x0E,
0x05,
0x1E,
0x04 },
// $
{
0x18,
0x19,
0x02,
0x04,
0x08,
0x13,
0x03 },
// %
{
0x0C,
0x12,
0x14,
0x08,
0x15,
0x12,
0x0D },
// &
{
0x0C,
0x04,
0x08,
0x00,
0x00,
0x00,
0x00 },
// '
{
0x02,
0x04,
0x08,
0x08,
0x08,
0x04,
0x02 },
// (
{
0x08, 0x04,
0x02,
0x02,
0x02,
0x04,
0x08 },
// )
{ 0x00,
0x04,
0x15,
0x0E,
0x15,
0x04,
0x00 },
// *
{ 0x00,
0x04,
0x04,
0x1F,
0x04,
0x04,
0x00 },
// +
{ 0x00,
0x00,
0x00,
0x00,
0x00,
0x0C,
0x04 },
// ,
{
0x00,
0x00,
0x00,
0x1F,
0x00,
0x00,
0x00 },
// -
{
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x0C },
// .
{
0x00,
0x01,
0x02,
0x04,
0x08,
0x10,
0x00 },
// /
{
0x0E,
0x11,
0x13,
0x15,
0x19,
0x11,
0x0E },
// 0
{
0x04,
0x0C,
0x04,
0x04,
0x04,
0x04,
0x0E },
// 1
{ 0x0E,
0x11,
0x02,
0x04,
0x08,
0x10,
0x1F },
// 2
{ 0x1F,
0x02,
0x04,
0x02,
0x01,
0x11,
0x0E },
// 3
{ 0x02,
0x06,
0x0A,
0x12,
0x1F,
0x02,
0x02 },
// 4
{
0x1F,
0x10,
0x1E,
0x01,
0x01,
0x11,
0x0E },
// 5
{
0x06,
0x08,
0x10,
0x1E,
0x11,
0x11,
0x0E },
// 6
{
0x1F,
0x01,
0x02,
0x04,
0x08,
0x08,
0x08 },
// 7
{
0x0E,
0x11,
0x11,
0x0E,
0x11,
0x11,
0x0E },
// 8
{
0x0E,
0x11,
0x11,
0x0F,
0x01,
0x02,
0x0C },
// 9
{ 0x00,
0x0C,
0x0C,
0x00,
0x0C,
0x0C,
0x00 },
// :
{ 0x00,
0x0C,
0x0C,
0x00,
0x0C,
0x04,
0x08 },
// ;
{ 0x01,
0x02,
0x04,
0x08,
0x04,
0x02,
0x01 },
// <
{
0x00,
0x00,
0x1F,
0x00,
0x1F,
0x00,
0x00 },
// =
{
0x10,
0x08,
0x04,
0x02,
0x04,
0x08,
0x10 },
// >
{
0x0E,
0x11,
0x01,
0x02,
0x04,
0x00,
0x04 },
// ?
{
0x0E,
0x11,
0x17,
0x15,
0x17,
0x10,
0x0E },
// @
{
0x0E,
0x11,
0x11,
0x11,
0x1F,
0x11,
0x11 },
// A
{ 0x1E,
0x11,
0x11,
0x1E,
0x11,
0x11,
0x1E },
// B
{ 0x0E,
0x11,
0x10,
0x10,
0x10,
0x11,
0x0E },
// C
{ 0x1C,
0x12,
0x11,
0x11,
0x11,
0x12,
0x1C },
// D
{
0x1F,
0x10,
0x10,
0x1E,
0x10,
0x10,
0x1F },
// E
{
0x1F,
0x10,
0x10,
0x1E,
0x10,
0x10,
0x10 },
// F
{
0x0E,
0x11,
0x10,
0x17,
0x11,
0x11,
0x0F },
// G
{
0x11,
0x11,
0x11,
0x1F,
0x11,
0x11,
0x11 },
// H
{
0x0E,
0x04,
0x04,
0x04,
0x04,
0x04,
0x0E },
// I
{ 0x07,
0x02,
0x02,
0x02,
0x02,
0x12,
0x0C },
// J
{ 0x11,
0x12,
0x14,
0x18,
0x14,
0x12,
0x11 },
// K
{ 0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x1F },
// L
{
0x11,
0x1B,
0x15,
0x15,
0x11,
0x11,
0x11 },
// M
{
0x11,
0x11,
0x19,
0x15,
0x13,
0x11,
0x11 },
// N
{
0x0E,
0x11,
0x11,
0x11,
0x11,
0x11,
0x0E },
// O
{
0x1E,
0x11,
0x11,
0x1E,
0x10,
0x10,
0x10 },
// P
{
0x0E,
0x11,
0x11,
0x11,
0x15,
0x12,
0x0D },
// Q
{ 0x1E,
0x11,
0x11,
0x1E,
0x14,
0x12,
0x11 },
// R
{ 0x0E,
0x11,
0x10,
0x0E,
0x01,
0x11,
0x0E },
// S
{ 0x1F,
0x04,
0x04,
0x04,
0x04,
0x04,
0x04 },
// T
{
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x0E },
// U
{
0x11,
0x11,
0x11,
0x11,
0x11,
0x0A,
0x04 },
// V
{
0x11,
0x11,
0x11,
0x11,
0x15,
0x15,
0x0A },
// W
{
0x11,
0x11,
0x0A,
0x04,
0x0A,
0x11,
0x11 },
// X
{
0x11,
0x11,
0x11,
0x0A,
0x04,
0x04,
0x04 },
// Y
{ 0x1F,
0x01,
0x02,
0x04,
0x08,
0x10,
0x1F },
// Z
{ 0x0E,
0x08,
0x08,
0x08,
0x08,
0x08,
0x0E },
// [
{ 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00 },
// Space
{
0x0E,
0x02,
0x02,
0x02,
0x02,
0x02,
0x0E },
// ]
{
0x04,
0x0A,
0x11,
0x00,
0x00,
0x00,
0x00 },
// ^
{
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x1F },
// _
{
0x06,
0x04,
0x02,
0x00,
0x00,
0x00,
0x00 },
// `
{
0x00,
0x00,
0x0E,
0x01,
0x0F,
0x11,
0x0F },
// a
{ 0x10,
0x10,
0x1E,
0x11,
0x11,
0x11,
0x1E },
// b
{ 0x00,
0x00,
0x0F,
0x10,
0x10,
0x10,
0x0F },
// c
{ 0x01,
0x01,
0x0F,
0x11,
0x11,
0x11,
0x0F },
// d
{
0x00,
0x00,
0x0E,
0x11,
0x1E,
0x10,
0x0E },
// f
{
0x03,
0x04,
0x1F,
0x04,
0x04,
0x04,
0x04 },
// e
{
0x00,
0x00,
0x0F,
0x11,
0x0F,
0x01,
0x0E },
// g
{
0x10,
0x10,
0x16,
0x19,
0x11,
0x11,
0x11 },
// h
{
0x04,
0x00,
0x0C,
0x04,
0x04,
0x04,
0x0E },
// i
{ 0x02,
0x00,
0x06,
0x02,
0x02,
0x12,
0x0C },
// j
{ 0x10,
0x10,
0x12,
0x14,
0x18,
0x14,
0x12 },
// k
{ 0x0C,
0x04,
0x04,
0x04,
0x04,
0x04,
0x0E },
// l
{
0x00,
0x00,
0x1E,
0x15,
0x15,
0x15,
0x15 },
// m
{
0x00,
0x00,
0x16,
0x19,
0x11,
0x11,
0x11 },
// n
{
0x00,
0x00,
0x0E,
0x11,
0x11,
0x11,
0x0E },
// o
{
0x00,
0x00,
0x1E,
0x11,
0x1E,
0x10,
0x10 },
// p
{
0x00,
0x00,
0x0F,
0x11,
0x0F,
0x01,
0x01 },
// q
{ 0x00,
0x00,
0x16,
0x18,
0x10,
0x10,
0x10 },
// r
{ 0x00,
0x00,
0x0F,
0x10,
0x0E,
0x01,
0x1E },
// s
{ 0x04,
0x04,
0x1F,
0x04,
0x04,
0x04,
0x03 },
// t
{
0x00,
0x00,
0x11,
0x11,
0x11,
0x13,
0x0D },
// u
{
0x00,
0x00,
0x11,
0x11,
0x11,
0x0A,
0x04 },
// v
{
0x00,
0x00,
0x11,
0x11,
0x15,
0x15,
0x0A },
// w
{
0x00,
0x00,
0x11,
0x0A,
0x04,
0x0A,
0x11 },
// x
{
0x00,
0x00,
0x11,
0x11,
0x0F,
0x01,
0x0E },
// y
{ 0x00,
0x00,
0x1F,
0x02,
0x04,
0x08,
0x1F },
// z
{ 0x06,
0x08,
0x08,
0x10,
0x08,
0x08,
0x06 },
// {
{ 0x04,
0x04,
0x04,
0x00,
0x04,
0x04,
0x04 },
// :
{
0x0C,
0x02,
0x02,
0x01,
0x02,
0x02,
0x0C },
// }
{
0x00,
0x04,
0x02,
0x1F,
0x02,
0x04,
0x00 },
// Right arrow
{
0x00,
0x04,
0x08,
0x1F,
0x08,
0x04,
0x00 },
// Left arroe
{
0x1f,
0x1f,
0x1f,
0x1f,
0x1f,
0x1f,
0x1f }
// Fill
};
//*****************************************************************************
//
G L O B A L V A R I A B L E
//*****************************************************************************
// KeySwitch
ushort Switch;
// LCD
char Text[20];
// ADC
uint Amp1DC, Amp2DC;
uint Amp1AC,Amp2AC;
ushort Amp1ACDC, Amp2ACDC;
ushort Amp1DCSlope, Amp2DCSlope;
uint Amp1Max, Amp2Max;
// Correction Factor
float Sensor1Slope[11];
float Sensor1B[11];
float Sensor1Value[11];
float Sensor2Slope[11];
float Sensor2B[11];
float Sensor2Value[11];
// AD/DC
uint Sensor1ACCounter;
uint Sensor2ACCounter;
//*****************************************************************************
//
M A I N
//*****************************************************************************
void main()
{
TaskInit();
LCDInit();
ADInit();
SwitchInit();
IntInit();
WDR();
WDTCR = 0x0f;
// Watch Dog enable
SEI();
//re-enable interrupts
LCDClrSCR();
LCDGraphClrSCR();
SplashScreen();
Delay(50);
DrawScreen();
TaskRegister(RedrawTick,T500MS,TRUE);
TaskRegister(SwitchScan,T100MS,TRUE);
while(1)
{
_StackCheck();
if (Switch
== (LEFT+RIGHT))
{
Switch = NULL;
Calibration();
}
if (Switch
== LEFT)
{
Switch =
NULL;
Amp1Max =
0;
}
if (Switch
== RIGHT)
{
Switch =
NULL;
Amp2Max =
0;
}
WDR();
}
}
/******************************************************************************
Name:
void _StackOverflowed(char c)
Description: This function is
automaticaly called if
the stack crash.
Input:
none
Output:
none
Misc:
******************************************************************************/
void _StackOverflowed(char
c)
{
int i;
LCDClrSCR();
LCDGraphClrSCR();
LCDGotoXY(5,12);
LCDWriteConstString("S
T A C K O V E R F L O W !!!!!\0");
LCDGotoXY(5,13);
LCDWriteConstString("--------------------------------\0");
for (i=0;i<1000;i++)
LCDDelay2ms();
CLI();
while(1);
}
/******************************************************************************
Name:
void Delay(ushort Del)
Description: This function make a
delay
Input:
none
Output:
none
Misc:
******************************************************************************/
void Delay(ushort
Del)
{
int i,j;
for (i=0;i<Del;i++)
for (j=0;j<32000;j++)
WDR();
}
/******************************************************************************
Name:
void LoadSlope(ushort Polarity)
Description: This function
Input:
none
Output:
none
Misc:
******************************************************************************/
void LoadSlope(ushort
Polarity)
{
ushort i;
for (i=0;i<11;i++)
{
EEPROMReadBytes(SLOPE1+(i*4)+(Polarity*100),&Sensor1Value[i],4);
EEPROMReadBytes(SLOPE2+(i*4)+(Polarity*100),&Sensor2Value[i],4);
}
CalculateMB();
}
/******************************************************************************
Name:
void CalculateMB(void)
Description: This function calculate
M & B for all the 11 points
Input:
none
Output:
none
Misc:
******************************************************************************/
void CalculateMB(void)
{
ushort i;
for (i=0;i<10;i++)
{
Sensor1Slope[i]
= SlopeGetM(i,Sensor1Value[i],
i+1,Sensor1Value[i+1]);
Sensor1B[i]
= SlopeGetB(i,
Sensor1Value[i],
Sensor1Slope[i]);
Sensor2Slope[i]
= SlopeGetM(i,Sensor2Value[i],
i+1,Sensor2Value[i+1]);
Sensor2B[i]
= SlopeGetB(i,
Sensor2Value[i],
Sensor2Slope[i]);
}
}
/******************************************************************************
Name:
void Calibration(void)
Description: This function is to
equalibrate the non linear curve of the sensor
Input:
none
Output:
none
Misc:
******************************************************************************/
void Calibration(void)
{
int i,j;
TaskUnRegister(RedrawTick);
Switch = NULL;
LCDGraphClrSCR();
LCDGraphBox(15,
14,
242,
113,
1);
LCDGraphBox(1,
1,
256,
128,
1);
LCDGraphBox(1,
1,
256,
128,
1);
LcdGraphConstString (10,
4, FONT_1X,
"Amp Meter V:1.0\0"
);
LcdGraphConstString (6,
20,
FONT_2X,
"Calibration\0" );
LcdGraphConstString (4,
50,
FONT_1X, "Set the
current to :\0" );
LcdGraphConstString (5,
60,
FONT_1X, "IN THIS
WAY ---------->>\0" );
LcdGraphConstString (9,
70,
FONT_1X, "and
press any key\0" );
LcdGraphConstString (6,
90,
FONT_1X, "both
amp meter must be\0" );
LcdGraphConstString (8,
100,
FONT_1X,
"connected in series\0" );
csprintf(&Text[0],"%d\0",i);
LcdGraphConstString (24,
43,
FONT_2X, "1");
LcdGraphConstString (28,
50,
FONT_1X, "Amp\0"
);
while(!Switch)
WDR();
Switch = NULL;
for (i=0;i<11;i++)
{
csprintf(&Text[0],"%d\0",i);
LcdGraphString (24,
43,
FONT_2X, &Text[0]);
LcdGraphConstString (28,
50,
FONT_1X, "Amp\0"
);
while(!Switch)
WDR();
Switch = NULL;
if ((INT_PIN
& INT_INPUT_0))
j = 0;
else j
= 100;
Sensor1Value[i]
= Amp1DC;
EEPROMWriteBytes(SLOPE1+(i*4)+j,&Sensor1Value[i],4);
Sensor2Value[i]
= Amp2DC;
EEPROMWriteBytes(SLOPE2+(i*4)+j,&Sensor2Value[i],4);
}
LcdGraphConstString (5,
60,
FONT_1X, "IN THIS
WAY <<----------\0" );
if (j ==
0) j=100;
else j =
0;
for (i=0;i<11;i++)
{
csprintf(&Text[0],"%d
\0",i);
LcdGraphString (24,
43,
FONT_2X, &Text[0]);
LcdGraphConstString (28,
50,
FONT_1X, "Amp\0"
);
while(!Switch)
WDR();
Switch = NULL;
Sensor1Value[i]
= Amp1DC;
EEPROMWriteBytes(SLOPE1+(i*4)+j,&Sensor1Value[i],4);
Sensor2Value[i]
= Amp2DC;
EEPROMWriteBytes(SLOPE2+(i*4)+j,&Sensor2Value[i],4);
}
DrawScreen();
TaskRegister(RedrawTick,T500MS,TRUE);
}
/******************************************************************************
Name:
void SplashScreen(void)
Description: This function draw
splash Screen
Input:
none
Output:
none
Misc:
******************************************************************************/
void SplashScreen(void)
{
LCDGraphClrSCR();
LCDGraphBox(1,
1,
256,
128,
1);
LcdGraphConstString (2,
20,
FONT_2X, "Amp
Meter V:1.0\0" );
LcdGraphConstString (9,
50,
FONT_2X,
"Sylvain\0" );
LcdGraphConstString (6,
70,
FONT_2X,
"Bissonnette\0" );
}
/******************************************************************************
Name:
void DrawScreen(void)
Description: This function draw the
main screen
Input:
none
Output:
none
Misc:
******************************************************************************/
void DrawScreen(void)
{
LCDGraphClrSCR();
LCDGraphBox(1,
1,
256,
128,
1);
LcdGraphConstString (10,
4, FONT_1X,
"Amp Meter V:1.0\0"
);
LCDGraphBox(4,
14,
125,
125,
1);
LcdGraphConstString (3,
29,
FONT_1X, "Max:\0"
);
LcdGraphConstString (13,
32,
FONT_1X, "A\0"
);
LcdGraphConstString (6,
75,
FONT_1X,
"Current\0" );
LcdGraphConstString (13,
103,
FONT_2X, "A\0"
);
LCDGraphBox(131,
14,
252,
125,
1);
LcdGraphConstString (19,
29,
FONT_1X, "Max:\0"
);
LcdGraphConstString (29,
32,
FONT_1X, "A\0"
);
LcdGraphConstString (22,
75,
FONT_1X,
"Current\0" );
LcdGraphConstString (29,
103,
FONT_2X, "A\0"
);
PrintAmp1(19,
90, Amp1DC,
FONT_4X, DC);
PrintAmp1(23,
25,
Amp1Max, FONT_2X,
DC);
if (Amp1ACDC)
LcdGraphConstString (6,
50,
FONT_2X, "A/C");
else LcdGraphConstString
(6,
50,
FONT_2X, "D/C");
PrintAmp2(3,
90, Amp2DC,
FONT_4X, DC);
PrintAmp2(7,
25,
Amp2Max, FONT_2X,
DC);
if (Amp2ACDC)
LcdGraphConstString (22,
50,
FONT_2X, "A/C");
else LcdGraphConstString
(22,
50,
FONT_2X, "D/C");
}
/******************************************************************************
Name:
void IntInit(void)
Description: This function initialize
MCU for INT0 & INT1 to be enable
Input:
none
Output:
none
Misc:
******************************************************************************/
void IntInit(void)
{
INT_DDR &= ~(INT_INPUT_0
+ INT_INPUT_1);
MCUCR |= (1<<ISC10)
+ (1<<ISC00);
GICR |= (1<<INT0)
+ (1<<INT1);
}
/******************************************************************************
Name:
void Int_0_AC(void)
Description: This function is call
when the current change polarity
Input:
none
Output:
none
Misc:
******************************************************************************/
#pragma interrupt_handler Int_0_AC:2
void Int_0_AC(void)
{
Sensor1ACCounter++;
}
/******************************************************************************
Name:
void Int_1_AC(void)
Description: This function is call
when the current change polarity
Input:
none
Output:
none
Misc:
******************************************************************************/
#pragma interrupt_handler Int_1_AC:3
void Int_1_AC(void)
{
Sensor2ACCounter++;
}
/******************************************************************************
Name:
void CheckAC(void)
Description: This function Check if
the current is AC or DC
Input:
none
Output:
none
Misc:
******************************************************************************/
void CheckAC(void)
{
if ((Sensor1ACCounter
> 10)
&& (Sensor1ACCounter <
150))
Amp1ACDC = TRUE;
else Amp1ACDC
= FALSE;
if ((Sensor2ACCounter
> 10)
&& (Sensor2ACCounter <
150))
Amp2ACDC = TRUE;
else Amp2ACDC
= FALSE;
Sensor1ACCounter =
0;
Sensor2ACCounter =
0;
}
/******************************************************************************
Name:
void void RedrawTick(void)
Description: This function print
values on the LCD
Input:
none
Output:
none
Misc:
******************************************************************************/
void RedrawTick(void)
{
CheckAC();
if (Amp1ACDC
== DC)
DrawDC1();
else DrawAC1();
if (Amp2ACDC
== DC)
DrawDC2();
else DrawAC2();
}
/******************************************************************************
Name:
void DrawDC1(void)
Description: This function draw all
the information on DC current
Input:
none
Output:
none
Misc:
******************************************************************************/
void DrawDC1(void)
{
if (Amp1DCSlope)
LoadSlope(FOWARD);
else LoadSlope(REVERSE);
LcdGraphConstString (6,
50,
FONT_2X, "D/C");
PrintAmp1(3,
90, Amp1DC,
FONT_4X,DC);
PrintAmp1(7,
25,
Amp1Max, FONT_2X,DC);
}
/******************************************************************************
Name:
void DrawDC2(void)
Description: This function draw all
the information on DC current
Input:
none
Output:
none
Misc:
******************************************************************************/
void DrawDC2(void)
{
if (Amp2DCSlope)
LoadSlope(FOWARD);
else LoadSlope(REVERSE);
LcdGraphConstString (22,
50,
FONT_2X, "D/C");
PrintAmp2(19,
90, Amp2DC,
FONT_4X,DC);
PrintAmp2(23,
25,
Amp2Max, FONT_2X,DC);
}
/******************************************************************************
Name:
void DrawAC1(void)
Description: This function draw all
the information on AC current
Input:
none
Output:
none
Misc:
******************************************************************************/
void DrawAC1(void)
{
if (Amp1DCSlope)
LoadSlope(FOWARD);
else LoadSlope(REVERSE);
LcdGraphConstString (6,
50,
FONT_2X, "A/C");
PrintAmp1(3,
90, Amp1AC,
FONT_4X,AC);
PrintAmp1(7,
25,
Amp1Max, FONT_2X,AC);
Amp1AC = 0;
}
/******************************************************************************
Name:
void DrawAC2(void)
Description: This function draw all
the information on AC current
Input:
none
Output:
none
Misc:
******************************************************************************/
void DrawAC2(void)
{
if (Amp2DCSlope)
LoadSlope(FOWARD);
else
LoadSlope(REVERSE);
LcdGraphConstString (22,
50,
FONT_2X, "A/C");
PrintAmp2(19,
90, Amp2AC,
FONT_4X,AC);
PrintAmp2(23,
25,
Amp2Max, FONT_2X,AC);
Amp2AC =
0;
}
/******************************************************************************
Name:
void PrintAmp1(void)
Description: This function print Amp
value on the LCD
Input:
int x, int y, long value
Output:
none
Misc:
******************************************************************************/
void PrintAmp1(int
X, int Y,
uint Value, int Size,ushort
ACDC)
{
int i;
float ValueFloat,
x=0;
ValueFloat = (float)Value;
if (ValueFloat
> (float)Sensor1Value[10])
ValueFloat = (float)Sensor1Value[10];
if (ValueFloat
< (float)Sensor1Value[0])
ValueFloat = (float)Sensor1Value[0];
for (i=0;i<10;i++)
{
if ((ValueFloat
> Sensor1Value[i])
&& (ValueFloat <= Sensor1Value[i+1]))
{
x =
SlopeGetX((float)ValueFloat,(float)Sensor1B[i],(float)Sensor1Slope[i]);
break;
}
}
if (ACDC
== AC) x =
x * 0.707106781;
if (x <
0.0) x
= 0.0;
if (x >
9.9) x
= 9.89999;
csprintf(&Text[0],"%#3.1f\0",x);
LcdGraphString (X,
Y, Size, &Text[0]);
}
/******************************************************************************
Name:
void PrintAmp2(void)
Description: This function print Amp
value on the LCD
Input:
int x, int y, long value
Output:
none
Misc:
******************************************************************************/
void PrintAmp2(int
X, int Y,
uint Value, int Size,
ushort ACDC)
{
int i;
float ValueFloat,
x=0;
ValueFloat = (float)Value;
if (ValueFloat
> (float)Sensor2Value[10])
ValueFloat = (float)Sensor2Value[10];
if (ValueFloat
< (float)Sensor2Value[0])
ValueFloat = (float)Sensor2Value[0];
for (i=0;i<10;i++)
{
if ((ValueFloat
> Sensor2Value[i])
&& (ValueFloat <= Sensor2Value[i+1]))
{
x =
SlopeGetX((float)ValueFloat,(float)Sensor2B[i],(float)Sensor2Slope[i]);
break;
}
}
if (ACDC
== AC) x =
x * 0.707106781;
if (x <
0.0) x
= 0.0;
if (x >
9.9) x
= 9.89999;
csprintf(&Text[0],"%#3.1f\0",x);
LcdGraphString (X,
Y, Size, &Text[0]);
}
/******************************************************************************
Name:
ADCInit(void)
Description: This function initialize
the ADC
Input:
none
Output:
none
Misc:
******************************************************************************/
void ADInit(void)
{
ADCSRA = (1<<ADEN)
+ (1<<ADIE)
+ (1<<ADPS2)
+ (1<<ADPS1)
+ (1<<ADPS0);
ADMUX = ADC0;
ADCSRA |= (1<<ADSC);
// Start AD convertion
}
/******************************************************************************
Name:
AD_interrupt(void)
Description: This function is
automaticaly called when the AD had finish
is convertion
Input:
none
Output:
none
Misc:
******************************************************************************/
#pragma interrupt_handler AD_interrupt:17
void AD_interrupt(void)
{
uint Amp1, Amp2;
if (ADMUX
== ADC0)
{
Amp1 = (uint)((int)ADCH
<< 8)
+ ADCL;
Amp1DC = Amp1;
if (Amp1
> Amp1AC)
Amp1AC = Amp1;
if (Amp1
> Amp1Max)
Amp1Max = Amp1;
Amp1DCSlope = INT_PIN
& INT_INPUT_0;
ADMUX = ADC1;
}
else if (ADMUX
== ADC1)
{
Amp2 = (uint)((int)ADCH
<< 8)
+ ADCL;
Amp2DC = Amp2;
if (Amp2
> Amp2AC)
Amp2AC = Amp2;
if (Amp2
> Amp2Max)
Amp2Max = Amp2;
Amp2DCSlope = INT_PIN
& INT_INPUT_1;
ADMUX = ADC0;
}
ADCSRA |= (1<<ADSC);
// Start AD convertion
}
/******************************************************************************
Name:
float SlopeGetM (float X1, float Y1, float X2, float Y2)
Description: This function Give the
slope
Input:
float Y2, float Y1, float X2, float X1
Output:
float M
Misc:
(Y2 - Y1) / (X2 - X1)
******************************************************************************/
float SlopeGetM
(float X1,
float Y1, float X2,
float Y2)
{
float M;
M = (Y2 -
Y1) / (X2 -
X1);
return M;
}
/******************************************************************************
Name:
float SlopeGetB (float X, float Y, float B)
Description: This function Give B
offset of the slope
Input:
float M, float X, float M
Output:
float B
Misc:
B = Y - (M * X)
******************************************************************************/
float SlopeGetB
(float X,
float Y, float M)
{
float B;
B = Y - (M
* X);
return B;
}
/******************************************************************************
Name:
float SlopeGetX (float Y, float B, float M)
Description: This function Give X the
slope
Input:
float Y, float B, float M
Output:
float Y
Misc:
X = (Y - B) / M
******************************************************************************/
float SlopeGetX
(float Y,
float B, float M)
{
float X;
X = (Y -
B) / M;
return X;
}
/******************************************************************************
Name:
float SlopeGetY (float X, float B, float M)
Description: This function Give Y the
slope
Input:
float X, float B, float M
Output:
float Y
Misc:
Y = (M * X) + B
******************************************************************************/
float SlopeGetY
(float X,
float B, float M)
{
float Y;
Y = (M *
X) + B;
return Y;
}
//*****************************************************************************
//
L C D F U N C T I O N
//*****************************************************************************
/******************************************************************************
Name:
void LCDInit(void)
Description: Initialize a graphic of
LCD_X & LCD_Y
SED1300
Input:
#define LCD_X ...
#define LCD_Y ...
Output:
none
Misc:
******************************************************************************/
void LCDInit(void)
{
int i,j;
// LCD Data Bus
LCDDATA_PORT = 0x00;
LCDDATA_DDR = 0xff;
// LCD control Bus
LCDCTRL_DDR |= LCD_WR+LCD_RD+LCD_RES;
LCDCTRL_DDR |= LCD_A0;
LCDCTRL_PORT |= LCD_WR;
// LCD_WR -> 1
LCDCTRL_PORT |= LCD_RD;
// LCD_RD -> 1
LCDCTRL_PORT |= LCD_RES;
LCDDelay2ms();
LCDCTRL_PORT &= ~LCD_RES;
// Reset LCD
LCDDelay2ms();
LCDCTRL_PORT |= LCD_RES;
for (i=0;i<200;i++)
{
LCDDelay2ms();
}
// SYSTEM SET COMMAND
LCDWriteCmd(0x40);
// SYSTEM SET COMMAND
LCDWriteData(0x30);
// P1 -> PRT=0, IV=1, W/S=0,
M0-M2=0
LCDWriteData(0x87);
// FX -> WF=1, FX=7
LCDWriteData(0x07);
// FY -> FY=7
LCDWriteData((LCD_X/8)-1);
// C/R -> Char per line - 1
LCDWriteData((LCD_XTAL
/ 70 /
LCD_Y) / 9);
// TC/R -> (f_osc/f_frame/[L/F]-1)/9
LCDWriteData(LCD_Y -
1);
// L/F -> Line per graphic screen - 1
(127)
LCDWriteData(LCD_X/8);
// APL -> Virtual scr low byte (ch
perline)
LCDWriteData(00);
// APH -> Virtual scr low byte
// SCROLL COMMAND
LCDWriteCmd(0x44);
// SCROLL COMMAND
LCDWriteData(0x00);
// First Layer Low Byte (0x0000)
LCDWriteData(0x00);
// First Layer Hign Byte
LCDWriteData(LCD_Y);
// 128 Line of scroll
LCDWriteData(0x00);
// Second Layer Low Byte (0x1000)
LCDWriteData(0x10);
// First Layer Hign Byte
LCDWriteData(LCD_Y);
// 128 Line of scroll
// HORIZONTAL SCROLL POSITION
LCDWriteCmd(0x5a);
// HORIZONTAL SCROLL POSITION
LCDWriteData(0x00);
// no scrool offset
// OVERLAY COMMAND
LCDWriteCmd(0x5b);
// OVERLAY COMMAND
LCDWriteData(0x03);
// 2 layer (1-Text 2-Graphic)
// DISPLAY ON/OFF COMMAND
LCDWriteCmd(0x58);
// DISPLAY OFF COMMAND
LCDWriteData(0x14);
// Layer 1 & 2 ON
LCDClrSCR();
LCDGraphClrSCR();
// LCDCursor FORMAT COMMAND
LCDWriteCmd(0x5d);
// LCDCursor FORMAT COMMAND
LCDWriteData(0x07);
// LCDCursor width (7)
LCDWriteData(0x87);
// LCDCursor Height(7) & Block type
// DISPLAY ON/OFF COMMAND
LCDWriteCmd(0x59);
// DISPLAY ON COMMAND
LCDWriteData(0x14);
// Layer 1 & 2 ON
// LCDCursor DIRECTION COMMAND
LCDWriteCmd(0x4c);
// LCDCursor DIRECTION COMMAND (SHIFT
RIGHT)
// LCDCursor WRITE COMMAND
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(0x00);
// LCDCursor position low byte
LCDWriteData(0x00);
// LCDCursor position high byte
}
/******************************************************************************
Name:
void LCDClrSCR(void)
Description: Clear Text Screen layer
1
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDClrSCR(void)
{
int i,j;
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(0x00);
// LCDCursor position low byte
LCDWriteData(0x00);
// LCDCursor position high byte
LCDWriteCmd(0x42);
// LCD WRITE MEMORY
LCDDATA_PORT = ' ';
LCDCTRL_PORT &= ~LCD_A0;
// LCD_A0 -> 0
j = ((LCD_X/8)*(LCD_Y/8));
for (i=0;i<j;i++)
{
LCDCTRL_PORT &=~LCD_WR;
// LCD_WR -> 0
WDR();
LCDCTRL_PORT |=LCD_WR;
}
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(0x00);
// LCDCursor position low byte
LCDWriteData(0x00);
// LCDCursor position high byte
}
/******************************************************************************
Name:
void LCDGotoXY(ushort x, ushort y)
Description: Goto LCD_X LCD_Y coor
Input:
LCD_X,LCD_Y
Output:
none
Misc:
******************************************************************************/
void LCDGotoXY(ushort
x, ushort y)
{
int Address;
ushort low;
ushort high;
x--;
y--;
Address = (y * (LCD_X/8))
+ x;
low = (ushort) (Address
& 0x00ff);
high = (ushort) ((Address
& 0xff00)
>> 8);
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(low);
// LCDCursor position low byte
LCDWriteData(high);
// LCDCursor position high byte
}
/******************************************************************************
Name:
void LCDWriteString(char *prt)
Description: Write a string to the
LCD
Input:
String
Output:
none
Misc:
String must be ended by \0
******************************************************************************/
void LCDWriteString(char
*ptr)
{
int i;
LCDWriteCmd(0x42);
// LCD WRITE MEMORY
while(*ptr !=
0x00)
LCDWriteData(*ptr++);
}
void LCDWriteConstString(const
char *ptr)
{
int i;
LCDWriteCmd(0x42);
// LCD WRITE MEMORY
while(*ptr !=
0x00)
LCDWriteData(*ptr++);
}
/******************************************************************************
Name:
void LCDCursor(ushort)
Description: 0-> LCDCursor off
1-> LCDCursor on
Input:
ON/OFF
Output:
none
Misc:
******************************************************************************/
void LCDCursor(ushort
LCDCursor)
{
LCDWriteCmd(0x59);
// DISPLAY ON COMMAND
if (LCDCursor
== 0)
LCDWriteData(0x14);
else LCDWriteData(0x16);
}
/******************************************************************************
Name:
void LCDGraphClrSCR(void)
Description: Clear Graphic Screen
layer 2
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDGraphClrSCR(void)
{
int i,j;
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(0x00);
// LCDCursor position low byte
LCDWriteData(0x10);
// LCDCursor position high byte
LCDWriteCmd(0x42);
// LCD WRITE MEMORY COMMAND
LCDDATA_PORT = 0x00;
LCDCTRL_PORT &= ~LCD_A0;
// LCD_A0 -> 0
j = ((LCD_X/8)*LCD_Y);
for (i=0;i<j;i++)
{
LCDCTRL_PORT &=~LCD_WR;
// LCD_WR -> 0 & LCD_WR -> 1
WDR();
LCDCTRL_PORT |=LCD_WR;
}
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(0x00);
// LCDCursor position low byte
LCDWriteData(0x10);
// LCDCursor position high byte
}
/******************************************************************************
Name:
void LCDGraphGotoXY(ushort x, ushort y)
Description: Goto LCD_X LCD_Y coor
Input:
LCD_X,LCD_Y
Output:
none
Misc:
******************************************************************************/
void LCDGraphGotoXY(ushort
x, ushort y)
{
int Address;
ushort low;
ushort high;
x--;
y--;
Address = (y * (LCD_X/8))
+ x;
low = (ushort) (Address
& 0x00ff);
high = (ushort)
(((Address &
0xff00) >>
8) +
0x10);
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(low);
// LCDCursor position low byte
LCDWriteData(high);
// LCDCursor position high byte
}
/******************************************************************************
Name:
void LcdGraphString(ushort X, ushort Y, ushort Size, ushort *Ptr)
Description: Displays a string at
Input:
size -> Font size.
ch -> Character to write.
Output:
none
Misc:
******************************************************************************/
void LcdGraphConstString
(ushort X,
ushort Y, ushort Size,
const char *Ptr )
{
while(*Ptr
!= 0x00)
{
LcdGraphChr(X,Y,Size,*Ptr++);
if ( Size
== FONT_1X )
X++;
if ( Size
== FONT_2X )
X+=2;
if ( Size
== FONT_4X )
X+=3;
}
}
void LcdGraphString
(ushort X,
ushort Y, ushort Size,
char *Ptr )
{
while(*Ptr
!= 0x00)
{
LcdGraphChr(X,Y,Size,*Ptr++);
if ( Size
== FONT_1X )
X++;
if ( Size
== FONT_2X )
X+=2;
if ( Size
== FONT_4X )
X+=3;
}
}
/******************************************************************************
Name:
void LcdGraphChr (ushort X, ushort Y, ushort Size, ushort Ch )
Description: Displays a character at
x,y location
Input:
X -> X axis position
Y -> Y axis position
Size -> Font size.
Ch -> Character to write.
Output:
none
Misc:
******************************************************************************/
void LcdGraphChr
(ushort X,
ushort Y, ushort Size,
ushort Ch )
{
ushort i,j;
uint Address;
ushort low;
ushort high;
ushort b1,b2,b3,b4;
ushort Font;
Ch -=32;
X--;
Y--;
Address = (Y * (LCD_X/8))
+ X;
LCDGraphSetRamPointer(Address);
if ( Size
== FONT_1X )
{
for (i=0;i<7;i++)
{
LCDWriteCmd(0x42);
// LCD WRITE MEMORY
LCDWriteData(
(ushort)(FontLookup[Ch][i])
<< 2 );
LCDGraphSetRamPointer(Address
+= LCD_X /
8);
}
}
if ( Size
== FONT_2X )
{
for ( i =
0; i
< 7;
i++ )
{
Font =
FontLookup[Ch][i]
<< 2;
b1 =
0;
b2 =
0;
if
(Font &
0x01) b1
|= 0b00000011;
if
(Font &
0x02) b1
|= 0b00001100;
if
(Font &
0x04) b1
|= 0b00110000;
if
(Font &
0x08) b1
|= 0b11000000;
if
(Font &
0x10) b2
|= 0b00000011;
if
(Font &
0x20) b2
|= 0b00001100;
if
(Font &
0x40) b2
|= 0b00110000;
if
(Font &
0x80) b2
|= 0b11000000;
for
(j=0;j<2;j++)
{
LCDWriteCmd(0x42);
// LCD WRITE MEMORY
LCDWriteData(b2);
LCDWriteData(b1);
LCDGraphSetRamPointer(Address
+= LCD_X /
8);
}
}
}
if ( Size
== FONT_4X )
{
for ( i
= 0;
i < 7;
i++ )
{
Font =
FontLookup[Ch][i]
<< 2;
b1 =
0x00;
b2 =
0x00;
b3 =
0x00;
b4 =
0x00;
if
(Font &
0x01) b4
|= 0x0f;
if
(Font &
0x02) b4
|= 0xf0;
if
(Font &
0x04) b3
|= 0x0f;
if
(Font &
0x08) b3
|= 0xf0;
if
(Font &
0x10) b2
|= 0x0f;
if
(Font &
0x20) b2
|= 0xf0;
if
(Font &
0x40) b1
|= 0x0f;
if
(Font &
0x80) b1
|= 0xf0;
for
(j=0;j<4;j++)
{
LCDWriteCmd(0x42);
// LCD WRITE MEMORY
LCDWriteData(b1);
LCDWriteData(b2);
LCDWriteData(b3);
LCDWriteData(b4);
LCDGraphSetRamPointer(Address
+= LCD_X /
8);
}
}
}
}
/******************************************************************************
Name:
void LCDGraphSetRamPointer(int Address)
Description: Setup the address
register of the LCD
Input:
int -> Address done by combination of X and Y
Output:
none
Misc:
******************************************************************************/
void LCDGraphSetRamPointer(int
Address)
{
ushort low;
ushort high;
low = (ushort) (Address
& 0x00ff);
high = (ushort)
(((Address &
0xff00) >>
8) +
0x10);
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(low);
// LCDCursor position low byte
LCDWriteData(high);
// LCDCursor position high byte
}
/******************************************************************************
Name:
void LCDGraphPix(int x, int y, ushort stat)
Description: Set of Clear a pixel
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDGraphPix(int
x, int y,
ushort stat)
{
uint Address;
ushort Offset;
ushort low;
ushort high;
ushort byte;
x--;
y--;
Address = (y * (LCD_X/8))
+ (x / 8);
Offset = x - ((x
/ 8)
* 8);
low = (ushort) (Address
& 0x00ff);
high = (ushort) (((Address
& 0xff00)
>> 8) +
0x10);
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(low);
// LCDCursor position low byte
LCDWriteData(high);
// LCDCursor position high byte
LCDWriteCmd(0x43);
// READ LCD MEMORY COMMAND
byte = LCDReadData();
// Read data at position
if (stat !=
0) byte
|= (0x80
>> Offset);
else byte &=
(~(0x80 >>
Offset));
LCDWriteCmd(0x46);
// LCDCursor WRITE COMMAND
LCDWriteData(low);
// LCDCursor position low byte
LCDWriteData(high);
// LCDCursor position high byte
LCDWriteCmd(0x42);
// LCD WRITE MEMORY COMMAND
LCDWriteData(byte);
// Write byte
}
/******************************************************************************
Name:
void LCDGraphBox(int x1, int y1, int x2, int y2)
Description: draw a box
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDGraphBox(int
x1, int y1,
int x2, int y2,int
stat)
{
int i;
for (i=x1;i<=x2;i++)
LCDGraphPix(i,y1,stat);
// Top line
for (i=x1;i<=x2;i++)
LCDGraphPix(i,y2,stat);
// Bottom line
for (i=y1;i<=y2;i++)
LCDGraphPix(x1,i,stat);
// Left side
for (i=y1;i<=y2;i++)
LCDGraphPix(x2,i,stat);
// Right side
}
/******************************************************************************
Name:
void LCDTextBox(int x, int y, int length,int stat)
Description:
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDTextBox(int
x, int y,
int length,int
stat)
{
LCDGraphBox(((x-1)*8),((y-1)*8),(((length*8)+((x-1)*8))-2),(y*8),stat);
}
/******************************************************************************
Name:
void LCDGraphLine(int x1, int y1, int x2, int y2)
Description: draw a line
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDGraphLine(int
x1, int y1,
int x2, int y2)
{
int dx,dy,stepx,stepy,fraction;
dy = y2 - y1;
dx = x2 - x1;
if (dy <
0)
{
dy = -dy;
stepy = -1;
}
else
{
stepy = 1;
}
if (dx <
0)
{
dx = -dx;
stepx = -1;
}
else
{
stepx = 1;
}
dy <<= 1;
dx <<= 1;
LCDGraphPix(x1,y1,1);
if (dx >
dy)
{
fraction = dy
- (dx >>
1);
while (x1
!= x2)
{
if (fraction
>= 0)
{
y1 +=
stepy;
fraction -=
dx;
}
x1 += stepx;
fraction += dy;
LCDGraphPix(x1,y1,1);
}
}
else
{
fraction = dx
- (dy >>
1);
while (y1
!= y2)
{
if (fraction
>= 0)
{
x1 +=
stepx;
fraction -=
dy;
}
y1 += stepy;
fraction += dx;
LCDGraphPix(x1,y1,1);
}
}
}
/******************************************************************************
Name:
void LCDWriteCmd(ushort byte)
Description: write a Cmd byte to the
LCD
Input:
Command (Byte)
Output:
none
Misc:
******************************************************************************/
void LCDWriteCmd(ushort
byte)
{
LCDDATA_DDR = 0xff;
// Data Port as output
LCDDATA_PORT = byte;
LCDCTRL_PORT |= LCD_A0;
// LCD_A0 -> 1
LCDCTRL_PORT &=~LCD_WR;
// LCD_WR -> 0
WDR();
LCDCTRL_PORT |=LCD_WR;
// LCD_WR -> 1
}
/******************************************************************************
Name:
void LCDWriteData(ushort byte)
Description: write a data byte to the
LCD
Input:
ushort byte -> data to write on the LCD
Output:
none
Misc:
******************************************************************************/
void LCDWriteData(ushort
byte)
{
LCDDATA_DDR = 0xff;
// Data Port as output
LCDDATA_PORT = byte;
LCDCTRL_PORT &= ~LCD_A0;
// LCD_A0 -> 0
LCDCTRL_PORT &=~LCD_WR;
// LCD_WR -> 0
WDR();
LCDCTRL_PORT |=LCD_WR;
// LCD_WR -> 1
}
/******************************************************************************
Name:
ushort LCDReadData(void)
Description: read a data byte to the
LCD
Input:
none
Output:
ushort byte -> Data read from the LCD
Misc:
******************************************************************************/
ushort LCDReadData(void)
{
ushort byte;
int i;
WDR();
LCDDATA_DDR = 0x00;
// Data Port as input
LCDCTRL_PORT |= LCD_A0;
// LCD_A0 -> 1
LCDDelay1us();
LCDCTRL_PORT &=~LCD_RD;
// LCD_RD -> 0
byte = LCDDATA_PIN;
// read byte
byte = LCDDATA_PIN;
// read byte
byte = LCDDATA_PIN;
// read byte
byte = LCDDATA_PIN;
// read byte
LCDCTRL_PORT |=LCD_RD;
// LCD_RD -> 1
return byte;
}
/******************************************************************************
Name:
void LCDDelay2ms(void)
Description: Delay of 2ms
Input:
void
Output:
void
Misc:
******************************************************************************/
void LCDDelay2ms(void)
{
int i,j;
for (i=0;i<(XTAL/36363);i++)
{
for (j=1;j<20;j++);
asm("WDR");
}
}
/******************************************************************************
Name:
void LCDDelay1us()
Description: Delay of 1us
Input:
none
Output:
none
Misc:
******************************************************************************/
void LCDDelay1us(void)
{
int i;
for (i=0;i<6;i++)
WDR();
}
/*****************************************************************************
Name:
void ScanSwitch(void)
Description:
Input:
none
Output:
none
Misc:
******************************************************************************/
void SwitchInit(void)
{
SWITCH_DDR &= ~(LEFT
+ RIGHT);
SWITCH_PORT |= (LEFT
+ RIGHT);
}
/*****************************************************************************
Name:
void SwitchScan(void)
Description:
Input:
none
Output:
none
Misc:
******************************************************************************/
void SwitchScan(void)
{
static unsigned char LastSwitch;
unsigned char SwitchRead;
SwitchRead = NULL;
if (!(SWITCH_PIN
& RIGHT))
SwitchRead = RIGHT;
if (!(SWITCH_PIN
& LEFT))
SwitchRead = LEFT;
if (!(SWITCH_PIN
& (LEFT+RIGHT)))
SwitchRead = BOTH;
if (SwitchRead
!= LastSwitch)
{
Switch = SwitchRead;
LastSwitch = SwitchRead;
}
}
//*****************************************************************************
// TaskManager
// Version 2.0 Fev 2005
//
// 2.0 -> -Re work all the interrupt code
// 1.0 -> -Everything is new
//
// Sylvain Bissonnette
//*****************************************************************************
// Editor : UltraEdit32
//*****************************************************************************
//
T I M E R U S A G E
//
// Timer 0 is use by Task Manager
//
//*****************************************************************************
//
//*****************************************************************************
//
I N C L U D E
//*****************************************************************************
#include <iom32v.h>
#include <shortnametype.h>
#include <macros.h>
#include <stdlib.h>
#include <STRING.H>
#include "TaskManager.h"
//#define MINIMUM_CODE //
if def save 71 words of code but no more
// checking of Register and UnRegister
//*****************************************************************************
//
G L O B A L V A R I A B L E
//*****************************************************************************
typedef struct Task
{
void (*FunctionPTR)(void);
uint Interval;
uint Ticker;
ushort Persiste;
}Task;
Task TaskList[MAX_TASK];
Task TaskAdd;
Task TaskDel;
int TaskMax
= 0;
/******************************************************************************
Name:
void TaskInit(void)
Description: Init task system
Input:
none
Output:
none
Misc:
Use Timer 0
******************************************************************************/
void TaskInit(void)
{
//Timer0
TCCR0 = 0x02;
// Timer0 / 8
TIMSK |= (1<<TOIE0);
// int enable on Timer 0 overflow
}
/******************************************************************************
Name:
int TaskRegister( void(*FunctionPTR)(void),
int Interval,
ushort Persiste)
Description: Register a function to
be call
Input:
void Function pointer
int Interval
uchar Persiste
Output:
0 -> Task not registrated (error)
1 -> Task is now registrated
Misc:
******************************************************************************/
int TaskRegister(void(*FunctionPTR)(void),
uint Interval,
ushort Persiste)
{
#ifndef MINIMUM_CODE
uint i = 0;
if (FunctionPTR
== NULL) return
0;
if (TaskMax >=
MAX_TASK) return
0;
while (TaskAdd.FunctionPTR
!= NULL)
{
WDR();
if (i++
> 65530)
return 0;
}
#endif
TaskAdd.FunctionPTR =
FunctionPTR;
TaskAdd.Interval =
Interval;
TaskAdd.Persiste =
Persiste;
return 1;
}
/******************************************************************************
Name:
int TaskUnRegister(void(*FunctionPTR)(void))
Description: UnRegister a function
Input:
Function pointer
Output:
0 -> Task not find
1 -> Task is unregistrated
Misc:
******************************************************************************/
int TaskUnRegister(void(*FunctionPTR)(void))
{
#ifndef MINIMUM_CODE
uint i = 0;
if (FunctionPTR
== NULL) return
0;
while(TaskDel.FunctionPTR
!= NULL)
{
WDR();
if (i++
> 65530)
return 0;
}
#endif
TaskDel.FunctionPTR =
FunctionPTR;
return 1;
}
/**********************************************************
Name:
int TaskCheckRegister(void(*FunctionPTR)(void))
Description: Check if a function is
register
Input:
Function pointer
Output:
0 -> Not register
1 -> Register
Misc:
**********************************************************/
int TaskCheckRegister(void(*FunctionPTR)(void))
{
ushort i;
for (i=0;
i < TaskMax;
i++)
{
if (TaskList[i].FunctionPTR
== FunctionPTR)
return 1;
}
return 0;
}
/**********************************************************
Name:
void TaskBlock(int Time)
Description: Block for x time
Input:
none
Output:
none
Misc:
**********************************************************/
void TaskBlock(uint
Time)
{
TaskRegister(TaskDummy,Time,FALSE);
while (TaskCheckRegister(TaskDummy))
WDR();
}
void TaskDummy(void)
{
}
/**********************************************************
Name:
void TaskStop(void)
Description: Stop Task Execution
Input:
none
Output:
none
Misc:
**********************************************************/
void TaskStop(void)
{
TIMSK &= ~(1<<TOIE0);
// int disable on Timer 0 overflow
}
/**********************************************************
Name:
void TaskStart(void)
Description: Start Task Execution
Input:
none
Output:
none
Misc:
**********************************************************/
void TaskStart(void)
{
TIMSK |= (1<<TOIE0);
// int enable on Timer 0 overflow
}
/**********************************************************
Name:
void TaskExecute(void)
Description: TaskExecute
Input:
none
Output:
none
Misc:
TaskExecute is execute each 100us
**********************************************************/
#pragma interrupt_handler TaskExecute:12
void TaskExecute(void)
{
static ushort i,j;
static void (*FunctionPTR)(void);
TCNT0 = 255
- (XTAL /
8 /
10000);
TaskStop();
WDR();
if (TaskDel.FunctionPTR
!= NULL) _TaskUnRegister();
if (TaskAdd.FunctionPTR
!= NULL) _TaskRegister();
for (i=0;i<TaskMax;i++)
{
if (TaskList[i].Ticker++
>= TaskList[i].Interval)
{
FunctionPTR =
TaskList[i].FunctionPTR;
if (!TaskList[i].Persiste)
{
for (j=i;j<TaskMax;j++)
memcpy(&TaskList[j],&TaskList[j+1],sizeof(Task));
TaskMax--;
}
else
{
TaskList[i].Ticker
= 0;
}
SEI();
FunctionPTR();
CLI();
}
}
TaskStart();
}
/******************************************************************************
Name:
void _TaskUnRegister(void)
Description: UnRegister a function
Input:
TaskDel struct
Output:
none
Misc:
******************************************************************************/
void _TaskUnRegister(void)
{
ushort i,j;
for (i=0;i<TaskMax;i++)
{
if (TaskList[i].FunctionPTR
== TaskDel.FunctionPTR)
{
for (j=i;j<TaskMax;j++)
memcpy(&TaskList[j],&TaskList[j+1],sizeof(Task));
TaskMax--;
TaskDel.FunctionPTR
= NULL;
return;
}
}
TaskDel.FunctionPTR =
NULL;
}
/******************************************************************************
Name:
int _TaskRegister(void)
Description: Register a function
Input:
TaskAdd struct
Output:
none
Misc:
******************************************************************************/
void _TaskRegister(void)
{
TaskList[TaskMax].FunctionPTR
= TaskAdd.FunctionPTR;
TaskList[TaskMax].Interval
= TaskAdd.Interval;
TaskList[TaskMax].Ticker
= 0;
TaskList[TaskMax].Persiste
= TaskAdd.Persiste;
TaskAdd.FunctionPTR =
NULL;
TaskMax++;
}
//*****************************************************************************
// TaskManager.h
// Version 1.0 Dec 2004
//
// 1.0 -> -Everything is new
//
// Sylvain Bissonnette
//*****************************************************************************
//
//*****************************************************************************
//
D E F I N E
//*****************************************************************************
#define TASK_MAN_VER 10
#define TRUE
1
#define FALSE
0
#define XTAL
8000000
#define MAX_TASK
10
#define T100US
1
#define T200US
2
#define T300US
3
#define T400US
4
#define T500US
5
#define T600US
6
#define T700US
7
#define T800US
8
#define T900US
9
#define T1MS
10
#define T2MS
20
#define T3MS
30
#define T4MS
40
#define T5MS
50
#define T6MS
60
#define T7MS
70
#define T8MS
80
#define T9MS
90
#define T10MS
100
#define T20MS
200
#define T30MS
300
#define T40MS
400
#define T50MS
500
#define T60MS
600
#define T70MS
700
#define T80MS
800
#define T90MS
900
#define T100MS
1000
#define T110MS
1100
#define T120MS
1200
#define T130MS
1300
#define T140MS
1400
#define T150MS
1500
#define T160MS
1600
#define T170MS
1700
#define T180MS
1800
#define T190MS
1900
#define T200MS
2000
#define T210MS
2100
#define T220MS
2200
#define T230MS
2300
#define T240MS
2400
#define T250MS
2500
#define T260MS
2600
#define T270MS
2700
#define T280MS
2800
#define T290MS
2900
#define T300MS
3000
#define T310MS
3100
#define T320MS
3200
#define T330MS
3300
#define T340MS
3400
#define T350MS
3500
#define T360MS
3600
#define T370MS
3700
#define T380MS
3800
#define T390MS
3900
#define T400MS
4000
#define T410MS
4100
#define T420MS
4200
#define T430MS
4300
#define T440MS
4400
#define T450MS
4500
#define T460MS
4600
#define T470MS
4700
#define T480MS
4800
#define T490MS
4900
#define T500MS
5000
#define T510MS
5100
#define T520MS
5200
#define T530MS
5300
#define T540MS
5400
#define T550MS
5500
#define T560MS
5600
#define T570MS
5700
#define T580MS
5800
#define T590MS
5900
#define T600MS
6000
#define T610MS
6100
#define T620MS
6200
#define T630MS
6300
#define T640MS
6400
#define T650MS
6500
#define T660MS
6600
#define T670MS
6700
#define T680MS
6800
#define T690MS
6900
#define T700MS
7000
#define T710MS
7100
#define T720MS
7200
#define T730MS
7300
#define T740MS
7400
#define T750MS
7500
#define T760MS
7600
#define T770MS
7700
#define T780MS
7800
#define T790MS
7900
#define T800MS
8000
#define T810MS
8100
#define T820MS
8200
#define T830MS
8300
#define T840MS
8400
#define T850MS
8500
#define T860MS
8600
#define T870MS
8700
#define T880MS
8800
#define T890MS
8900
#define T900MS
9000
#define T910MS
9100
#define T920MS
9200
#define T930MS
9300
#define T940MS
9400
#define T950MS
9500
#define T960MS
9600
#define T970MS
9700
#define T980MS
9800
#define T990MS
9900
#define T1S
10000
#define T2S
20000
#define T3S
30000
#define T4S
40000
#define T5S
50000
#define T6S
60000
#define T7S
70000
#define T8S
80000
#define T9S
90000
#define T10S
100000
#define T11S
110000
#define T12S
120000
#define T13S
130000
#define T14S
140000
#define T15S
150000
#define T16S
160000
#define T17S
170000
#define T18S
180000
#define T19S
190000
#define T20S
200000
#define T21S
210000
#define T22S
220000
#define T23S
230000
#define T24S
240000
#define T25S
250000
#define T26S
260000
#define T27S
270000
#define T28S
280000
#define T29S
290000
#define T30S
300000
#define T31S
310000
#define T32S
320000
//*****************************************************************************
//
P R O T O T Y P E
//*****************************************************************************
void TaskInit(void);
int TaskRegister(void(*CallBack)(void),
unsigned int Interval,
// was long
unsigned char Persiste);
int TaskUnRegister(void(*CallBack)(void));
int TaskCheckRegister(void(*CallBack)(void));
void TaskBlock(unsigned
int Time);
// was long
void TaskDummy(void);
void TaskStop(void);
void TaskStart(void);
void TaskExecute(void);
void _TaskUnRegister(void);
void _TaskRegister(void);