/*
 * MonoGLCD.cpp
 */

#include "MonoGLCD.h"
#include "stm32f1xx_hal.h"

// defines ------
#define DISPLAY_ON 				0xAF
#define DISPLAY_OFF 			0xAE

#define DISPLAY_START_LINE_SET	0x40 	//0x40 to 0x7F	63-Stufen
#define PAGE_ADRESS_SET			0xB0 	//0xB0 to 0xB8	8-Stufen
#define COLUMN_ADRESS_SET		0x00 	//0x00 to 0x18	24-Stufen
// ---- Column Adresses for GDSC-12864WM-64 ----
#define HIGH_NIBBLE				0x10	// 0x10 to 0x18
#define LOW_NIBBLE				0x00	// 0x00 to 0x0F
// --------------

#define ADC_SELECT_NORMAL		0xA0
#define ADC_SELECT_REVERSE		0xA1

#define DISPLAY_NORMAL			0xA6
#define DISPLAY_REVERSE			0xA7

#define DISPLAY_UPSIDE			0xC0
#define DISPLAY_UPSIDEDOWN		0xC8

#define ENTIRE_DISPLAY_ON		0xA4
#define ENTIRE_DISPLAY_OFF		0xA5

#define LCD_BIAS_1_9			0xA2	//default
#define	LCD_BIAS_1_7			0xA3

#define BOOST4X					0x2F
#define BOOSTXX					0xFB

#define READ_MODIFY_WRITE		0xE0

#define END						0xEE
#define RESET					0xE2

#define COMMON_OUTPUT_MODE_SEL	0xC0	//0xC0 to 0xCF	15-Stufen

#define POWER_CONTROL_SET		0x28	//0x28 to 0x2F	7-Stufen

#define V0_VOLTAGE_REGULATOR	0x20	//0x20 to 0x27  7-Stufen
#define V0_VOLTAGE_DEFAULT      0x24

#define ELECTRONIC_VOLUME_MODE	0x81	//

#define SET_STATIC_INDIC_ON		0xAC	//
#define SET_STATIC_INDIC_OFF	0xAD

#define NORMAL_DISPLAY			0x82
#define PARTIAL_DISPLAY
// --------------------------------------
#define PAGE					8
#define SEGMENT  				128
// --------------------------------------



MonoGLCD::MonoGLCD() {
}

MonoGLCD::MonoGLCD(uint8_t* graphicBuffer):graphicBuffer(graphicBuffer){
	//MonoGLCD::graphicBuffer = graphicBuffer;
}

void MonoGLCD::config(DisplayBusParallel dbp, uint8_t* graphicBuffer) {
	MonoGLCD::dbp = dbp;
	MonoGLCD::graphicBuffer = graphicBuffer;
	MonoGLCD::upsideDownStatus = false;
}

void MonoGLCD::init(void) {

	MonoGLCD::dbp.init();

	// Display OFF
	MonoGLCD::dbp.writeCommand(DISPLAY_OFF);

	//  Reset
	MonoGLCD::dbp.writeCommand(RESET);
	HAL_Delay(100);
	// CLEAR RAM
	MonoGLCD::clearRAMall();

	//  Power Control 4x Boost fuer 3.3V
	MonoGLCD::dbp.writeCommand(BOOST4X);
	//  Booster
	//MonoGLCD::dbp.writeCommand(0xFB);
	// LCD non inverse
	MonoGLCD::dbp.writeCommand(DISPLAY_NORMAL);
	// Bias Control 1/9
	MonoGLCD::dbp.writeCommand(LCD_BIAS_1_9);
	// Bias Control 1/7
	//MonoGLCD::dbp.writeCommand(LCD_BIAS_1_7);
	// ADC Select - Normal
	MonoGLCD::dbp.writeCommand(ADC_SELECT_NORMAL);
	// ADC Select - Reverse
	//MonoGLCD::dbp.writeCommand(ADC_SELECT_REVERSE);

	//  Setze V0
	MonoGLCD::dbp.writeCommand(V0_VOLTAGE_DEFAULT);

	// Setze Kontrast
//	MonoGLCD::dbp.writeCommand(0x81);
//	MonoGLCD::dbp.writeCommand(0x0c);
//	MonoGLCD::dbp.writeCommand(0x20);

	//  LSB unten
	//#ifdef OPTION_DISPLAY_UPSIDEDOWN
//	MonoGLCD::dbp.writeCommand(DISPLAY_UPSIDEDOWN);
//	MonoGLCD::upsideDownStatus = true;
	//#else
	MonoGLCD::dbp.writeCommand(DISPLAY_UPSIDE);
	MonoGLCD::upsideDownStatus = false;
	//#endif

	HAL_Delay(10);
	// Display ON
	MonoGLCD::dbp.writeCommand(DISPLAY_ON);

	// Cursor ON
//	MonoGLCD::dbp.writeCommand(0xAD);
//	MonoGLCD::dbp.writeCommand(0x00);
//
//	MonoGLCD::dbp.writeCommand(0xE5);

	// Normal Display (no Partitial Display)
	MonoGLCD::dbp.writeCommand(NORMAL_DISPLAY);

}

void MonoGLCD::update(void) {
	uint16_t i = 0;
	uint8_t j = 0;
		for(j=0; j<PAGE;j++) {		//Pages
			MonoGLCD::dbp.writeCommand(PAGE_ADRESS_SET + j);	//selsct Page
			MonoGLCD::dbp.writeCommand(HIGH_NIBBLE);
			MonoGLCD::dbp.writeCommand(LOW_NIBBLE);
			for(i=0; i < SEGMENT ;i++) {		//Segment
				if(MonoGLCD::upsideDownStatus) {
					MonoGLCD::dbp.writeData(MonoGLCD::graphicBuffer[(j * SEGMENT) + i]);
				} else {
					MonoGLCD::dbp.writeData(MonoGLCD::graphicBuffer[j * SEGMENT + (SEGMENT - i - 1)]);
				}
			}
		}
}
void MonoGLCD::clearRAM(void) {
	uint16_t i = 0;
	uint8_t j = 0;
		for(j=0; j<PAGE;j++) {		//Pages
			MonoGLCD::dbp.writeCommand(PAGE_ADRESS_SET + j);	//selsct Page
			MonoGLCD::dbp.writeCommand(HIGH_NIBBLE);
			MonoGLCD::dbp.writeCommand(LOW_NIBBLE);
			for(i=0; i < SEGMENT ;i++) MonoGLCD::dbp.writeData(0x00);
		}
}
void MonoGLCD::FFxRAM(void) {
	uint16_t i = 0;
	uint8_t j = 0;
		for(j=0; j<PAGE;j++) {		//Pages
			MonoGLCD::dbp.writeCommand(PAGE_ADRESS_SET + j);	//selsct Page
			MonoGLCD::dbp.writeCommand(HIGH_NIBBLE);
			MonoGLCD::dbp.writeCommand(LOW_NIBBLE);
			for(i=0; i < SEGMENT ;i++) MonoGLCD::dbp.writeData(0xFF);
		}
}
void MonoGLCD::clearRAMall(void) {
	uint16_t i = 0;
	uint8_t k = 0, j = 0;
	for(k=0; k<2;k++) {		//ADC
		MonoGLCD::dbp.writeCommand(0xA0+k);
		for(j=0; j<PAGE;j++) {		//Pages
			MonoGLCD::dbp.writeCommand(0xB0 + j);	//selsct Page
			MonoGLCD::dbp.writeCommand(0x10);
			if(0==k) MonoGLCD::dbp.writeCommand(0x00);
			else MonoGLCD::dbp.writeCommand(0x04);
			for(i=0; i < SEGMENT ;i++) {		//Segment
				if(0==k) {
					if(MonoGLCD::upsideDownStatus) MonoGLCD::dbp.writeData(0x00);
					else MonoGLCD::dbp.writeData(0x00);
				}
				else {
					if(MonoGLCD::upsideDownStatus) MonoGLCD::dbp.writeData(0x00);
					else MonoGLCD::dbp.writeData(0x00);
				}
			}
		}
	}
}

void MonoGLCD::invers(void) {
	MonoGLCD::dbp.writeCommand(0xA7);
	//MonoGLCD::setContrast(20);
}

void MonoGLCD::nonInvers(void) {
	MonoGLCD::dbp.writeCommand(0xA6);
	//MonoGLCD::setContrast(16);
}

void MonoGLCD::ALLdots(void) {
	MonoGLCD::dbp.writeCommand(0xA5);
}

void MonoGLCD::NOdots(void) {
	MonoGLCD::dbp.writeCommand(0xA4);
}

void MonoGLCD::lightOn(void) {
	MonoGLCD::dbp.ledOn();
}

void MonoGLCD::lightOff(void) {
	MonoGLCD::dbp.ledOff();
}

void MonoGLCD::upsideDown(void) {
	MonoGLCD::dbp.writeCommand(0xC0);
	MonoGLCD::upsideDownStatus = true;
}

void MonoGLCD::upsideUp(void) {
	MonoGLCD::dbp.writeCommand(0xC8);
	MonoGLCD::upsideDownStatus = false;
}

void MonoGLCD::setContrast(uint8_t contrast) {
	MonoGLCD::dbp.writeCommand(0x81);
	MonoGLCD::dbp.writeCommand(contrast);
}


// BACKUP


//void MonoGLCD::update(void) {
//	uint16_t i = 0;
//	uint8_t k = 0, j = 0;
////	for(k=0; k<2;k++) {		//ADC
////		MonoGLCD::dbp.writeCommand(0xA0+k);
//		for(j=0; j<8;j++) {		//Pages
//			MonoGLCD::dbp.writeCommand(0xB0 + j);	//selsct Page
//			MonoGLCD::dbp.writeCommand(0x10);
//			if(0==k) {
//				MonoGLCD::dbp.writeCommand(0x00);
//			} else {
//				MonoGLCD::dbp.writeCommand(0x04);
//			}
//			for(i=0; i < 128 ;i++) {		//Segment
////				if(0==k) {
////					if(MonoGLCD::upsideDownStatus) {
////						MonoGLCD::dbp.writeData(MonoGLCD::graphicBuffer[j * 128 + (128 - i - 1)]);
////					} else {
//						MonoGLCD::dbp.writeData(MonoGLCD::graphicBuffer[(j * 128) + i]);
////					}
////				} else {
////					if(MonoGLCD::upsideDownStatus) {
////						MonoGLCD::dbp.writeData(MonoGLCD::graphicBuffer[j * 128 + i]);
////					} else {
////						MonoGLCD::dbp.writeData(MonoGLCD::graphicBuffer[j * 128 + (128 - i - 1) ]);
////					}
////				}
////			}
//		}
//	}
//}
