CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Help with SPI code for display

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jeetdesai



Joined: 05 Jul 2018
Posts: 18

View user's profile Send private message

Help with SPI code for display
PostPosted: Mon Jul 23, 2018 3:41 pm     Reply with quote

I am trying to interface the PIC18F87K22 with an OLED display using the SPI protocol. But I havn't been able to light any pixel on the display. The following is the link of the display that I'm using and its demo code: https://www.crystalfontz.com/product/cfal12864g024w-128x64-2-4inch-white-oled-module

The display came with a sample code for Arduino and the display is lighting successfully with Arduino but fails with the PIC18. The output waveform of the PIC18 is different from the output waveform of the Arduino. The Arduino waveforms at the output is very unclear and triangular, while the PIC18 is giving relatively clear square waves. So i'm not sure if the SPI data that is sent from PIC18 is correct or not.

The 'Fill_Framebuffer(0xFF, 0xFF);' is responsible for lighting all pixels on the display.



The following is my code:

Code:
/////////////////////////////////////////////////////////////////////////  Main File  ////////////////////////////////////////////////////////////////////////////////////////////////

#include <18F87K22.h>
#use delay(clock = 1000000)   
#include "OLED_low.h"
#include "OLED_low.c"
#include "OLED_draw.h"
#include "OLED_draw.c"
#FUSES INTRC_IO                  //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                 //No code protected from reads
#FUSES MCLR                      //Master Clear pin enabled
#FUSES NOCPD                     //No EE protection
#FUSES NOBROWNOUT                //No brownout reset
#FUSES NOIESO                    //Internal External Switch Over mode disabled
#FUSES NOFCMEN                   //Fail-safe clock monitor disabled   
#FUSES NOWDT           
#include <string.h>
#define OLED 0x78
#INCLUDE <stdlib.h>

void setup(void)
   {
   output_low(RES);
   output_low(RS);
   output_high(CS);
   
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_64);
   Initialize_CFAL12864G(255);
   }
//==============
void main(void)
{
 
   setup();
 
   while(1)
   {   
    Fill_Framebuffer(0xFF, 0xFF); //light all pixels
    Send_Framebuffer_To_Display(); //sends data, address for bit0, send address for bit 1
    delay_ms(50); 
   }
   delay_ms(500);
}

//==============

/////////////////////////////////////////////////////////////////////////  OLED_low.c  ////////////////////////////////////////////////////////////////////////////////////////////////
#include "OLED_low.h"
#include "OLED_draw.h"

#define SSD1309_00_SET_LOWER_COLUMN_ADDRESS_BIT       (0x00)
#define SSD1309_10_SET_UPPER_COLUMN_ADDRESS_BIT       (0x10)
#define SSD1309_20_MEMORY_ADDRESSING_MODE_PREFIX      (0x20)
#define SSD1309_00_ADRESSING_HORIZONTAL_PARAMETER     (0x00)
#define SSD1309_01_ADRESSING_VERTICAL_PARAMETER       (0x01)
#define SSD1309_02_ADRESSING_PAGE_PARAMETER           (0x02)
#define SSD1309_21_SET_COLUMN_ADDRESS_PREFIX          (0x21)
#define SSD1309_22_SET_PAGE_ADDRESS_PREFIX            (0x22)
#define SSD1309_26_SCROLL_SET_CONT_HORIZ_RIGHT_PREFIX (0x26)
#define SSD1309_27_SCROLL_SET_CONT_HORIZ_LEFT_PREFIX  (0x27)
#define SSD1309_29_SCROLL_SET_VERT_HORIZ_RIGHT_PREFIX (0x29)
#define SSD1309_2A_SCROLL_SET_VERT_HORIZ_LEFT_PREFIX  (0x2A)
#define SSD1309_2C_SCROLL_SET_ONE_HORIZ_RIGHT_PREFIX  (0x2C)
#define SSD1309_2D_SCROLL_SET_ONE_HORIZ_LEFT_PREFIX   (0x2D)
#define SSD1309_2E_SCROLL_DEACTIVATE                  (0x2E)
#define SSD1309_2F_SCROLL_ACTIVATE                    (0x2F)
#define SSD1309_40_SET_DISPLAY_START_LINE_BIT         (0x40)
#define SSD1309_81_CONTRAST_PREFIX                    (0x81)
#define SSD1309_A0_SEGMENT_REMAP_NORMAL               (0xA0)
#define SSD1309_A1_SEGMENT_REMAP_REVERSE              (0xA1)
#define SSD1309_A3_SCROLL_VERT_AREA_PREFIX            (0xA3)
#define SSD1309_A4_ENTIRE_DISPLAY_NORMAL              (0xA4)
#define SSD1309_A5_ENTIRE_DISPLAY_FORCE_ON            (0xA5)
#define SSD1309_A6_INVERSION_NORMAL                   (0xA6)
#define SSD1309_A7_INVERSION_INVERTED                 (0xA7)
#define SSD1309_A8_MULTIPLEX_RATIO_PREFIX             (0xA8)
#define SSD1309_AE_DISPLAY_OFF_SLEEP_YES              (0xAE)
#define SSD1309_AF_DISPLAY_ON_SLEEP_NO                (0xAF)
#define SSD1309_B0_SET_PAGE_START_ADDRESS_BIT         (0xB0)
#define SSD1309_C0_COM_DIRECTION_NORMAL               (0xC0)
#define SSD1309_C8_COM_DIRECTION_REVERSE              (0xC8)
#define SSD1309_D3_DISPLAY_VERT_OFFSET_PREFIX         (0xD3)
#define SSD1309_D5_CLOCK_DIVIDE_PREFIX                (0xD5)
#define SSD1309_D9_PRECHARGE_PERIOD_PREFIX            (0xD9)
#define SSD1309_DA_COM_PINS_CONFIGURATION_PREFIX      (0xDA)
#define SSD1309_DB_VCOMH_DESELECT_PREFIX              (0xDB)
#define SSD1309_DC_GPIO_CONFIGURATION_PREFIX          (0xDC)
#define SSD1309_E3_NOP                                (0xE3)
#define SSD1309_FD_LOCK_UNLOCK_PREFIX                 (0xFD)
#define SSD1309_16_LOCK_PARAMETER                     (0x16)
#define SSD1309_12_UNLOCK_PARAMETER                   (0x12)

//===========================================================================
void SPI_sendCommand(unsigned int8 command)
  {
   output_low(RS); //DC // RS   
   output_low(CS);
   spi_write(command); //Char
   output_high(CS);   
  // delay_us(1000);
  }
//============================================================================
void SPI_sendData(unsigned int8 data)
  {
   output_high(RS); //DC
   output_low(CS);   
   spi_write(data); //Char
   output_high(CS);   
   //delay_us(1000);
  }
//============================================================================
void Set_Address(unsigned int8 column, unsigned int8 page)
  {
  //Set column-lower nibble
  SPI_sendCommand(SSD1309_00_SET_LOWER_COLUMN_ADDRESS_BIT|(column&0x0F));
 
  //Set column-upper nibble
  SPI_sendCommand(SSD1309_10_SET_UPPER_COLUMN_ADDRESS_BIT|((column>>4)&0x0F));
  //Set page address, limiting from 0 to 7
  SPI_sendCommand(SSD1309_B0_SET_PAGE_START_ADDRESS_BIT|(page&0x07));
  }
//============================================================================
void Set_Brightness(unsigned int8 brightness)
  {
  //Set the "contrast" (brightness, max determined by IREF current)
  SPI_sendCommand(SSD1309_81_CONTRAST_PREFIX);
  SPI_sendCommand(brightness);
  }
//============================================================================
void Initialize_CFAL12864G(unsigned int8 brightness)
  {
  //Thump the hardware reset line.
  delay_ms(1);
  // CLR_RESET;
  output_low(RES);
  delay_ms(100);
  //SET_RESET;
  output_high(RES);
  delay_ms(100);

  //Start with the display off (sleeping)
  SPI_sendCommand(SSD1309_AE_DISPLAY_OFF_SLEEP_YES);

  //Set the memory addressing mode to PAGE (increment column, no wrap)
  SPI_sendCommand(SSD1309_20_MEMORY_ADDRESSING_MODE_PREFIX);
  SPI_sendCommand(SSD1309_02_ADRESSING_PAGE_PARAMETER);

  //Point to the upper-left
  Set_Address(0,0);

  //Set the "contrast" (brightness, max determined by IREF current)
  SPI_sendCommand(SSD1309_81_CONTRAST_PREFIX);
  SPI_sendCommand(brightness);

  //Set start line to 0
  SPI_sendCommand(SSD1309_40_SET_DISPLAY_START_LINE_BIT);//Set Display Start Line

  //Set Segment remap for the CFAL12864G, we want the lower-left to be 0,0
  SPI_sendCommand(SSD1309_A1_SEGMENT_REMAP_REVERSE);

  //Ensure tha the "entire display force on", test mide is disabled. Read
  //the data from the RAM and display it as normal.
  SPI_sendCommand(SSD1309_A4_ENTIRE_DISPLAY_NORMAL);

  //Make sure that inversion is disabled.
  SPI_sendCommand(SSD1309_A6_INVERSION_NORMAL);

  //Set the multiplex ratio. 64 lines so 1/64
  SPI_sendCommand(SSD1309_A8_MULTIPLEX_RATIO_PREFIX);
  SPI_sendCommand(63);

  //Set COM directiom CFAL12864G, we want the lower-left to be 0,0
  SPI_sendCommand(SSD1309_C0_COM_DIRECTION_NORMAL);

  //No display vertical offset
  SPI_sendCommand(SSD1309_D3_DISPLAY_VERT_OFFSET_PREFIX);
  SPI_sendCommand(0);

  //Set clock frequency and division ratio
  SPI_sendCommand(SSD1309_D5_CLOCK_DIVIDE_PREFIX);
  //Fastest clock, smallest divisor.
  SPI_sendCommand(0xF0);
  // FFFF DDDD
  // |||| ||||-- DDDD = division, 0=>1, 1=>2 etc
  // ||||------- FFFF = frequency, 0 = slow 15 = fast

  //Set Pre-charge Period
  SPI_sendCommand(SSD1309_D9_PRECHARGE_PERIOD_PREFIX);
  SPI_sendCommand(0xF1);
  // 2222 1111
  // |||| ||||-- Phase 1 DCLK periods
  // ||||------- Phase 2 DCLK periods

  //Set COM Pins Hardware Configuration
  SPI_sendCommand(SSD1309_DA_COM_PINS_CONFIGURATION_PREFIX);
  // Alternate, Disable remap
  SPI_sendCommand(0x12);

  //Set Vcomh Deselect Level
  SPI_sendCommand(SSD1309_DB_VCOMH_DESELECT_PREFIX);
//// not in 1309 datasheet says it should be one of 00, 34 or 3C
  SPI_sendCommand(0x40);

  //Make sure the scroll is deactivated.
  SPI_sendCommand(SSD1309_2E_SCROLL_DEACTIVATE);

  //Turn the display on (wake)
  SPI_sendCommand(SSD1309_AF_DISPLAY_ON_SLEEP_NO);
  }
 
/////////////////////////////////////////////////////////////////////////  OLED_low.h  ////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __OLEDLOW_H__
#define __OLEDLOW_H__

#define RES Pin_H1 // PIC18 pin at PortH.1 defined as RESET
#define CS Pin_H0  //SPI Enable
#define RS Pin_H2 // DC


//============================================================================
void SPI_sendCommand(unsigned int8 command);
void SPI_sendData(unsigned int8 data);
void Set_Address(unsigned int8 column, unsigned int8 page);
void Set_Brightness(unsigned int8 brightness);
void Initialize_CFAL12864G(unsigned int8 brightness);
//============================================================================
#endif //  __OLEDLOW_H__


/////////////////////////////////////////////////////////////////////////  OLED_draw.c  ////////////////////////////////////////////////////////////////////////////////////////////////
//============================================================================
// CFAL12864G 128x64 OLED in SPI mode
// OLEDdraw.cpp : Higher-level OLED drawing routines
// 2017 - 06 - 09 Brent A. Crosby
// Crystalfontz America, Inc. http://www.crystalfontz.com
//============================================================================


//#include "fnt08x08.h"
#include "OLED_low.h"
#include "OLED_draw.h"


#define Fast_Horizontal_Line OLED_Line
//============================================================================
// There is limited memory on the Arduino, so we can have the SD card or
// we could have a RAM display buffer, but not both.
unsigned int8 framebuffer[8][128]; // 8 = pages, 128 = pixels
//============================================================================
void Fill_Framebuffer(unsigned int8 data1, unsigned int8 data2)
  {
  unsigned int16 count;
  unsigned int8  *target;
  target=&framebuffer[0][0];
  for(count=0;count<512;count++) // 8 pages
    {
    *target=data1;
    target++;
    *target=data2;
    target++;
    }             
  }
//============================================================================
void Send_Framebuffer_To_Display(void)
  {
#if 0
  //simple 2.57mS flash 2952 ram 1211
  unsigned int8 page;
  unsigned int8 column;
  for(page=0;page<8;page++)
    {
    //Set the LCD to the left of this line.
    Set_Address(0,page);
    //Move across the columns, sending the data.
    for(column=0;column<128;column++)
      {
      SPI_sendData(framebuffer[page][column]);
      }
    }
#endif

#if 0
  //Optimized pointer 2.32mS flash 2588 ram 1211
  unsigned int8 page;
  unsigned int8 column;
  unsigned int8 *source;
  source=&framebuffer[0][0];       
  for(page=0;page<8;page++)
    {
    //Set the LCD to the left of this line.
    Set_Address(0,page);
    //Move across the columns, alternating the two data
    //bytes.
    for(column=0;column<128;column++)
      {
      SPI_sendData(*source);
      source++;
      }
    }
#endif

#if 1
  //Optimized pointer, plus unwrap SPI 1.94mS flash 2588 ram 1211
  unsigned int8 page;
  unsigned int8 column;
  unsigned int8 *source;
  source=&framebuffer[0][0];       
  for(page=0;page<8;page++)
    {
    //Set the LCD to the left of this line.
    Set_Address(0,page);
    //Move across the columns, alternating the two data
    //bytes.
    // Select the LCD's data register
    //SET_RS;
    output_high(RS); //DC
   
    // Select the LCD controller
    //CLR_CS;
    output_Low(CS);
    for(column=0;column<128;column++)
      {
      //Send the data via SPI:
      //SPI.transfer(*source);
      spi_write(*source);
      source++;
      }
    // Deselect the LCD controller
    //SET_CS;
    output_high(CS);
   
    }
#endif
  }
//============================================================================

//============================================================================


/////////////////////////////////////////////////////////////////////////  OLED_draw.h  ////////////////////////////////////////////////////////////////////////////////////////////////

    #ifndef __OLEDDRAW_H__
#define __OLEDDRAW_H__
//============================================================================
extern unsigned int8 framebuffer[8][128];
//----------------------------------------------------------------------------
void Fill_Framebuffer(unsigned int8 data1, unsigned int8 data2);
void Send_Framebuffer_To_Display(void);
void horizontal_line(unsigned int8 x1, unsigned int8 y, unsigned int8 x2);

//============================================================================
#endif //  __OLEDDRAW_H__



Most of the commands for graphics have been removed from the sample code and simply the important commands for lighting the entire display is kept as it is. I have tested the above code in Arduino and it works successfully. All I want to do is light all pixels on the display.


Am I initializing the SPI commands properly?
Have I written the 'Setup' and 'Main' functions correctly?



Thank You in advance.
Jeetdesai



Joined: 05 Jul 2018
Posts: 18

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 4:03 pm     Reply with quote

The following is the code for arduino:

Code:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Main File ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <SPI.h>
#include "OLED_low.h"
#include "OLEDdraw.h"
//----------------------------------------------------------------------------
void demo(void)
  {
    //Fill_Framebuffer(0x00, 0x00); no pixels light (data1: 4bit upper nibble 4bit  lower nibble, data2: upper nib lower nib)
    //Fill_Framebuffer(0xFF, 0xFF); all pixels light
    Fill_Framebuffer(0x64, 0xC0); // alternate columns light


    Send_Framebuffer_To_Display(); // sends data, address for bit0, send address for bit 1
    delay(50);
   
  }
//============================================================================
void setup( void )
  {

  DDRB |= 0x2F; // output

  //Drive the ports to a reasonable starting state.
  CLR_RESET; // logic low
  CLR_RS;     // logic high
  SET_CS;
  CLR_MOSI;
  CLR_SCK;


  pinMode(PIN_TIME, OUTPUT);

  //debug console
  Serial.begin(115200);
  //Serial.println(F("setup()"));

  // Initialize SPI. By default the clock is 4MHz.
  SPI.begin();
  //Bump the clock to 8MHz. Appears to be the maximum.
  SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

  //Fire up the SPI OLED
  //Serial.println(F("Initialize_CFAL12864G()"));
  Initialize_CFAL12864G(255);
  }
//============================================================================
void loop(void)
  {
  demo();
  delay(500);

  }
//============================================================================



////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OLED_low.cpp ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//============================================================================
#include <Arduino.h>
#include <SPI.h>
#include "OLED_low.h"

//===========================================================================
//  The controller is a SSD1309.
//  https://www.crystalfontz.com/controllers/Solomon%20Systech/SSD1309
#define SSD1309_00_SET_LOWER_COLUMN_ADDRESS_BIT       (0x00)
#define SSD1309_10_SET_UPPER_COLUMN_ADDRESS_BIT       (0x10)
#define SSD1309_20_MEMORY_ADDRESSING_MODE_PREFIX      (0x20)
#define SSD1309_00_ADRESSING_HORIZONTAL_PARAMETER     (0x00)
#define SSD1309_01_ADRESSING_VERTICAL_PARAMETER       (0x01)
#define SSD1309_02_ADRESSING_PAGE_PARAMETER           (0x02)
#define SSD1309_21_SET_COLUMN_ADDRESS_PREFIX          (0x21)
#define SSD1309_22_SET_PAGE_ADDRESS_PREFIX            (0x22)
#define SSD1309_26_SCROLL_SET_CONT_HORIZ_RIGHT_PREFIX (0x26)
#define SSD1309_27_SCROLL_SET_CONT_HORIZ_LEFT_PREFIX  (0x27)
#define SSD1309_29_SCROLL_SET_VERT_HORIZ_RIGHT_PREFIX (0x29)
#define SSD1309_2A_SCROLL_SET_VERT_HORIZ_LEFT_PREFIX  (0x2A)
#define SSD1309_2C_SCROLL_SET_ONE_HORIZ_RIGHT_PREFIX  (0x2C)
#define SSD1309_2D_SCROLL_SET_ONE_HORIZ_LEFT_PREFIX   (0x2D)
#define SSD1309_2E_SCROLL_DEACTIVATE                  (0x2E)
#define SSD1309_2F_SCROLL_ACTIVATE                    (0x2F)
#define SSD1309_40_SET_DISPLAY_START_LINE_BIT         (0x40)
#define SSD1309_81_CONTRAST_PREFIX                    (0x81)
#define SSD1309_A0_SEGMENT_REMAP_NORMAL               (0xA0)
#define SSD1309_A1_SEGMENT_REMAP_REVERSE              (0xA1)
#define SSD1309_A3_SCROLL_VERT_AREA_PREFIX            (0xA3)
#define SSD1309_A4_ENTIRE_DISPLAY_NORMAL              (0xA4)
#define SSD1309_A5_ENTIRE_DISPLAY_FORCE_ON            (0xA5)
#define SSD1309_A6_INVERSION_NORMAL                   (0xA6)
#define SSD1309_A7_INVERSION_INVERTED                 (0xA7)
#define SSD1309_A8_MULTIPLEX_RATIO_PREFIX             (0xA8)
#define SSD1309_AE_DISPLAY_OFF_SLEEP_YES              (0xAE)
#define SSD1309_AF_DISPLAY_ON_SLEEP_NO                (0xAF)
#define SSD1309_B0_SET_PAGE_START_ADDRESS_BIT         (0xB0)
#define SSD1309_C0_COM_DIRECTION_NORMAL               (0xC0)
#define SSD1309_C8_COM_DIRECTION_REVERSE              (0xC8)
#define SSD1309_D3_DISPLAY_VERT_OFFSET_PREFIX         (0xD3)
#define SSD1309_D5_CLOCK_DIVIDE_PREFIX                (0xD5)
#define SSD1309_D9_PRECHARGE_PERIOD_PREFIX            (0xD9)
#define SSD1309_DA_COM_PINS_CONFIGURATION_PREFIX      (0xDA)
#define SSD1309_DB_VCOMH_DESELECT_PREFIX              (0xDB)
#define SSD1309_DC_GPIO_CONFIGURATION_PREFIX          (0xDC)
#define SSD1309_E3_NOP                                (0xE3)
#define SSD1309_FD_LOCK_UNLOCK_PREFIX                 (0xFD)
#define SSD1309_16_LOCK_PARAMETER                     (0x16)
#define SSD1309_12_UNLOCK_PARAMETER                   (0x12)
//===========================================================================
void SPI_sendCommand(uint8_t command)
  {
  // Select the LCD's command register
  CLR_RS;
  // Select the LCD controller
  CLR_CS;
  //Send the command via SPI:
  SPI.transfer(command);
  // Deselect the LCD controller
  SET_CS;
  }
//============================================================================
void SPI_sendData(uint8_t data)
  {
  // Select the LCD's data register
  SET_RS;
  // Select the LCD controller
  CLR_CS;
  //Send the data via SPI:
  SPI.transfer(data);
  // Deselect the LCD controller
  SET_CS;
  }
//============================================================================
void Set_Address(uint8_t column, uint8_t page)
  {
  //Set column-lower nibble
  SPI_sendCommand(SSD1309_00_SET_LOWER_COLUMN_ADDRESS_BIT|(column&0x0F));
  //Set column-upper nibble
  SPI_sendCommand(SSD1309_10_SET_UPPER_COLUMN_ADDRESS_BIT|((column>>4)&0x0F));
  //Set page address, limiting from 0 to 7
  SPI_sendCommand(SSD1309_B0_SET_PAGE_START_ADDRESS_BIT|(page&0x07));
  }
//============================================================================
void Set_Brightness(uint8_t brightness)
  {
  //Set the "contrast" (brightness, max determined by IREF current)
  SPI_sendCommand(SSD1309_81_CONTRAST_PREFIX);
  SPI_sendCommand(brightness);
  }
//============================================================================
void Initialize_CFAL12864G(uint8_t brightness)
  {
  //Thump the hardware reset line.
  _delay_ms(1);
  CLR_RESET;
  _delay_ms(1);
  SET_RESET;
  _delay_ms(1);

  //Start with the display off (sleeping)
  SPI_sendCommand(SSD1309_AE_DISPLAY_OFF_SLEEP_YES);

  //Set the memory addressing mode to PAGE (increment column, no wrap)
  SPI_sendCommand(SSD1309_20_MEMORY_ADDRESSING_MODE_PREFIX);
  SPI_sendCommand(SSD1309_02_ADRESSING_PAGE_PARAMETER);

  //Point to the upper-left
  Set_Address(0,0);

  //Set the "contrast" (brightness, max determined by IREF current)
  SPI_sendCommand(SSD1309_81_CONTRAST_PREFIX);
  SPI_sendCommand(brightness);

  //Set start line to 0
  SPI_sendCommand(SSD1309_40_SET_DISPLAY_START_LINE_BIT);//Set Display Start Line

  //Set Segment remap for the CFAL12864G, we want the lower-left to be 0,0
  SPI_sendCommand(SSD1309_A1_SEGMENT_REMAP_REVERSE);

  //Ensure tha the "entire display force on", test mide is disabled. Read
  //the data from the RAM and display it as normal.
  SPI_sendCommand(SSD1309_A4_ENTIRE_DISPLAY_NORMAL);

  //Make sure that inversion is disabled.
  SPI_sendCommand(SSD1309_A6_INVERSION_NORMAL);

  //Set the multiplex ratio. 64 lines so 1/64
  SPI_sendCommand(SSD1309_A8_MULTIPLEX_RATIO_PREFIX);
  SPI_sendCommand(63);

  //Set COM directiom CFAL12864G, we want the lower-left to be 0,0
  SPI_sendCommand(SSD1309_C0_COM_DIRECTION_NORMAL);

  //No display vertical offset
  SPI_sendCommand(SSD1309_D3_DISPLAY_VERT_OFFSET_PREFIX);
  SPI_sendCommand(0);

  //Set clock frequency and division ratio
  SPI_sendCommand(SSD1309_D5_CLOCK_DIVIDE_PREFIX);
  //Fastest clock, smallest divisor.
  SPI_sendCommand(0xF0);
  // FFFF DDDD
  // |||| ||||-- DDDD = division, 0=>1, 1=>2 etc
  // ||||------- FFFF = frequency, 0 = slow 15 = fast

  //Set Pre-charge Period
  SPI_sendCommand(SSD1309_D9_PRECHARGE_PERIOD_PREFIX);
  SPI_sendCommand(0xF1);
  // 2222 1111
  // |||| ||||-- Phase 1 DCLK periods
  // ||||------- Phase 2 DCLK periods

  //Set COM Pins Hardware Configuration
  SPI_sendCommand(SSD1309_DA_COM_PINS_CONFIGURATION_PREFIX);
  // Alternate, Disable remap
  SPI_sendCommand(0x12);

  //Set Vcomh Deselect Level
  SPI_sendCommand(SSD1309_DB_VCOMH_DESELECT_PREFIX);
//// not in 1309 datasheet says it should be one of 00, 34 or 3C
  SPI_sendCommand(0x40);

  //Make sure the scroll is deactivated.
  SPI_sendCommand(SSD1309_2E_SCROLL_DEACTIVATE);

  //Turn the display on (wake)
  SPI_sendCommand(SSD1309_AF_DISPLAY_ON_SLEEP_NO);
  }
//============================================================================



////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OLED_low.h///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __OLEDLOW_H__
#define __OLEDLOW_H__


#define CLR_RS    (PORTB &= ~(0x01))
#define SET_RS    (PORTB |=  (0x01))
#define CLR_RESET (PORTB &= ~(0x02))
#define SET_RESET (PORTB |=  (0x02))
#define CLR_CS    (PORTB &= ~(0x04))
#define SET_CS    (PORTB |=  (0x04))
#define CLR_MOSI  (PORTB &= ~(0x08))
#define SET_MOSI  (PORTB |=  (0x08))
#define CLR_SCK   (PORTB &= ~(0x20))
#define SET_SCK   (PORTB |=  (0x20))

//PD.7
#define PIN_TIME   (7) // digital 7
#define CLR_TIME   (PORTD &= ~(0x80))
#define SET_TIME   (PORTD |=  (0x80))
//============================================================================
void SPI_sendCommand(uint8_t command);
void SPI_sendData(uint8_t data);
void Set_Address(uint8_t column, uint8_t page);
void Set_Brightness(uint8_t brightness);
void Initialize_CFAL12864G(uint8_t brightness);
//============================================================================
#endif //  __OLEDLOW_H__



////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OLEDdraw.cpp //////////////////////////////////////////////////////////////////////////////////////////////////////////////
//============================================================================
// CFAL12864G 128x64 OLED in SPI mode
// OLEDdraw.cpp : Higher-level OLED drawing routines
// 2017 - 06 - 09 Brent A. Crosby
// Crystalfontz America, Inc. http://www.crystalfontz.com
//============================================================================
#include <Arduino.h>
#include <SPI.h>
//#include "fnt08x08.h"
#include "OLED_low.h"
#include "OLEDdraw.h"

#define Fast_Horizontal_Line OLED_Line
//============================================================================
// There is limited memory on the Arduino, so we can have the SD card or
// we could have a RAM display buffer, but not both.
uint8_t framebuffer[8][128];
//============================================================================
void Fill_Framebuffer(uint8_t data1, uint8_t data2)
  {
  uint16_t count;
  uint8_t *target;
  target=&framebuffer[0][0];
  for(count=0;count<512;count++)
    {
    *target=data1;
    target++;
    *target=data2;
    target++;
    }             
  }
//============================================================================
void Send_Framebuffer_To_Display(void)
  {
#if 0
  //simple 2.57mS flash 2952 ram 1211
  uint8_t page;
  uint8_t column;
  for(page=0;page<8;page++)
    {
    //Set the LCD to the left of this line.
    Set_Address(0,page);
    //Move across the columns, sending the data.
    for(column=0;column<128;column++)
      {
      SPI_sendData(framebuffer[page][column]); //sends data
      }
    }
#endif

#if 0
  //Optimized pointer 2.32mS flash 2588 ram 1211
  uint8_t page;
  uint8_t column;
  uint8_t *source;
  source=&framebuffer[0][0];       
  for(page=0;page<8;page++)
    {
    //Set the LCD to the left of this line.
    Set_Address(0,page);
    //Move across the columns, alternating the two data
    //bytes.
    for(column=0;column<128;column++)
      {
      SPI_sendData(*source);                      // sends address?
      source++;
      }
    }
#endif

#if 1
  //Optimized pointer, plus unwrap SPI 1.94mS flash 2588 ram 1211
  uint8_t page;
  uint8_t column;
  uint8_t *source;
  source=&framebuffer[0][0];       
  for(page=0;page<8;page++)
    {
    //Set the LCD to the left of this line.
    Set_Address(0,page); // (column, page)
    //Move across the columns, alternating the two data
    //bytes.
    // Select the LCD's data register
    SET_RS;
    // Select the LCD controller
    CLR_CS;
    for(column=0;column<128;column++)
      {
      //Send the data via SPI:
      SPI.transfer(*source);
      source++;
      }
    // Deselect the LCD controller
    SET_CS;
    }
#endif
  }



////////////////////////////////////////////////////////////////////////////////////////////////////////////////// OLEDdraw.h //////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __OLEDDRAW_H__
#define __OLEDDRAW_H__
//============================================================================
extern uint8_t framebuffer[8][128];
//----------------------------------------------------------------------------
void Fill_Framebuffer(uint8_t data1, uint8_t data2);
void Send_Framebuffer_To_Display(void);
void Put_Pixel(uint8_t x, uint8_t y, uint8_t set);
void OLED_Line(uint8_t x0, uint8_t y0,
               uint8_t x1, uint8_t y1,
               uint8_t set);
void horizontal_line(uint8_t x1, uint8_t y, uint8_t x2);
void put_string(uint8_t x, uint8_t y, uint8_t Field_Width, const char *input);
void invert_string(uint8_t x, uint8_t y, uint8_t Field_Width);

//============================================================================
#endif //  __OLEDDRAW_H__

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 4:16 pm     Reply with quote

Here you are using SPI Mode 1:
Quote:
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_64);

Mode 1 is not the correct mode.
The CrystalFontz demo code says it uses Mode 0:
Quote:
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));


The CrystalFontz demo program says this:
Code:
//  !! IMPORTANT !!
//
//  The CFAL12864G is a 3.3v device. You need a 3.3v Arduino to operate this
//  code properly. We used a seeedunio v4.2 set to 3.3v:
//  http://www.seeedstudio.com/item_detail.html?p_id=2517
//
//  You need to supply +13v to pin 30 (Vcc) for the OLED drive.
//
//  IREF should be set to 10uA. Place a 1M Ohm resistor from pin 28 (IREF)
//  to ground (VSS).

Are you doing all of this ? Are you running your PIC at 3.3 volts ?


Here, I want to show you something that you are doing that is bad.
This is from a previous thread:
Quote:
/*#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H) */

//========================================
void main()
{
setup_spi(SPI_MASTER | SPI_H_TO_L| SPI_CLK_DIV_64);

You have commented out the #define statements, and then stuck a piece
of the #define into your code. This is very, very, very bad form.

You should un-comment the #define statements, and then do it like this:
Quote:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64);

Now your code is self-documenting. You don't have to wonder what mode
you are using. You just look at it, and say "Oh, I'm using mode 0".
That's the correct way.
Jeetdesai



Joined: 05 Jul 2018
Posts: 18

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 4:31 pm     Reply with quote

Thank You PCM p, for the quick response.

Quote:
Are you doing all of this ? Are you running your PIC at 3.3 volts ?


Yes, I am using a Voltage Translator to convert the 5v signals to 3.3v. So the PIC runs on 5v and the 5v signals are give to the input of the translator, while I use the Vddcore of the PIC18 for the 3.3v reference and give the 3.3v to the display. I cross checked the waveforms on the oscilloscope before connecting the display.


Thank You again for the pointers for corrections.
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 6:50 pm     Reply with quote

comments.

I downloaded the datasheet and that PIC will run fine at 3 volts, so you would not need the 'voltage translators'.
It appears you're only running at 1 MHz clock speed, seems a shame to be going that slow.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Jul 24, 2018 1:40 am     Reply with quote

As a comment, though it is significant work, it is much easier to adapt the existing oled driver to use SPI, than to start again:
Code:

//In the setup
#use SPI (SPI1, MASTER, BAUD=400000, MODE=0)
//Mode 0 on SPI1
#define CS_PIN PIN_xx //whatever pin you are using for the CS
#define DC_PIN PIN_xx //whatever pin you are using for D/C

//Then replace these functions in the oled driver
void OLED_commands(rom unsigned int8 * commands, unsigned int8 number)
//send a multiple command, or commands to the display - number says how many
//from a ROM buffer
{
   int8 ctr; //counter for the transmission
   int8 dummy;
   output_low(CS_PIN); //select the display
   output_low(DC_PIN);   
   for (ctr=0;ctr<number;ctr++)
   {   
      dummy=spi_xfer(commands[ctr], 8);
   }
   output_high(CS_PIN);
}

void OLED_data(unsigned int8 * data, unsigned int8 number)
//send 'number' bytes of data to display - from RAM
{
   int8 ctr;
   int8 dummy;
   output_low(CS_PIN); //select display
   output_high(DC_PIN);
   for (ctr=0;ctr<number;ctr++)
      dummy=spi_xfer(data[ctr],8); //send the byte(s)
   output_high(CS_PIN);   
}

void OLED_address(unsigned int8 x, unsigned int8 y)
{
   int8 dummy;
   //routine to move the memory pointers to x,y.
   //x is 0 to 127 (column), y (row) is 0 to 7 (page only)
#ifdef SH1106
   x+=2;
#endif
   output_low(CS_PIN); //select display
   output_low(DC_PIN);
   dummy=spi_xfer(S_ROWADDRESS | y,8); //select the display row
   dummy=spi_xfer((S_SETLOWCOLUMN | (x & 0x0F),8); //low col address
   dummy=spi_xfer((S_SETHIGHCOLUMN | ((x>>4) & 0x0F),8); //high col address
   output_high(CS_PIN);
} //also made more efficient

void OLED_CLS(void)
{
   unsigned int8 row, col;
   int8 dummy;

   //Just fill the memory with zeros
   for (row=0;row<S_LCDHEIGHT/8;row++)
   {
      OLED_address(0,row); //take the addresses back to 0,0 0,1 etc..
      output_low(CS_PIN);
      output_high(DC_PIN);
      for (col=0;col<S_LCDWIDTH;col++)
      {
         if (set)
            dummy=spi_xfer (0,8); //send 1024 zeros
         else
            dummy=spi_xfer(255,8); //or the inverse
      }
      output_high(CS_PIN);
   }
   OLED_gotoxy(0,0); //and text back to the top corner   
}



Your code would need to ensure it sets the CS_PIN high at the start before calling the oled routines.

No guarantees, but provided you have the display correctly connected to SPI1, with the CS_PIN and DC_PINs connected and defined, these should be close.
If you don't want to connect DC, then you can wire this low and replace all the lines talking to this with software commands to select the registers.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group