shithub: leaf

ref: 21f5ac6f65245a6d5f1b63b0f1a38d4001f1d5dc
dir: /LEAF/Src/ssd1306.c/

View raw version
/*
 * ssd1306.c
 *
 *  Created on: Oct 8, 2019
 *      Author: jeffsnyder
 */


/*
 * ssd1306.c
 *
 *  Created on: Jul 6, 2018
 *      Author: jeffsnyder
 */

#include "main.h"
#include "ssd1306.h"

unsigned char buffer[512];

//unsigned char buffer [] = {
//
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x00, 0x00, 0xC0, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xC0, 0xC0,
//		0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0,
//		0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
//		0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
//		0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x00, 0x00, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0xFE, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
//		0xF0, 0xFE, 0x1F, 0x03, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0x0F, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00,
//		0x00, 0x01, 0x01, 0x03, 0x0F, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0x0F, 0x03, 0x01, 0x01,
//		0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0x0F, 0x03, 0x01, 0x01,
//		0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x0F, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x0F, 0xFE, 0xF0, 0x00, 0x00, 0x00,
//		0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0,
//		0xFE, 0x0F, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00,
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0xFC, 0xE0, 0xE0, 0xFC, 0x1F,
//		0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0x78, 0x60, 0xC0, 0xC0, 0x80, 0x80, 0x80,
//		0x80, 0xC0, 0xC0, 0x60, 0x78, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x07, 0x3F, 0x78, 0xE0, 0xC0, 0xC0,
//		0x80, 0x80, 0xC0, 0xC0, 0xE0, 0x70, 0x10, 0x00, 0x00, 0x00, 0x07, 0x3F, 0x78, 0x60, 0xC0, 0xC0,
//		0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0x60, 0x78, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
//		0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0x78, 0x3F, 0x07, 0x00, 0x00, 0x00,
//		0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07,
//		0x3F, 0x78, 0xE0, 0xC0, 0xC0, 0x80, 0x80, 0xC0, 0xC0, 0xE0, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00,
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00,
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
//		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
//		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
//		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
//		};



#define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; }
#define WIDTH SSD1306_LCDWIDTH
#define HEIGHT SSD1306_LCDHEIGHT

uint8_t displayBufferChunk[513] __ATTR_RAM_D3;

uint8_t OLED_xpos = 0;
uint8_t OLED_ypos = 0;



uint8_t OLED_i2c_address;
uint8_t OLED_externalVCC;
I2C_HandleTypeDef* OLED_i2c_handle;

void ssd1306_begin(I2C_HandleTypeDef* hi2c, uint8_t vccstate, uint8_t i2caddr)
{
	OLED_i2c_address = i2caddr;
	OLED_externalVCC = vccstate;
	OLED_i2c_handle = hi2c;

	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); //PULL RESET LINE HIGH
	// VDD (3.3V) goes high at start, lets just chill for a ms
	HAL_Delay(1);
	// bring reset low
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET); //PULL RESET LINE HIGH
	// wait 10ms
	HAL_Delay(10);
	// bring out of reset
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET); //PULL RESET LINE HIGH
	// turn on VCC (9V?)


	// Init sequence
	ssd1306_command(SSD1306_DISPLAYOFF);                    // 0xAE
	ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV);            // 0xD5
	ssd1306_command(0x80);                                  // the suggested ratio 0x80

	ssd1306_command(SSD1306_SETMULTIPLEX);                  // 0xA8
	ssd1306_command(SSD1306_LCDHEIGHT - 1);

	ssd1306_command(SSD1306_SETDISPLAYOFFSET);              // 0xD3
	ssd1306_command(0x0);                                   // no offset
	ssd1306_command(SSD1306_SETSTARTLINE | 0x0);            // line #0
	ssd1306_command(SSD1306_CHARGEPUMP);                    // 0x8D
	if (vccstate == SSD1306_EXTERNALVCC)
	{ ssd1306_command(0x10); }
	else
	{ ssd1306_command(0x14); }
	ssd1306_command(SSD1306_MEMORYMODE);                    // 0x20
	ssd1306_command(0x00);                                  // 0x0 act like ks0108
	ssd1306_command(SSD1306_SEGREMAP | 0x1);
	ssd1306_command(SSD1306_COMSCANDEC);

	#if defined SSD1306_128_32
	ssd1306_command(SSD1306_SETCOMPINS);                    // 0xDA
	ssd1306_command(0x02);
	ssd1306_command(SSD1306_SETCONTRAST);                   // 0x81
	ssd1306_command(0x8F);

	#elif defined SSD1306_128_64
	ssd1306_command(SSD1306_SETCOMPINS);                    // 0xDA
	ssd1306_command(0x12);
	ssd1306_command(SSD1306_SETCONTRAST);                   // 0x81
	if (vccstate == SSD1306_EXTERNALVCC)
	{ ssd1306_command(0x9F); }
	else
	{ ssd1306_command(0xCF); }

	#elif defined SSD1306_96_16
	ssd1306_command(SSD1306_SETCOMPINS);                    // 0xDA
	ssd1306_command(0x2);   //ada x12
	ssd1306_command(SSD1306_SETCONTRAST);                   // 0x81
	if (vccstate == SSD1306_EXTERNALVCC)
	{ ssd1306_command(0x10); }
	else
	{ ssd1306_command(0xAF); }

	#endif

	ssd1306_command(SSD1306_SETPRECHARGE);                  // 0xd9
	if (vccstate == SSD1306_EXTERNALVCC)
	{ ssd1306_command(0x22); }
	else
	{ ssd1306_command(0xF1); }
	ssd1306_command(SSD1306_SETVCOMDETECT);                 // 0xDB
	ssd1306_command(0x40);
	ssd1306_command(SSD1306_DISPLAYALLON_RESUME);           // 0xA4
	ssd1306_command(SSD1306_NORMALDISPLAY);                 // 0xA6

	ssd1306_command(SSD1306_DEACTIVATE_SCROLL);

	ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel
}


void sdd1306_invertDisplay(uint8_t i) {
  if (i) {
    ssd1306_command(SSD1306_INVERTDISPLAY);
  } else {
    ssd1306_command(SSD1306_NORMALDISPLAY);
  }
}

void ssd1306_command(uint8_t c) {
	// I2C
	//	uint8_t control = 0x00;   // Co = 0, D/C = 0

	uint8_t i2c_message[2] = {0,0};
	i2c_message[1] = c;
	HAL_I2C_Master_Transmit(OLED_i2c_handle, OLED_i2c_address, i2c_message, 2, 2000);
}


// Dim the display
// dim = true: display is dimmed
// dim = false: display is normal
void ssd1306_dim(uint8_t dim) {
  uint8_t contrast;

  if (dim) {
    contrast = 0; // Dimmed display
  } else {
    if (OLED_externalVCC == SSD1306_EXTERNALVCC) {
      contrast = 0x9F;
    } else {
      contrast = 0xCF;
    }
  }
  // the range of contrast to too small to be really useful
  // it is useful to dim the display
  ssd1306_command(SSD1306_SETCONTRAST);
  ssd1306_command(contrast);
}



void ssd1306_display_full_buffer(void) {

	ssd1306_home();

//	for (int i = 0; i < 512; i++)
//	{
//		displayBufferChunk[0] = 0x40;
//		for (int x = 0; x < 16; x++)
//		{
//			displayBufferChunk[x+1] = buffer[i];
//			i++;
//		}
//		HAL_I2C_Master_Transmit_DMA(OLED_i2c_handle, OLED_i2c_address, displayBufferChunk, 17);
////		HAL_I2C_Master_Transmit(OLED_i2c_handle, OLED_i2c_address, displayBufferChunk, 17, 2000);
////		HAL_Delay(1);
//		i--;
//	}
	displayBufferChunk[0] = 0x40;
	for (int i = 0; i < 512; i++)
	{
		displayBufferChunk[i+1] = buffer[i];
	}
	HAL_I2C_Master_Transmit_DMA(OLED_i2c_handle, OLED_i2c_address, displayBufferChunk, 513);
}



void ssd1306_home(void) {

	ssd1306_move_raw(0,0);
}

void ssd1306_move_raw(uint8_t row, uint8_t column){
	if(column > 127) { column = 127; }
	if(row > 7) { row = 7; }
	ssd1306_command(SSD1306_COLUMNADDR);
	ssd1306_command(column);   // Column start address (0 = reset)
	ssd1306_command(SSD1306_LCDWIDTH-1); // Column end address (127 = reset)

	ssd1306_command(SSD1306_PAGEADDR);
	ssd1306_command(row); // Page start address (0 = reset)
	ssd1306_command(3); // Page end address
}


void ssd1306_move(uint8_t row, uint8_t column) {

	if(column > 15) { column = 15; }
	if(row > 7) { row = 7; }
	ssd1306_move_raw(row,(uint8_t)(column << 3));
}


void ssd1306_write_internal(uint8_t* data, uint16_t numBytes) {
	for (uint16_t i = 0; i < numBytes; i++)
	{
		buffer[i+(OLED_xpos + (OLED_ypos * 128))] = data[i];

	}
}



void ssd1306_write(uint8_t* data, uint16_t numBytes) {

	uint8_t localBuffer[numBytes+1];

	localBuffer[0] = 0x40;

	for (uint16_t i = 0; i < numBytes; i++)
	{
		localBuffer[i+1] = data[i];
	}

	HAL_I2C_Master_Transmit(OLED_i2c_handle, OLED_i2c_address, localBuffer, numBytes+1, 2000);

}

void ssd1306_write_2X(uint8_t* data, uint16_t numBytes) {

	uint8_t localBuffer[(numBytes*2)+1];

	localBuffer[0] = 0x40;

	for (uint16_t i = 0; i < numBytes; i++)
	{
		localBuffer[i+1] = data[i] >> 4;

	}

	HAL_I2C_Master_Transmit(OLED_i2c_handle, OLED_i2c_address, localBuffer, (numBytes*2)+1, 2000);

	ssd1306_move(1,0);

	for (uint16_t i = 0; i < numBytes; i++)
	{
		localBuffer[i+1] = data[i] & 0x0f;
	}

	HAL_I2C_Master_Transmit(OLED_i2c_handle, OLED_i2c_address, localBuffer, (numBytes*2)+1, 2000);

}