pic16f690 code


/*
 * File:   main.c
 * Author: root
 * Random numbers based on self blinking LEDS and comparators
 * Created on 13 dec, 2023, 10:23 AM
 * oled i2c 
 */

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator:
// I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-Up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF   // MCLR pin is digital I/O, MCLR internally tied to
// VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code
// protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code
// protection is disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include <htc.h>
#include "oled_font.c"


#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 RA0  // clock
#define SDA RA1 // data

//prototypes
void command( unsigned char comm);
void oled_init(void);
void clrScreen(void);
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
unsigned char num, digit_2,digit_3;

void main(void) {
    ANSEL = 0x00;   //disable all analog ports
    ANSELH = 0x00;
    CM1CON0 = 0x07;  // comparator off    
    TRISA = 0x00; // all outputs 
    TRISC = 0xFF; // all inputs 
    PORTC = 0x00;  // all low
    //---------------------------------------------------- 
    PORTAbits.RA0 = 1;
    PORTAbits.RA1 = 1;
    
    __delay_ms(200);
    oled_init();
    __delay_ms(200);
    clrScreen();       // clear screen 
    
    
    while (1) {
          
        drawChar2(11, 1, 3);  //space
        drawChar2(11, 1, 4);
        drawChar2(11, 1, 5);
        
        num = PORTC;
        digit_2 = (num / 10) % 10;   // 207    10 11 12 99  100
        digit_3 = num % 10;
        if (num > 199) {  // 200-255
            drawChar2(2, 1, 3);
            drawChar2(digit_2, 1, 4); 
        } else if (num > 99) {   // 100 -199
            drawChar2(1, 1, 3);
            drawChar2(digit_2, 1, 4); 
        } else if (num > 9) {  // 10-99            
            drawChar2(digit_2, 1, 4); 
        }
        drawChar2(digit_3, 1, 5);
        __delay_ms(1800);   
        num = 0;
    }   //while
}

   //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();
    }
    TRISAbits.TRISA1 = 1;   //SDA input
    clock();
    __delay_us(5);
    TRISAbits.TRISA1 =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

}
-----------------------------------------------
File "oled_font.c"

static const unsigned char  font[] = {
0x7E,0xC1,0x81,0x83,0x7E, // zero
0x82,0x83,0xFF,0x80,0x80,  // one
0xC2,0xA1,0x91,0x89,0x86,  // two
0x42,0x81,0x89,0x89,0x7E,  // three
0x18,0x14,0x92,0xFF,0x90, // four
0xC7,0x89,0x89,0x99,0x70, // five
0xFE,0x91,0x91,0x91,0xF0, // six
0x01,0xE1,0x19,0x05,0x03,  // seven
0x76,0x99,0x99,0x99,0x76, // eight
0x1E,0x91,0x91,0x91,0xFE, // nine
0x0C,0x30,0xC0,0x30,0x0C, // v
0x00, 0x00, 0x00, 0x00, 0x00, // space
0x00,0xC0,0xC0,0xC0,0x00 // dot
};