So I was able to get this display going using an atmega and now I am giving an XMEGA a whirl.
Few things changed here, most notably that it's on a 3.3v supply now instead of 5v.
I am thinking initialization problem?
code that is not working:
#define F_CPU 32000000UL
#include <avr/io.h>
#include <util/delay.h>
const uint8_t ROW_N = 4; // Number of display rows
const uint8_t COLUMN_N = 20; // Number of display columns
const uint8_t SLAVE = 0x3C; // Display I2C address, in 7-bit form: 0x3C if SA0=LOW, 0x3D if SA0=HIGH
uint8_t new_line[4] = {0x80, 0xA0, 0xC0, 0xE0}; // DDRAM address for each line of the display
uint8_t rows = 0x08; // Display mode: 1/3 lines or 2/4 lines; default 2/4 (0x08)
uint8_t tx_packet[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // Packet to be transmitted (max 20 bytes)
#define BAUDRATE 100000L
#define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)
#define TWI_BAUDSETTING TWI_BAUD(F_CPU, BAUDRATE)
void twi_write(uint8_t writeData)
{
uint8_t addr = 0;
addr |= SLAVE << 1;
TWIC.MASTER.ADDR = addr;
while(!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm));
TWIC.MASTER.DATA = writeData;
while(!(TWIC.MASTER.STATUS & TWI_MASTER_WIF_bm));
TWIC.MASTER.CTRLC = 0x03; // ???
return;
}
void twi_init()
{
TWIC.CTRL = 0x00;
TWIC.MASTER.CTRLB = TWI_MASTER_SMEN_bm;
TWIC.MASTER.BAUD = TWI_BAUDSETTING;
TWIC.MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
TWIC.MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
return;
}
void send_packet(uint8_t x)
{
uint8_t ix = 0;
for(ix=0; ix<x; ix++)
{
twi_write(tx_packet[ix]);
}
}
void command(uint8_t c)
{
tx_packet[0] = 0x00;
tx_packet[1] = c;
send_packet(2);
}
void data(uint8_t d)
{
tx_packet[0] = 0x40;
tx_packet[1] = d;
send_packet(2);
}
void initlcd(void)
{
if (ROW_N == 2 || ROW_N == 4)
{
rows = 0x08; // Display mode: 2/4 lines
}
else
{
rows = 0x00; // Display mode: 1/3 lines
}
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x71); // Function selection A:
data(0x00); // 3.3v ??????
//data(0x5C); // enable internal Vdd regulator at 5V I/O mode (def. value) (0x00 for disable, 2.8V I/O)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x08); // Display ON/OFF control: display off, cursor off, blink off (default values)
command(0x22 | rows); // Function set: extended command set (RE=1), lines #
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xD5); // Set display clock divide ratio/oscillator frequency:
command(0x70); // divide ratio=1, frequency=7 (default values)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
if (ROW_N > 2)
{
command(0x09); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 3/4 lines
}
else
{
command(0x08); // Extended function set (RE=1): 5-dot font, B/W inverting disabled (def. val.), 1/2 lines
}
command(0x06); // Entry Mode set - COM/SEG direction: COM0->COM31, SEG99->SEG0 (BDC=1, BDS=0)
command(0x72); // Function selection B:
data(0x0A); // ROM/CGRAM selection: ROM C, CGROM=250, CGRAM=6 (ROM=10, OPR=10)
command(0x79); // OLED characterization: OLED command set enabled (SD=1)
command(0xDA); // Set SEG pins hardware configuration:
command(0x10); // alternative odd/even SEG pin, disable SEG left/right remap (default values)
command(0xDC); // Function selection C:
command(0x00); // internal VSL, GPIO input disable
command(0x81); // Set contrast control:
command(0x7F); // contrast=127 (default value)
command(0xD9); // Set phase length:
command(0xF1); // phase2=15, phase1=1 (default: 0x78)
command(0xDB); // Set VCOMH deselect level:
command(0x40); // VCOMH deselect level=1 x Vcc (default: 0x20=0,77 x Vcc)
command(0x78); // OLED characterization: OLED command set disabled (SD=0) (exit from OLED command set)
command(0x20 | rows); // Function set: fundamental command set (RE=0) (exit from extended command set), lines #
command(0x01); // Clear display
_delay_ms(2); // After a clear display, a minimum pause of 1-2 ms is required
command(0x80); // Set DDRAM address 0x00 in address counter (cursor home) (default value)
command(0x0C); // Display ON/OFF control: display ON, cursor off, blink off
_delay_ms(250); // Waits 250 ms for stabilization purpose after display on
if (ROW_N == 2)
{
new_line[1] = 0xC0; // DDRAM address for each line of the display (only for 2-line mode)
}
}
void blocks(void)
{
uint8_t r = 0;
uint8_t c = 0;
command(0x01); // Clear display (and cursor home)
_delay_ms(2);
for (r=0; r < ROW_N; r++)
{
command(new_line[r]);
for (c=0; c < COLUMN_N; c++)
{
data(0xDB); // displays character 0xDB (block)
_delay_ms(100);
}
}
}
int main(void)
{
CCP = 0xD8;
OSC.CTRL = 0x02;
while(!(OSC.STATUS & 0x02));
CCP = 0xD8;
CLK.CTRL = 0x01;
twi_init();
initlcd();
uint8_t addr = 0;
addr |= SLAVE << 1;
/* Replace with your application code */
while (1)
{
//TWIC_MASTER_ADDR = addr;
blocks();
}
}