Code: Select all
////////////////////////////////////////////////////////////////////////////////
// KS0108 128 x 64 Graphical LCD
// Oscilloscope Example
//
// Filename : 18F2550 GLCD Oscilloscope DR1r1.c
// Programmer : Steven Cholewiak, www.semifluid.com
// Version : Version 1.0 08/21/2006
// : Modified for MikroC compiler and librarie by Doug Slocum
// Remarks : This example draws a digital oscilloscope display to a KS0108
// graphical LCD. Please note the limitations of the PIC's analog
// port and make sure to buffer the input for the most accurate
// reading.
//
// More information on the circuit can be found at:
// http://www.semifluid.com/PIC18F2550_GLCD_Oscilloscope.php
////////////////////////////////////////////////////////////////////////////////
unsigned short useThreshold = 0; // 0 = Off, 1 = Rising, 2 = Falling
unsigned short theThreshold = 127;
unsigned short timeType = 1; // 1 = us, 2 = ms
unsigned long timePeriod = 4; // us or ms per measurement (* 25 for each div)
unsigned short voltageRange = 1; // 1 = 0 - 5V, 2 = 0 - 2.5V, 3 = 0 - 1.25V
float voltageConst = 0.079365; // For displaying the scaled voltage
char strAverageV[] = "Av";
char strVMaximum[] = "Mx";
char strVMinimum[] = "Mn";
char strVPtoP[] = "PP";
char strThreshold[] ="Th";
char strOff[] = "Off";
char strRising[] = "Rise";
char strFalling[] = "Fall";
char strTime[] = "Tm";
char strMs[] = "ms/div";
char strHz[] = "Hz";
char strRange[] = "R";
char strR0to5[] = "0-5";
char strR0to25[] = "0-2.5";
char strR0to12[] = "0-1.2";
// Glcd module connections
char GLCD_DataPort at PORTD;
sbit GLCD_CS1 at RB0_bit;
sbit GLCD_CS2 at RB1_bit;
sbit GLCD_RS at RB2_bit;
sbit GLCD_RW at RB3_bit;
sbit GLCD_EN at RB4_bit;
sbit GLCD_RST at RB5_bit;
sbit GLCD_CS1_Direction at TRISB0_bit;
sbit GLCD_CS2_Direction at TRISB1_bit;
sbit GLCD_RS_Direction at TRISB2_bit;
sbit GLCD_RW_Direction at TRISB3_bit;
sbit GLCD_EN_Direction at TRISB4_bit;
sbit GLCD_RST_Direction at TRISB5_bit;
// End Glcd module connections
void displayFloat(unsigned short x, unsigned short y, float oldValue, float theValue) {
char toPrintOld[9];
char toPrint[9];
sprintf(toPrintOld, "%f", oldValue);
sprintf(toPrint, "%f", theValue);
toPrintOld[4] = '\0';
toPrint[4] = '\0'; // Limit shown digits to 3
Glcd_Write_Text(toPrintOld, x, y, 0);
Glcd_Write_Text(toPrint, x, y, 1);
}
void displayShort(unsigned short x, unsigned short y, unsigned short oldValue, unsigned short theValue) {
char toPrintOld[4];
char toPrint[4];
sprintf(toPrintOld, "%u", oldValue);
sprintf(toPrint, "%u", theValue);
toPrintOld[3] = '\0';
toPrint[3] = '\0'; // Limit shown digits to 3
Glcd_Write_Text(toPrintOld, x, y, 0);
Glcd_Write_Text(toPrint, x, y, 1);
}
void displayInt(unsigned short x, unsigned short y, unsigned int oldValue, unsigned int theValue) {
char toPrintOld[6];
char toPrint[6];
sprintf(toPrintOld, "%lu", oldValue);
sprintf(toPrint, "%lu", theValue);
toPrintOld[5] = '\0';
toPrint[5] = '\0'; // Limit shown digits to 5
Glcd_Write_Text(toPrintOld, x, y, 0);
Glcd_Write_Text(toPrint, x, y, 1);
}
void changeThreshold(unsigned short theUsage, unsigned short theValue) {
float tempFloat = 0.0;
tempFloat = (theThreshold>>2) * voltageConst;
if (theUsage == 0)
Glcd_Write_Text(strOff, 12, 24, 0);
else if (theUsage == 1) {
Glcd_Write_Text(strRising, 12, 24, 0);
displayFloat(12, 30, tempFloat, (theValue>>2) * voltageConst);
}
else if (theUsage == 2) {
Glcd_Write_Text(strFalling, 12, 24, 0);
displayFloat(12, 30, tempFloat, (theValue>>2) * voltageConst);
}
useThreshold = theUsage;
theThreshold = theValue;
Glcd_Write_Text(strThreshold, 0, 24, 1);
if (useThreshold == 0) Glcd_Write_Text(strOff, 12, 24, 1);
else if (useThreshold == 1) Glcd_Write_Text(strRising, 12, 24, 1);
else if (useThreshold == 2) Glcd_Write_Text(strFalling, 12, 24, 1);
}
void changeTimeDivision(unsigned short theType, unsigned int theValue) {
float tempFloat = 0.0, tempFloat2 = 0.0;
Glcd_Write_Text(strTime, 0, 36, 1);
if (theType == 1) {
tempFloat = timePeriod * 25;
tempFloat2 = theValue * 25;
displayFloat(12, 36, tempFloat/1000, tempFloat2/1000);
}
else if (theType == 2)
displayFloat(12, 36, timePeriod * 25, theValue * 25);
timeType = theType;
timePeriod = theValue;
if ((theType == 1) && (timePeriod < 16)) timePeriod = 16;
Glcd_Write_Text(strMs, 4, 42, 1);
}
void changeVoltageRange(unsigned short theType) {
Glcd_Write_Text(strRange, 0, 54, 1);
if (voltageRange == 1) Glcd_Write_Text(strR0to5, 8, 54, 0);
else if (voltageRange == 2) Glcd_Write_Text(strR0to25, 8, 54, 0);
else if (voltageRange == 3) Glcd_Write_Text(strR0to12, 8, 54, 0);
voltageRange = theType;
if (voltageRange == 1) voltageConst = 0.079365;
else if (voltageRange == 2) voltageConst = 0.039683;
else if (voltageRange == 3) voltageConst = 0.019841;
if (voltageRange == 1) Glcd_Write_Text(strR0to5, 8, 54, 1);
else if (voltageRange == 2) Glcd_Write_Text(strR0to25, 8, 54, 1);
else if (voltageRange == 3) Glcd_Write_Text(strR0to12, 8, 54, 1);
}
void main() {
unsigned short const numOfSamples = 100;
unsigned int HQadcReadings[numOfSamples];
unsigned short adcReadings[numOfSamples], adcReadingsOld[numOfSamples];
unsigned short i = 0;
unsigned short thres2 = 1;
unsigned int tempThres = 0, k = 0;
float avgV = 0.0, avgVOld = 0.0;
float maxV = 0.0, maxVOld = 0.0;
float minV = 0.0, minVOld = 0.0;
float ptopV = 0.0, ptopVOld = 0.0;
unsigned int theFreq = 0.0, theFreqOld = 0.0;
//SETUP_ADC_PORTS(AN0 | VSS_VDD); // Setup ADC Pins
ADCON0 = 0x01; // Configure AN0 pin as analog, and enabled
ADCON1 = 0x0E; // Configure other AN pins as digital I/O
ADCON2 = 0; //
//SETUP_ADC(ADC_CLOCK_DIV_64); // Setup ADC
//SETUP_TIMER_0(RTCC_INTERNAL|RTCC_DIV_1); // Use the int. osc. for Timer 0
//SETUP_TIMER_1(T1_DISABLED); // Disable Timer 1
//SETUP_TIMER_2(T2_DISABLED, 127, 1); // Disable Timer 2
//SETUP_TIMER_3(T3_DISABLED); // Disable Timer 3
//SETUP_CCP1(CCP_OFF); // Disable CCP1
//C1ON_bit = 0; ??? CMCON maybe?
/*
There are comparators that are connected to PORTD.
You also need to turn them off.
Add CMCON = 0x07 This should turn them off.
Also ADCON1 = 0x07 does not turn off all the A/D channels, it needs to be ADCON1 = 0x0F. This is just for reference because you did have the A/D's turned off for the Ports that you were using.
*/
//SETUP_CCP2(CCP_OFF); // Disable CCP2
//C2ON_bit = 0; ???
//enable_interrupts(INT_RDA);
// ???
//enable_interrupts(GLOBAL);
// ???
Glcd_Init(); // Must initialize the LCD
Glcd_Line((128-numOfSamples),0,(128-numOfSamples),63,1);
Glcd_Set_Font(Font_Glcd_System3x5, 3, 5, 32);
// Draw static text
Glcd_Write_Text(strAverageV, 0, 0, 1);
Glcd_Write_Text(strVMaximum, 0, 6, 1);
Glcd_Write_Text(strVMinimum, 0, 12, 1);
Glcd_Write_Text(strVPtoP, 0, 18, 1);
Glcd_Write_Text(strHz, 20, 48, 1);
// Setup variable ranges
changeVoltageRange(1); // Set voltage range
changeTimeDivision(1, 20); // Set time divisions
changeThreshold(1, 127); // Set threshold level
//set_adc_channel(0);
delay_ms(10);
delay_ms(100);
while (1) {
// If using threshold, wait until it has been reached
if (voltageRange == 1) tempThres = (unsigned int) theThreshold << 2;
else if (voltageRange == 2) tempThres = (unsigned int) theThreshold << 1;
else if (voltageRange == 3) tempThres = (unsigned int) theThreshold;
if (useThreshold == 1) {
k = 0;
while ((ADC_Read(2)>tempThres) && (k<65535)) (k++);
k = 0;
while ((ADC_Read(2)<tempThres) && (k<65535)) (k++);
}
else if (useThreshold == 2) {
k = 0;
while ((ADC_Read(2)<tempThres) && (k<65535)) (k++);
k = 0;
while ((ADC_Read(2)>tempThres) && (k<65535)) (k++);
}
// Collect ADC readings
if (timeType == 1)
for (i=0; i<numOfSamples; i++) {
HQadcReadings[i] = ADC_Read(2);
//VDelay_us(timePeriod-16);
}
else if (timeType == 2)
for (i=0; i<numOfSamples; i++) {
HQadcReadings[i] = ADC_Read(2);
VDelay_ms(timePeriod);
}
for (i=0; i<numOfSamples; i++) {
if (voltageRange == 1) adcReadings[i] = 63-(HQadcReadings[i]>>4);
else if (voltageRange == 2) adcReadings[i] = 63-(HQadcReadings[i]>>3);
else if (voltageRange == 3) adcReadings[i] = 63-(HQadcReadings[i]>>2);
}
// Draw ADC readings
for (i=1; i<numOfSamples; i++)
Glcd_Dot(i+(128-numOfSamples),adcReadingsOld[i],0);
for (i=1; i<numOfSamples; i++)
Glcd_Dot(i+(128-numOfSamples),adcReadings[i],1);
for (i=0; i<numOfSamples; i++)
adcReadingsOld[i] = adcReadings[i];
// Calculate and display frequency of signal using zero crossing
// displayunsigned short(0, 54, thres2, 0);
if (useThreshold != 0) {
for (i=0; i<63; i+=3)
Glcd_Dot(thres2+(128-numOfSamples),i,0);
if (useThreshold == 1) {
thres2 = 1;
while ((adcReadings[thres2]<(63-(theThreshold>>2))) && (thres2<numOfSamples-1)) (thres2++);
thres2++;
while ((adcReadings[thres2]>(63-(theThreshold>>2))) && (thres2<numOfSamples-1)) (thres2++);
}
else if (useThreshold == 2) {
thres2 = 1;
while ((adcReadings[thres2]>(63-(theThreshold>>2))) && (thres2<numOfSamples-1)) (thres2++);
thres2++;
while ((adcReadings[thres2]<(63-(theThreshold>>2))) && (thres2<numOfSamples-1)) (thres2++);
}
// display unsigned short(0, 54, 0, thres2);
for (i=0; i<63; i+=3)
Glcd_Dot(thres2+(128-numOfSamples),i,1);
k = (unsigned int) thres2 * timePeriod;
if (timeType == 1) theFreq = (float) 1000/k * 1000;
if (timeType == 2) theFreq = (float) 1000/k;
displayInt(0, 48, theFreqOld, theFreq);
theFreqOld = theFreq;
}
// Calculate and display Average V
avgV = 0;
for (i=0; i<numOfSamples; i++)
avgV = (float) avgV + adcReadings[i];
avgV = (float) (63-(avgV / numOfSamples)) * voltageConst;
displayFloat(12, 0, avgVOld, avgV);
avgVOld = avgV;
// Calculate and display Maximum V
maxV = 63;
for (i=0; i<numOfSamples; i++)
if (adcReadings[i]<maxV) maxV = adcReadings[i];
maxV = (float) (63-maxV) * voltageConst;
displayFloat(12, 6, maxVOld, maxV);
maxVOld = maxV;
// Calculate and display Minimum V
minV = 0;
for (i=0; i<numOfSamples; i++)
if (adcReadings[i]>minV) minV = adcReadings[i];
minV = (float) (63-minV) * voltageConst;
displayFloat(12, 12, minVOld, minV);
minVOld = minV;
// Calculate and display Peak-to-peak V
ptopV = maxV - minV;
displayFloat(12, 18, ptopVOld, ptopV);
ptopVOld = ptopV;
// Display graph lines
if (useThreshold != 0)
for (i=29; i<127; i+=3)
Glcd_Dot(i,63-(theThreshold>>2),1);
for (i=0; i<63; i+=5) {
Glcd_Dot(53,i,1);
Glcd_Dot(78,i,1);
Glcd_Dot(103,i,1);
Glcd_Dot(127,i,1);
}
delay_ms(100); // Reduces flicker by allowing pixels to be on
// much longer than off
}
}