Did you find this site useful ? Please
to help www.micro-examples.com

If you need a coder or a freelance programmer, submit your project to me


PIC PAL Video Library

Printer-friendly version | Forums | FAQs |

PIC PAL VIDEO LIBRARY SCREEN SHOT

 

Did you ever need to display some informations on your TV screen, for your home application project for example ? But you gave up, because the hardware and software involved in this kind of project is not easy to operate.

This time is over ! This page will show you, how to turn a PIC18 into a B&W Text & Graphics PAL video processor with a very few and inexpensive hardware, and a minimum of coding effort !

 See also my tiny PIC PAL composite video superimposer

 

Page index :


WHY A PIC PAL LIBRARY ?

If you are into PICs, you maybe tried one day or another to build a software video processor, either for fun or for a project.
If you tried to generate video signals, you surely know some of this web pages :

This projects are fun, but I wanted to build a general purpose software video processor, to drive a TV screen just like a GLCD could be.

I kept the idea to use a 2-resistor ladder as a fast and cheap digital to analog converter, and started to work on the software.


PIC PAL SOFTWARE VIDEO LIBRARY

Since the video screen has to be mapped in memory, only PICs with enough RAM are concerned, that's why the PIC PAL Library is for PIC18 family only.

The PIC must be clocked at 32 Mhz with a 8 Mhz crystal, to get the 64 µs horizontal synchronization timing of the PAL system.

The library generates a 625 lines interlaced PAL video signal, and can display up to 248 vertical lines of 128 pixel. Any video display device with a PAL video composite input should be able to display the picture generated by the PIC.

Because timing is critical, the part of the software producing the video uses in-line assembly mixed with C.

You can download the full mikroC project, including the library source code.

Here is the user's manual of the PIC PAL Library :

INITIALIZATION

PROTOTYPE void    PAL_init(unsigned char y)
PARAMETERS

y : number of vertical lines, up to 128

RETURNS nothing
DESCRIPTION

prepare the PIC PAL video library
the more vertical lines you want, the less memory & MPU power you have

Warnings :

  • this library takes control of TIMER 0 and associated interrupts !
  • this library takes control of the PORTD !
REQUIRES

the file PAL_library.h must be included in user's source code.

specified hardware with 2 resistors, see schematic
the device must be clocked at 32 Mhz

EXAMPLE PAL_init(128) ;

 Video control

PROTOTYPE void    PAL_control(unsigned char st, unsigned char rd)
PARAMETERS

st : PAL synchronization control
PAL_CNTL_START : start PAL synchro 
PAL_CNTL_STOP : stop PAL synchro (free all MCU power)

rd : rendering control
PAL_CNTL_BLANK : only borders are displayed (free a part of MCU power)
PAL_CNTL_RENDER : full video is rendered, with borders and picture (most of MCU power is required)

RETURNS nothing
DESCRIPTION

control the video generation

when the PAL synchro is started, the unsigned long global variable PAL_frameCtr is incremented 25 times per second.

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ;

FILL SCREEN

PROTOTYPE void    PAL_fill(unsigned char c)
PARAMETERS

c : filling pattern

RETURNS nothing
DESCRIPTION

fill screen with pattern c
use 0 to clear the screen, 0xff to paint the screen in white

REQUIRES

PAL_init() must have been called

EXAMPLE PALL_fill(0) ;

 SET SCREEN BORDER COLOR

PROTOTYPE void    PAL_setBorder(unsigned char border)
PARAMETERS

border : either PAL_COLOR_BLACK or PAL_COLOR_WHITE

RETURNS nothing
DESCRIPTION

change the screen border color surrounding the picture

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_border(PAL_COLOR_BLACK) ;

SET PIXEL

PROTOTYPE void    PAL_setPixel(char x, char y, unsigned char mode)
PARAMETERS

x : pixel column, from 0 to 127
y : pixel row, from 0 to the number of lines - 1 
mode : pixel color, either PAL_COLOR_BLACK,  PAL_COLOR_WHITE or PAL_COLOR_REVERSE

RETURNS nothing
DESCRIPTION

set the color of the pixel located a column x, row y

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_setPixel(10, 20, PAL_COLOR_REVERSE) ;

draw a line

PROTOTYPE void PAL_line(char x0, char y0, char x1, char y1, unsigned char mode)
PARAMETERS

x0, y0 : column and row of the start of the line
x1, y1 : column and row of the end of the line
mode : pixel color, either PAL_COLOR_BLACK,  PAL_COLOR_WHITE or PAL_COLOR_REVERSE

RETURNS nothing
DESCRIPTION

draw a line from (x0, y0) to (x1, y1)

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_line(0, 0, 127, 127, PAL_COLOR_WHITE) ;

DRAW A CIRCLE

PROTOTYPE void PAL_circle(char x, char y, char r, unsigned char mode)
PARAMETERS

x : column of the center of the circle
y : row of the center of the circle
r : radius of the circle
mode : pixel color, either PAL_COLOR_BLACK,  PAL_COLOR_WHITE or PAL_COLOR_REVERSE

RETURNS nothing
DESCRIPTION

draw a circle of radius r centered at (x, y)

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_circle(30, 30, 5, PAL_COLOR_WHITE) ;

DRAW A SOLID BOX

PROTOTYPE void PAL_box(char x0, char y0, char x1, char y1, unsigned char mode)
PARAMETERS

x0, y0 : top left of the box
x1, y1 : bottom right of the box
mode : pixel color, either PAL_COLOR_BLACK,  PAL_COLOR_WHITE or PAL_COLOR_REVERSE

RETURNS nothing
DESCRIPTION

fill a rectangle from corner (x0, y0) to corner (x1, y1)

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_box(10, 10, 30, 30, PAL_COLOR_WHITE) ;

draw a rectangle

PROTOTYPE void PAL_rectangle(char x0, char y0, char x1, char y1, unsigned char pcolor)
PARAMETERS

x0, y0 : top left of the rectangle
x1, y1 : bottom right of the rectangle
mode : pixel color, either PAL_COLOR_BLACK,  PAL_COLOR_WHITE or PAL_COLOR_REVERSE

RETURNS nothing
DESCRIPTION

draw a rectangle from corner (x0, y0) to corner (x1, y1)

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_rectangle(10, 10, 30, 30, PAL_COLOR_WHITE) ;

draw a character

PROTOTYPE void  PAL_char(unsigned char x, unsigned char y, unsigned char c, unsigned char size)
PARAMETERS

x : pixel column of the top left position of the character, from 0 to 127
y : pixel row of the character, from 0 to number of vertical pixels
c : ASCII code of the char
size : high nibble is height multiplier, low nibble is width multiplier
predefined sizes : PAL_CHAR_STANDARD, PAL_CHAR_DWIDTH, PAL_CHAR_DHEIGHT, PAL_CHAR_DSIZE

RETURNS nothing
DESCRIPTION

draw char c at (x, y), always in white on black (use PAL_box() to reverse video)

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_char(3, 5, 'A', PAL_CHAR_DSIZE) ;

DRAW A STRING

PROTOTYPE void  PAL_write(unsigned char lig, unsigned char col, unsigned char *s, unsigned char size)
PARAMETERS

lig : text line of the string
col : text column of the string
s : pointer to the string (NULL terminated)
size : high nibble is height multiplier, low nibble is width multiplier
predefined sizes : PAL_CHAR_STANDARD, PAL_CHAR_DWIDTH, PAL_CHAR_DHEIGHT, PAL_CHAR_DSIZE

RETURNS nothing
DESCRIPTION

write string s at position (lig, col)

REQUIRES

PAL_init() must have been called

EXAMPLE

PAL_write(0, 5, myString, PAL_CHAR_STANDARD) ;

DRAW a CONSTANT STRING

PROTOTYPE void  PAL_constWrite(unsigned char lig, unsigned char col, const unsigned char *s, unsigned char size)
PARAMETERS

lig : text line of the string
col : text column of the string
s : pointer to the constant string (NULL terminated)
size : high nibble is height multiplier, low nibble is width multiplier
predefined sizes : PAL_CHAR_STANDARD, PAL_CHAR_DWIDTH, PAL_CHAR_DHEIGHT, PAL_CHAR_DSIZE 

RETURNS nothing
DESCRIPTION

same as PAL_write(), but s is a string located in ROM

REQUIRES

PAL_init() must have been called

EXAMPLE PAL_write(0, 5, myConstantString, PAL_CHAR_STANDARD) ;

DRAW A PICTURE

PROTOTYPE void    PAL_picture(unsigned char x, unsigned char y, const unsigned char *bm, unsigned char sx, unsigned char sy)
PARAMETERS

x : top left pixel column of the picture
y : top left pixel row of the picture
bm : pointer to a bitmap picture in ROM
sx : width of the picture
sy : height of the picture

RETURNS nothing
DESCRIPTION

draw the picture pointed to by bm at position (x, y)
bitmap is arranged as a monochrome bitmap, use mikroElektronika GLCD bitmap editor and select T6963 to convert bitmap into source code

REQUIRES

PAL_init() must have been called

EXAMPLE

PAL_picture(0, 0, pict, 128, 128) ;

VIDEO ROUTINE

PROTOTYPE void    PAL_ISR()
PARAMETERS

none

RETURNS nothing
DESCRIPTION

this function must not be called directly by user, but must be placed within the interrupt() function.

Warning : other interrupts may cause bad video synchronization if they are enabled.

REQUIRES

PAL_init() must have been called

EXAMPLE

void    interrupt(void)
        {
        PAL_ISR() ;
        }


CIRCUIT EXAMPLE

  PIC PAL VIDEO PROCESSOR CIRCUIT

Click on the picture to enlarge

The core of the circuit is a PIC18F4620 :

C1, C3 and C4 are decoupling capacitors

The PIC is clocked with a 8 Mhz crystal

D1 is used as temperature sensor connected to PIC ADC

Video signal is mixed through R8 and R9

Switches with pull-downs are used for settings

You can connect the video out signal directly to the composite video input of your TV.

 

 


PROGRAM EXAMPLE

This program example shows you most of the features of the PIC PAL Library.

On a PIC18F4620, it uses 25% of the ROM and 55% of the RAM only !

 PIC PAL VIDEO LIBRARY EXAMPLE

 

The first screen of the program example is a 128x128 picture with a blinking border

The program waits for the key RB7 to be pressed and then goes to the second screen

 

 

  PIC PAL VIDEO PROGRAM EXAMPLE

The second screen is a calendar clock with temperature.
The time is displayed both as digital and graphic clock.

Press RB0 to change minutes, RB1 to change hours, RB2 to change month day, RB3 to change month, RB4 to change year.
Press RB5 to adjust temperature.
Press RB7 at the same time to decrement values, instead of to increment.

 

 

MIKROC SOURCE CODE EXAMPLE

Here is the mikroC source code of the program example. You have to use the zipped mikroC project to build it.

This program shows how to use the new mikroC time library too, very usefull to build rapidly clocks & calendars !

/*
 * file         : PALdemo.c
 * project      : PIC PAL SOFTWARE VIDEO GENERATOR DEMO
 * author       : Bruno Gavand
 * compiler     : mikroC V6.2
 * date         : January 17, 2006
 *
 * description  :
 * 	This program displays a clock, a calendar and the temperature on a TV screen
 *      and shows how to use the PIC PAL library.
 *              press RB7 to skip the welcome screen
 *              to adjust clock and calendar, press :
 *                      RB0 to adjust minute
 *                      RB1 to adjust hour
 *                      RB2 to adjust day
 *                      RB3 to adjust month
 *                      RB4 to adjust year
 *                      RB5 to adjust temperature
 *              press RB7 at the same time to decrement.
 *
 * target device :
 *      PIC18F4620 @ 32 Mhz (8 Mhz crystal + HS PLL)
 *
 * Licence :
 *      Feel free to use this source code at your own risks.
 *
 * history :
 *      created january 2007
 *
 * see more details on http://www.micro-examples.com/
 */

#include        "PAL_Library.h"
#include        "pictures.h"

/*************
 * DEFINITIONS
 *************/
 
/*
 * graphic clock
 */
#define CLK_CENTER_X    90      // center
#define CLK_CENTER_Y    60
#define CLK_RADIUS_PSS  28      // clock radius
#define CLK_RADIUS_SS   25      // seconds
#define CLK_RADIUS_MN   20      // minutes
#define CLK_RADIUS_HH   15      // hours

#define DEG_NBHISTO     16      // number of temperature samples

/*
 * number of vertical pixels
 * from 1 to 128 included
 * the more pixels you have :
 * - the less RAM you have
 * - the less MCU time you have
 */
#define PAL_Y      128

/*
 * simple time structure definition
 */
typedef struct
        {
        unsigned char   ss ;    // seconds
        unsigned char   mn ;    // minutes
        unsigned char   hh ;    // hours
        unsigned char   md ;    // day in month, from 1 to 31
        unsigned char   wd ;    // day in week, monday=0, tuesday=1, .... sunday=6
        unsigned char   mo ;    // month number, from 1 to 12 (and not from 0 to 11 as with unix C time !)
        unsigned int    yy ;    // year Y2K compliant, from 1892 to 2038
        } TimeStruct ;

/********************
 * ROM CONSTANTS
 ********************/
 
/*
 * month names
 */
const unsigned char monthStr[13][4] =
	{
	"???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
	} ;

/*
 * day of week names
 */
const unsigned char wDaystr[7][4] =
	{
	"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
	} ;

/********************
 * RAM VARIABLES
 ********************/
 
/*
 * screen memory map
 * do not change this line !
 */
unsigned char   PAL_screen[PAL_X * PAL_Y / 8] ;

/*
 * general purpose string
 */
unsigned char   str[20] ;

char    degRef ;                        // DAC temperature reference
char    degHisto[DEG_NBHISTO] ;         // temperature samples buffer
char    tIdx = 0 ;                      // temperature samples index

unsigned long   secOffset = 0 ;         // reference timestamp
unsigned long   oldCtr = 0 ;            // frame counter backup
TimeStruct      ts ;                    // time struct

/*************************
 * FUNCTIONS
 *************************/

/*
 * adjust time struct member
 */
void    adjust(unsigned char *v, unsigned char min, unsigned char max)
	{
	if(PORTB.F7)
	        {
	        if(*v == min) *v = max ;
	        else (*v)-- ;
	        }
	else
	        {
	        if(*v == max) *v = min ;
	        else (*v)++ ;
	        }
	}

/*
 * convert value v into string pointed to by p, leading zero blanks if blk is set
 */
void    char2str(unsigned char *p, unsigned char v, unsigned char blk)
        {
        *p = v / 10 + '0' ;
        if(blk && (*p == '0'))
                {
                *p = ' ' ;
                }
        p++ ;
        *p = v % 10 + '0' ;
        p++ ;
        *p = 0 ;
        }

/*
 * draw screen with decoration if full is set, using video mode mode
 */
void    drawScreen(unsigned char full, unsigned char mode)
        {
        static unsigned char    osx = CLK_CENTER_X, osy = CLK_CENTER_Y,
		omx = CLK_CENTER_X, omy = CLK_CENTER_Y,
		ohx = CLK_CENTER_X, ohy = CLK_CENTER_Y ;
        unsigned int    i ;
	int		t ;
        unsigned char   ss ;
        unsigned char   sx, sy, mx, my, hx, hy ;

        PAL_control(PAL_CNTL_START, mode) ;

        if(full)                // draw full screen with decoration
                {
                PAL_fill(0) ;
                PAL_constWrite( 0,  0, "\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 1,  0, "\xBA PAL LIBRARY DEMO  \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 2,  0, "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC", PAL_CHAR_STANDARD) ;

                PAL_box(0, 0, 127, 21, PAL_COLOR_REVERSE) ;

                PAL_constWrite( 3,  0, "\xC9\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCB\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBB", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 4,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 5,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 6,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 7,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 8,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite( 9,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite(10,  0, "\xBA        \xBA          \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite(11,  0, "\xCC\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCA\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xB9", PAL_CHAR_STANDARD) ;
                PAL_constWrite(12,  0, "\xBA                   \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite(13,  0, "\xBA                   \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite(14,  0, "\xBA                   \xBA", PAL_CHAR_STANDARD) ;
                PAL_constWrite(15,  0, "\xC8\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xBC", PAL_CHAR_STANDARD) ;

                PAL_write(4, 3, "H  :", PAL_CHAR_DHEIGHT) ;

                PAL_constWrite(12, 3, "TEMP. : ", 0x31) ;
                PAL_constWrite(12, 17, "\xf8C", 0x31) ;

                for(ss = 0 ; ss < 60 ; ss++)
                        {
                        sx = CLK_CENTER_X - (cosE3(90 + 6 * ss) * CLK_RADIUS_PSS) / 1000 ;
                        sy = CLK_CENTER_Y - (sinE3(90 + 6 * ss) * CLK_RADIUS_PSS) / 1000 ;
                        
                        PAL_setPixel(sx, sy, PAL_COLOR_WHITE) ;
                        
                        if((ss % 5) == 0)
                                {
                                PAL_setPixel(sx + 1, sy, PAL_COLOR_WHITE) ;
                                PAL_setPixel(sx - 1, sy, PAL_COLOR_WHITE) ;
                                PAL_setPixel(sx, sy + 1, PAL_COLOR_WHITE) ;
                                PAL_setPixel(sx, sy - 1, PAL_COLOR_WHITE) ;
                                }
                        }
                }

	if(PAL_frameCtr > OldCtr)       // it's time to update the clock & calendar
		{
		unsigned char   h ;
		
	        oldCtr = PAL_frameCtr + 24 ;    // prepare oldCtr for next update time

		Time_EpochToDate(secOffset + PAL_frameCtr / 25, &ts) ;  // convert timestamp to date and time

		/*
		 * draw analog clock
		 */
	        sx = CLK_CENTER_X - (cosE3(90 + 6 * ts.ss) * CLK_RADIUS_SS) / 1000 ;
	        sy = CLK_CENTER_Y - (sinE3(90 + 6 * ts.ss) * CLK_RADIUS_SS) / 1000 ;

	        mx = CLK_CENTER_X - (cosE3(90 + 6 * ts.mn) * CLK_RADIUS_MN) / 1000 ;
	        my = CLK_CENTER_Y - (sinE3(90 + 6 * ts.mn) * CLK_RADIUS_MN) / 1000 ;

		h = (ts.hh % 12) * 5 + (ts.mn / 8) ;
	        hx = CLK_CENTER_X - (cosE3(90 + 6 * h) * CLK_RADIUS_HH) / 1000 ;
	        hy = CLK_CENTER_Y - (sinE3(90 + 6 * h) * CLK_RADIUS_HH) / 1000 ;

	        if((hx != ohx) || (hy != ohy))
	                {
	                PAL_line(CLK_CENTER_X, CLK_CENTER_Y, ohx, ohy, PAL_COLOR_BLACK) ;
	                }
	        if((mx != omx) || (my != omy))
	                {
	                PAL_line(CLK_CENTER_X, CLK_CENTER_Y, omx, omy, PAL_COLOR_BLACK) ;
	                }
	        if((sx != osx) || (sy != osy))
	                {
	                PAL_line(CLK_CENTER_X, CLK_CENTER_Y, osx, osy, PAL_COLOR_BLACK) ;
	                }
	        PAL_line(CLK_CENTER_X, CLK_CENTER_Y, hx, hy, PAL_COLOR_WHITE) ;
	        PAL_line(CLK_CENTER_X, CLK_CENTER_Y, mx, my, PAL_COLOR_WHITE) ;
	        PAL_line(CLK_CENTER_X, CLK_CENTER_Y, sx, sy, PAL_COLOR_WHITE) ;

		/*
		 * print date and time
		 */
	        char2str(str, ts.ss, 0) ;
	        PAL_write(4, 7, str, PAL_CHAR_DHEIGHT) ;

	        char2str(str, ts.mn, 0) ;
	        PAL_write(4, 4, str, PAL_CHAR_DHEIGHT) ;

	        char2str(str, ts.hh, 1) ;
	        PAL_write(4, 1, str, PAL_CHAR_DHEIGHT) ;

	        PAL_constWrite(6, 2, wdayStr[ts.wd], PAL_CHAR_STANDARD) ;
	        PAL_constWrite(7, 2, monthStr[ts.mo], PAL_CHAR_DHEIGHT) ;

	        char2str(str, ts.md, 1) ;
	        PAL_write(6, 5, str, 0x32) ;

	        wordToStr(ts.yy, str) ;
	        PAL_write(9, 1, str + 1, PAL_CHAR_DSIZE) ;

		/*
		 * save old value for fast analog clock cleaning at next update
		 */
	        osx = sx ;
	        osy = sy ;
	        omx = mx ;
	        omy = my ;
	        ohx = hx ;
	        ohy = hy ;

                t = degRef - Adc_Read(4) ;      // read temperature sensor

                t *= 221 ;           // temperature coefficient of the silicon junction
                t /= 102 ;
                t = 25 + t ;      // get the result in celcius

		/*
		 * adjust limits
		 */
                if(t < -99)
                        {
                        t = -99 ;
                        }
		if(t > 99)
		        {
		        t = 99 ;
		        }

		/*
		 * average values
		 */
                degHisto[tIdx] = t ;
                tIdx++ ;
                if(tIdx == DEG_NBHISTO)
                        {
                        tIdx = 0 ;
                        }
                t = 0 ;
                for(i = 0 ; i < DEG_NBHISTO ; i++)
                        {
                        t += degHisto[i] ;
                        }
		t /= DEG_NBHISTO ;

		/*
		 * print temperature
		 */
	        if(t < 0)
	                {
	                i = -t ;
	                PAL_constWrite(12, 11, "-", 0x31) ;
	                }
	        else
	                {
	                i = t ;
	                PAL_constWrite(12, 11, " ", 0x31) ;
	                }
	        char2str(str, i, 1) ;
	        PAL_write(12, 12, str, 0x32) ;
	        }

        PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ;          // restore video rendering if it was stopped
        }

/*
 * interrupt service routine
 */
void    interrupt(void)
        {
        /*
         * do PAL stuff
         */
        PAL_ISR() ;             // library call
        }

/*
 * main program
 */
void main(void)
        {
        unsigned char i ;
        
	/*
	 * I/O configuration
	 */
        ADCON1 = 0x0f ;
        TRISA = 0xff ;
        PORTA = 0 ;
        
        TRISB = 0xff ;
        PORTB = 0 ;
        
        TRISC = 0xff ;
        PORTC = 0 ;
        
        TRISD = 0 ;
        PORTD = 0 ;
        
        TRISE = 0 ;
        PORTE = 0 ;
        
        degRef = EEPROM_read(0) ;       // get temperature calibration from EEPROM

	/*
	 * default time and date
	 */
        ts.ss = 0 ;
        ts.mn = 0 ;
        ts.hh = 12 ;
        ts.md = 1 ;
        ts.mo = 1 ;
        ts.yy = 2007 ;

        secOffset = Time_dateToEpoch(&ts) ;

	/*
	 * start video and display first screen
	 */
        PAL_init(PAL_Y) ;       // init PAL library
        PAL_fill(0) ;           // clear screen
        PAL_picture(0, 0, logo_bmp, 128, 128) ;         // paint picture
        PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ;  // start video and rendering

	i = 0 ;
        while(PORTB == 0)	// wait for a key to be pressed
                {
                /*
		 * change border color two times per second
		 */
                if(PAL_frameCtr > 12)
                        {
			PAL_setBorder(i) ;
			i = !i ;
			PAL_frameCtr = 0 ;
			}
		}
	PAL_setBorder(PAL_COLOR_BLACK) ;      // clear border

        drawScreen(1, PAL_CNTL_BLANK) ;         // draw full screen in blank mode (faster)

        for(;;)
                {
                if(PORTB & 0b1111111)   // a key is pressed
                        {
			Time_EpochToDate(secOffset + PAL_frameCtr / 25, &ts) ;

			/*
			 * calendar settings
			 */
                        if(PORTB.F0)
                                {
                                adjust(&ts.mn, 0, 59) ;
				ts.ss = 0 ;
                                }
                        if(PORTB.F1)
                                {
                                adjust(&ts.hh, 0, 59) ;
				ts.ss = 0 ;
                                }
                        if(PORTB.F2)
                                {
                                adjust(&ts.md, 1, 31) ;
                                }
                        if(PORTB.F3)
                                {
                                adjust(&ts.mo, 1, 12) ;
                                }
                        if(PORTB.F4)
                                {
                                if(PORTB.F7) ts.yy-- ; else ts.yy++ ;
                                }

		        secOffset = Time_dateToEpoch(&ts) ;   // new timestamp

			/*
			 * temperature calibration
			 */
                        if(PORTB.F5)
                                {
                                if(PORTB.F7)
                                        {
	                                degRef-- ;
	                                EEPROM_write(0, degref) ;
                                        }
				else
				        {
	                                degRef++ ;
	                                EEPROM_write(0, degref) ;
	                                }
                                }

			while(PORTB & 0b1111111) ;      // wait for the key to be released
			
		        PAL_frameCtr = 0 ;      // reset counters
			oldCtr = 0 ;
                        }

                drawScreen(0, PAL_CNTL_RENDER) ;        // update screen
                }
        }

PROJECT DOWNLOAD

You can use this software as you wish, if you accept to do it at your own risks.

Download PIC PAL Library with demo example for mikroC : zipped file, 29.64 Ko 

content of the archive :

  • PAL_library.c, 37 Ko : library C source code
  • PAL_library.h, 2 Ko : library C definitions
  • PALdemo.c, 15 Ko : demo example C source code
  • PALdemo.eed, 1 Ko : PIC EEPROM definition
  • PALdemo.hex, 46 Ko : demo example HEX file for PIC18F4620
  • PALdemo.ppc, 2 Ko : mikroC project file
  • pictures.h, 9 Ko : demo example picture bitmap

You can get mikroC from here : http://www.mikroe.com/en/compilers/mikroc/pic/


Please report any bug, comment or suggestion in my forums. Thanks !


All trademarks and registered trademarks are the property of their respective owners