Escolar Documentos
Profissional Documentos
Cultura Documentos
*************************************************************************
******
* LCDscope : a PIC18 oscilloscope on a 20x4 text LCD
* also works with a standard 16x4 text LCD
*************************************************************************
******
*
* This program shows how to use custom chars on a text LCD to build a
tiny graphic screen
* To illustrate this, here is a quick & dirty mini oscilloscope.
*
* Author : Bruno Gavand, February 2009
* see more details on http://www.micro-examples.com/
*
* source code for mikro C compiler V8.2
* feel free to use this code at your own risks
*
* target : PIC18 with 10 Mhz crystal, HS PLL
*
* PIC PIN Assignemnt :
*
* RA0 : analog input, 0-5V
*
* control buttons on PORTB (internal pull-ups, switchs to GND) :
* RB0/RB1 : change horizontal frequency
* RB2/RB3 : change input range
* RB4 : hold/release screen
*
* 4-bit LCD on PORTD :
* RD2 : RS
* RD3 : E
* RD4 : D4
* RD5 : D5
* RD6 : D6
* RD7 : D7
* Note : R/W pin of LCD must be tied to ground.
*
* Credits to CircuitED for the 20x4 black/yellow LCD
* http://www.circuit-ed.com/
* Thank you Warren !
*
*************************************************************************
******
*/
/*********************
* CONSTANTS
*********************/
#ifdef LCD20x4
// scrolling message
unsigned char msg[][8] =
{
" ",
" ",
" ",
" ",
" LCD ",
" SCOPE ",
" By ",
"BrunoG ",
"* ",
" ",
" ",
" see ",
" more ",
"details",
" and ",
"dwnload",
"mikroC ",
"source ",
"code on",
" ",
"www. ",
"micro- ",
"example",
"s.com ",
"* ",
" ",
" ",
"20x4LCD",
"Black/ ",
"Yellow ",
"BkLight",
"specs.&",
"price :",
" ",
"www. ",
"circuit",
"-ed.com",
"* ",
" ",
" ",
" Thank ",
" you ",
"Warren!",
""
} ;
unsigned char firstMsg = 0 ; // scrolling message index
#endif
/****************************
* INTERRUPT ROUTINE
****************************/
void interrupt()
{
// only timer 0 overflow is due to service
if(INTCON.TMR0IF)
{
if(sIdx < miniGLCD_x) // is sampling in
progress ?
{
if(trigger == 2) // is sampling
triggered ?
{
// read ADC sample, adjust to range and
store to sample buffer
samples[sIdx++] = miniGLCD_y - (ADRESH >>
vdiv) ;
}
else if(trigger == 1) // maximum was
detected
{
// is signal rising down ?
if((trigValue > LEVEL) && (ADRESH <
trigValue - LEVEL))
{
// yes, triggers sampling
trigger = 2 ;
}
else
{
// no, update maximum value
if(ADRESH > trigValue)
{
trigValue = ADRESH ;
}
}
}
else // looking for
maximum
{
// is signal rising up ?
if((trigValue < 255 - LEVEL) && (ADRESH >
trigValue + LEVEL))
{
// yes, next step is to wait for
signal rising down
trigger = 1 ;
trigValue = 0 ;
}
else
{
// no, update minimum value
if(ADRESH < trigValue)
{
trigValue = ADRESH ;
}
}
}
// start ADC, no sampling is required since ADC
// is always connected to the same input
ADCON0.GO = 1 ;
}
t0ctr++ ;
INTCON.TMR0IF = 0 ;
}
}
/*******************************
* UPDATE SETTINGS & DRAW SCREEN
*******************************/
void mkScreen()
{
T0CON = timeBase[tbase].t0con ; // new
timer 0 settings
vdiv = input[ipt].div ; // store
input divider
// ADC settings
ADCON1 = 0b00001110 ;
ADCON0 = 0b11000001 ;
#ifdef LCD20x4
LCD_out(1, 14, timeBase[tbase].period) ; //
display period value
LCD_chr(2, 15, timeBase[tbase].unit) ; //
display period unit
// hold screen ?
LCD_out(1, 9, hold ? "Hold" : "\xff\xff\xff\xff") ;
#else
LCD_out(1, 12, timeBase[tbase].period) ; //
display period value
LCD_chr(2, 12, timeBase[tbase].unit) ; //
display period unit
// hold screen ?
LCD_out(1, 6, hold ? "H" : "\xff") ;
#endif
}
/************************
* UPDATE SCREEN AND DEBOUNCE PORTB KEYS
************************/
void debounce()
{
mkScreen() ;
Delay_ms(20) ;
while(PORTB != 0xff) ;
Delay_ms(20) ;
}
/***********************
* PSEUDO GRAPHIC FUNCTIONS
***********************/
/************************************************
* miniGLCD_fill : fill graphic screen with pattern
* parameters :
* c : filling pattern
* for example : 0 for black screen, 0xff for white screen
* returns :
* nothing
* requires :
* miniGLCD_init must have been called
* notes :
* none
*/
void miniGLCD_fill(unsigned char c)
{
memset(miniGLCD_screen, c, sizeof(miniGLCD_screen)) ;
}
/********************************************
* miniGLCD_setPixel : write pixel
* parameters :
* x : pixel row
* y : pixel column
* mode : miniGLCD_COLOR_WHITE or miniGLCD_COLOR_BLACK or
miniGLCD_COLOR_REVERSE
* returns :
* nothing
* requires :
* miniGLCD_init must have been called
* notes :
* none
*/
void miniGLCD_setPixel(char x, char y, unsigned char mode)
{
unsigned char *ptr ;
unsigned char mask ;
/*
* do nothing if pixel is out of bounds
*/
if(x < 0) return ;
if(y < 0) return ;
if(x > miniGLCD_x) return ;
if(y > miniGLCD_y) return ;
switch(mode)
{
case miniGLCD_COLOR_BLACK:
*ptr &= ~mask ; // clear bit
break ;
case miniGLCD_COLOR_WHITE: // set bit
*ptr |= mask ;
break ;
default:
*ptr ^= mask ; // toggle bit
break ;
}
}
/********************************************
* miniGLCD_setPixel : read pixel
* parameters :
* x : pixel row
* y : pixel column
* returns :
* color of pixel at (x, y)
* requires :
* miniGLCD_init must have been called
* notes :
* none
*/
unsigned char miniGLCD_getPixel(char x, char y)
{
unsigned char *ptr ;
unsigned char mask ;
/*
* do nothing if pixel is out of bounds
*/
if(x < 0) return(0) ;
if(y < 0) return(0) ;
if(x > miniGLCD_x) return(0) ;
if(y > miniGLCD_y) return(0) ;
/******************************
* miniGLCD_line : draw a line
* parameters :
* x0, y0 : pixel start coordinates
* x1, y1 : pixel end coordinates
* pcolor : miniGLCD_COLOR_WHITE or miniGLCD_COLOR_BLACK or
miniGLCD_COLOR_REVERSE
* returns :
* nothing
* requires :
* miniGLCD_init must have been called
* notes :
* uses Bresenham's line drawing algorithm
*/
void miniGLCD_line(char x0, char y0, char x1, char y1, unsigned char
pcolor)
{
int dy ;
int dx ;
int stepx, stepy ;
dy = y1 - y0 ;
dx = x1 - x0 ;
if(dy < 0)
{
dy = -dy ;
stepy = -1 ;
}
else
{
stepy = 1 ;
}
if(dx < 0)
{
dx = -dx ;
stepx = -1 ;
}
else
{
stepx = 1 ;
}
dy <<= 1 ;
dx <<= 1 ;
while(x0 != x1)
{
if(fraction >= 0)
{
y0 += stepy ;
fraction -= dx ;
}
x0 += stepx ;
fraction += dy ;
miniGLCD_setPixel(x0, y0, pcolor) ;
}
}
else
{
int fraction = dx - (dy >> 1) ;
while(y0 != y1)
{
if(fraction >= 0)
{
x0 += stepx ;
fraction -= dy ;
}
y0 += stepy ;
fraction += dx ;
miniGLCD_setPixel(x0, y0, pcolor) ;
}
}
}
/*************************************************************
* program custom character n at line pos_row column pos_char
* if mode is not zero, also write custom char to LCD
*/
void CustomChar(unsigned char mode, unsigned char n, char pos_row, char
pos_char)
{
unsigned char i, j ;
LCD_Cmd(64 + n * 8) ;
for(i = 0 ; i < 8 ; i++)
{
unsigned char bm = 0 ;
/******************
* MAIN LOOP
******************/
void main()
{
unsigned char i, j ;
unsigned int wait ;
TRISA = 0xff ; // set PORTA as inputs
// LCD configuration
LCD_Init(&LATD) ; // Initialize LCD
connected to PORTD
LCD_Cmd(Lcd_CLEAR) ; // Clear display
LCD_Cmd(Lcd_CURSOR_OFF) ; // Turn cursor off
// display layout
#ifdef LCD20x4
LCD_out(1, 8, "\xff\xff\xff\xff\xff\xff") ;
LCD_out(2, 8, "\xff \xff s/Div") ;
LCD_out(3, 8, "\xff \xff") ;
LCD_out(4, 8, "\xff\xff\xff\xff\xff\xff V/Div") ;
#else
LCD_out(1, 1, " \xff \xff") ;
LCD_out(2, 1, "V/Div\xff \xff s/Div") ;
#endif
mkScreen() ;
for(;;) // forever
{
// if not in hold mode and samples buffer is full
if((hold == 0) && (sIdx == miniGLCD_x))
{
// clear pseudo-screen
miniGLCD_fill(0) ;
// draw wave
for(i = 0 ; i < miniGLCD_x - 1 ; i++)
{
j = i + 1 ;
miniGLCD_line(i, samples[i], j,
samples[j], miniGLCD_COLOR_WHITE) ;
}
// hold/release screen
else if(PORTB.F4 == 0)
{
hold ^= 1 ;
debounce() ;
}
// scrolling message
#ifdef LCD20x4
if(wait)
{
if(t0ctr > (1u << (tbase + 5)))
{
firstMsg++ ;
if(msg[firstMsg][0] == 0)
{
firstMsg = 0 ;
}
t0ctr = 0 ;
wait = 0 ;
}
}
else if(t0ctr > (1u << (tbase + 1)))
{
j = firstMsg ;
for(i = 1 ; i <= 4 ; i++)
{
if((i == 4) && (msg[j + 1][0] == '*'))
{
wait++ ;
}
if(msg[j][0] == '*')
{
LCD_out(i, 1, " ") ;
}
else
{
LCD_out(i, 1, msg[j]) ;
}
j++ ;
if(msg[j][0] == 0)
{
j = 0 ;
}
}
firstMsg++ ;
if(msg[firstMsg][0] == 0)
{
firstMsg = 0 ;
}
t0ctr = 0 ;
}
#endif
}
}