// OLED VOLTMETER.
// By moty22.co.uk
// PIC12F675
#include <htc.h> // default library
#include "oled_font.c"
#pragma config WDTE=OFF, MCLRE=OFF, BOREN=OFF, FOSC=INTRCIO, CP=OFF, CPD=OFF //,INTRCIO
#define _XTAL_FREQ 4000000
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
#define SCL GP4 //pin3
#define SDA GP5 //pin2
//prototypes
void command( unsigned char comm);
void oled_init();
void clrScreen();
void sendData(unsigned char dataB);
void startBit(void);
void stopBit(void);
void clock(void);
void drawChar2(char fig, unsigned char y, unsigned char x);
unsigned char addr=0x78; //0b0111 1000
void main(void){
unsigned char d[4];
unsigned int count;
// PIC I/O init
CMCON = 0b111; //comparator off
TRISIO = 0b00001111; //SCL, SDA, input
ANSEL = 0b01010100; // 101=Fosc/16, 0100=AN2 GP2
ADCON0 = 0b10001001; //1=right justified, 0,0,0, 10=AN2, 0, 1 =ADC on
SCL=1;
SDA=1;
__delay_ms(500);
oled_init();
clrScreen(); // clear screen
drawChar2(10, 1, 7); //V
drawChar2(12, 1, 2); //.
while(1) {
GO_DONE = 1; //start ADC
while(GO_DONE){};
count=((ADRESH << 8) + ADRESL)*5; // (0 - 1023) * 5 = 0 - 5115
d[0]=(count/1000) %10; //digit on left
d[1]=(count/100) %10;
d[2]=(count/10) %10;
d[3]=count %10; // digit on right
drawChar2(d[0], 1, 1);
drawChar2(d[1], 1, 3);
drawChar2(d[2], 1, 4);
drawChar2(d[3], 1, 5);
__delay_ms(500);
}
}
//size 2 chars
void drawChar2(char fig, unsigned char y, unsigned char x)
{
unsigned char i, line, btm, top; //
command(0x20); // vert mode
command(0x01);
command(0x21); //col addr
command(13 * x); //col start
command(13 * x + 9); //col end
command(0x22); //0x22
command(y); // Page start
command(y+1); // Page end
startBit();
sendData(addr); // address
sendData(0x40);
for (i = 0; i < 5; i++){
line=font[5*(fig)+i]; // font [5 x 5 + i] = 0x27, 0x45, 0x45, 0x45, 0x39
btm=0; top=0;
// 128x32 OLED has 4 pages (0-3) starting in column 0 and ending in column 127
// top = top page (page1 y) of 5 columns wide and 8 rows deep
// btm = bottom page (page2 y+1) of 5 columns wide and 8 rows deep
// when 1 byte is written the pointer moves to the next column automatically
// the 4 bits on the left determine the top page column
// the 4 bits on the right determine the bottom page column
// 0x93 means top page from top downwards white,white,white,black and bottom page white,black,black,white
if(line & 8) {top +=192;} //
if(line & 4) {top +=48;} //
if(line & 2) {top +=12;} //
if(line & 1) {top +=3;} //
if(line & 128) {btm +=192;} //
if(line & 64) {btm +=48;} //
if(line & 32) {btm +=12;} //
if(line & 16) {btm +=3;} //
/* original code
// expend char
if(line & 64) {btm +=192;} // line & 0100 bottom + 192
if(line & 32) {btm +=48;} // line & 0010 bottom + 48 -> 48
if(line & 16) {btm +=12;} // line & 0001 bottom + 12
if(line & 8) {btm +=3;} // line & 1000 bottom + 3
if(line & 4) {top +=192;} // line & 0100 top + 192 -> 252
if(line & 2) {top +=48;} // line & 0010 top + 48
if(line & 1) {top +=12;} // line & 0001 top + 12
*/
sendData(top); //top page (page 1)
sendData(btm); // page below top (page 2)
sendData(top); // top page, but next column
sendData(btm); // bottom page, but next column
// this means 1 byte for 2 columns in 2 pages (16 bits)
}
stopBit();
command(0x20); // horizontal mode
command(0x00);
}
void clrScreen() //fill screen with 0
{
unsigned char y, i;
for ( y = 0; y < 8; y++ ) {
command(0x21); //col addr
command(0); //col start
command(127); //col end
command(0x22); //0x22
command(y); // Page start
command(y+1); // Page end
startBit();
sendData(addr); // address
sendData(0x40);
for (i = 0; i < 128; i++){
sendData(0x00);
}
stopBit();
}
}
//Software I2C
void sendData(unsigned char dataB)
{
for(unsigned char b=0;b<8;b++){
SDA=(dataB >> (7-b)) % 2;
clock();
}
TRISIO5=1; //SDA input
clock();
__delay_us(5);
TRISIO5=0; //SDA output
}
void clock(void)
{
__delay_us(1);
SCL=1;
__delay_us(5);
SCL=0;
__delay_us(1);
}
void startBit(void)
{
SDA=0;
__delay_us(5);
SCL=0;
}
void stopBit(void)
{
SCL=1;
__delay_us(5);
SDA=1;
}
void command( unsigned char comm){
startBit();
sendData(addr); // address
sendData(0x00);
sendData(comm); // command code
stopBit();
}
void oled_init() {
command(0xAE); // DISPLAYOFF
command(0x8D); // CHARGEPUMP *
command(0x14); //0x14-pump on
command(0x20); // MEMORYMODE
command(0x0); //0x0=horizontal, 0x01=vertical, 0x02=page
command(0xA1); //SEGREMAP * A0/A1=top/bottom
command(0xC8); //COMSCANDEC * C0/C8=left/right
command(0xDA); // SETCOMPINS *
command(0x22); //0x22=4rows, 0x12=8rows
command(0x81); // SETCONTRAST
command(0xFF); //0x8F
//next settings are set by default
// command(0xD5); //SETDISPLAYCLOCKDIV
// command(0x80);
// command(0xA8); // SETMULTIPLEX
// command(0x3F); //0x1F
// command(0xD3); // SETDISPLAYOFFSET
// command(0x0);
// command(0x40); // SETSTARTLINE
// command(0xD9); // SETPRECHARGE
// command(0xF1);
// command(0xDB); // SETVCOMDETECT
// command(0x40);
// command(0xA4); // DISPLAYALLON_RESUME
// command(0xA6); // NORMALDISPLAY
command(0xAF); //DISPLAYON
}
// ----oled_font.c-----------------------
static const unsigned char font[] = {
0x7E,0xC1,0x81,0x83,0x7E,
0x82,0x83,0xFF,0x80,0x80,
0xC2,0xA1,0x91,0x89,0x46,
0x42,0x81,0x99,0x99,0x7E,
0x18,0x14,0x92,0xFF,0x90,
0xC7,0x89,0x89,0x99,0x70,
0xEE,0x91,0x91,0x91,0x70,
0x01,0xC1,0x31,0x19,0x06,
0x66,0x99,0x99,0x99,0x66,
0x0E,0x91,0x91,0x91,0x7E,
0x0C,0x30,0xC0,0x30,0x0C,
0x00, 0x00, 0x00, 0x00, 0x00,// (space)
0x00,0xC0,0xC0,0xC0,0x00
};