498 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			498 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | #include "max7456.h"
 | ||
|  | #include <Arduino.h>
 | ||
|  | #include <SPI.h>
 | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::Max7456
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | Max7456::Max7456(byte pinCS) | ||
|  | { | ||
|  | 	this->init(pinCS); | ||
|  | } | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::setBlinkParams
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::setBlinkParams(byte blinkBase, byte blinkDC) | ||
|  | { | ||
|  | 	_regVm1.bits.blinkingTime = blinkBase; | ||
|  | 	_regVm1.bits.blinkingDutyCycle = blinkDC; | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	SPI.transfer(VM1_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regVm1.whole); | ||
|  | 	digitalWrite(_pinCS,HIGH);	 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::setDisplayOffsets
 | ||
|  | //----------------------------------------------------------------------------
 | ||
|  | void Max7456::setDisplayOffsets(byte horizontal, byte vertical) | ||
|  | { | ||
|  | 	 | ||
|  | 	_regHos.whole = 0; | ||
|  | 	_regVos.whole = 0; | ||
|  | 	 | ||
|  | 	_regHos.bits.horizontalPositionOffset = horizontal; | ||
|  | 	_regVos.bits.verticalPositionOffset = vertical; | ||
|  | 	 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	SPI.transfer(HOS_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regHos.whole); | ||
|  | 
 | ||
|  | 	SPI.transfer(VOS_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regVos.whole); | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,HIGH);	 | ||
|  | } | ||
|  | 	 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::Max7456
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | Max7456::Max7456() | ||
|  | { | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::sendCharacter
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::sendCharacter(const charact chara, byte x, byte y) | ||
|  | { | ||
|  | 	byte charAddress; | ||
|  | 	if(y<0) | ||
|  | 		charAddress = x; | ||
|  | 	else | ||
|  | 		charAddress = x + (y<<4); | ||
|  | 	activateOSD(false); | ||
|  | 	//datasheet p38
 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	SPI.transfer(CMAH_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(charAddress); | ||
|  | 
 | ||
|  | 	for(byte i = 0 ; i < 54 ; i++) | ||
|  | 	{ | ||
|  | 		SPI.transfer(CMAL_ADDRESS_WRITE); | ||
|  | 		SPI.transfer(i); | ||
|  | 		SPI.transfer(CMDI_ADDRESS_WRITE); | ||
|  | 		SPI.transfer(chara[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_regCmm = 0xA0; //To write the NVM array
 | ||
|  | 	SPI.transfer(CMM_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regCmm); | ||
|  | 	//while STAT[5] is not good, we wait.
 | ||
|  | 	_regStat.bits.characterMemoryStatus = 1; | ||
|  | 	while(  _regStat.bits.characterMemoryStatus ==1) | ||
|  | 	{ | ||
|  | 		SPI.transfer(STAT_ADDRESS_READ); | ||
|  | 		_regStat.whole = SPI.transfer(0x00); | ||
|  | 	} | ||
|  | 
 | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,HIGH); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::getCharacter
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::getCharacter(charact chara, byte x, byte y) | ||
|  | { | ||
|  | 	byte charAddress; | ||
|  | 
 | ||
|  | 
 | ||
|  | 	if(y<=0) | ||
|  | 		charAddress = x; | ||
|  | 	else | ||
|  | 		charAddress = x + y*16; | ||
|  | 
 | ||
|  | 	activateOSD(false); | ||
|  | 	//datasheet p38
 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	SPI.transfer(CMAH_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(charAddress); | ||
|  | 
 | ||
|  | 	_regCmm = 0x50; //To read from the NVM array
 | ||
|  | 	SPI.transfer(CMM_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regCmm); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	for(byte i = 0 ; i < 54 ; i++) | ||
|  | 	{ | ||
|  | 		SPI.transfer(CMAL_ADDRESS_WRITE); | ||
|  | 		SPI.transfer(i); | ||
|  | 
 | ||
|  | 		SPI.transfer(CMDO_ADDRESS_READ); //read from device through spi
 | ||
|  | 		chara[i] = SPI.transfer(0x00); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,HIGH); | ||
|  | 
 | ||
|  | } | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::printCharacterToSerial
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::printCharacterToSerial(const charact array, bool img) | ||
|  | { | ||
|  | 
 | ||
|  | 	if(img) | ||
|  | 	{ | ||
|  | 		CARACT car ; | ||
|  | 		car = Max7456::byteArray2CARACT(array); | ||
|  | 
 | ||
|  | 		Serial.println("------------"); | ||
|  | 		for(int i = 0 ; i < 18 ; i++) | ||
|  | 		{ | ||
|  | 			for(int j = 0 ; j < 3 ; j++) | ||
|  | 			{ | ||
|  | 				printPixel(car.line[i].pixels[j].pix0); | ||
|  | 				printPixel(car.line[i].pixels[j].pix1); | ||
|  | 				printPixel(car.line[i].pixels[j].pix2); | ||
|  | 				printPixel(car.line[i].pixels[j].pix3); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			Serial.println(""); | ||
|  | 		} | ||
|  | 		Serial.println("------------"); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	else | ||
|  | 	{ | ||
|  | 		Serial.print("{"); | ||
|  | 		for(unsigned int i = 0 ; i < 53 ; i++) | ||
|  | 		{ | ||
|  | 			Serial.print("0x"); | ||
|  | 			Serial.print(String(array[i],HEX)); | ||
|  | 			Serial.print(", "); | ||
|  | 		} | ||
|  | 		Serial.print("0x"); | ||
|  | 		Serial.print(String(array[53],HEX)); | ||
|  | 		Serial.println("};"); | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | void Max7456::printPixel(byte value) | ||
|  | { | ||
|  | 	switch(value ) | ||
|  | 	{ | ||
|  | 	case COLOR_BLACK : | ||
|  | 		Serial.print("#"); | ||
|  | 		return; | ||
|  | 	case COLOR_WHITE : | ||
|  | 		Serial.print("*"); | ||
|  | 		return; | ||
|  | 	default: | ||
|  | 		Serial.print(" "); | ||
|  | 		return; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::print
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::print(const char string[], byte x, byte y, byte blink,byte inv) | ||
|  | { | ||
|  | 	char          currentChar; | ||
|  | 	byte          size; | ||
|  | 	byte *chars = NULL; | ||
|  | 
 | ||
|  | 	if(!string) return; | ||
|  | 
 | ||
|  | 	size = 0; | ||
|  | 	currentChar = string[0]; | ||
|  | 
 | ||
|  | 	while(currentChar != '\0') | ||
|  | 	{ | ||
|  | 		currentChar = string[++size]; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	chars = (byte*) malloc(size * sizeof(byte)); | ||
|  | 
 | ||
|  | 	for(byte i = 0 ; i < size ; i++) | ||
|  | 	{ | ||
|  | 		chars[i] = Max7456::giveMax7456CharFromAsciiChar(string[i]); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	printMax7456Chars(chars, size, x,  y,  blink , inv ); | ||
|  | 	free(chars); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void Max7456::printMax7456Char(const byte address, byte x, byte y, byte blink, byte inv) | ||
|  | { | ||
|  | 	byte ad = address; | ||
|  | 	printMax7456Chars(&ad,1,x,y,blink,inv); | ||
|  | } | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::printMax7456Chars
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::printMax7456Chars(byte chars[],byte size,byte x, byte y, byte blink ,byte inv ) | ||
|  | { | ||
|  | 	byte          currentCharMax7456; | ||
|  | 	byte          posAddressLO; | ||
|  | 	byte          posAddressHI; | ||
|  | 	unsigned int  posAddress; | ||
|  | 
 | ||
|  | 	posAddress = 30*y+x; | ||
|  | 
 | ||
|  | 	posAddressHI = posAddress >> 8; | ||
|  | 	posAddressLO = posAddress; | ||
|  | 
 | ||
|  | 	_regDmm.whole = 0x01; | ||
|  | 
 | ||
|  | 	_regDmm.bits.INV = inv; | ||
|  | 	_regDmm.bits.BLK = blink; | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	SPI.transfer(DMM_ADDRESS_WRITE); | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 	SPI.transfer(_regDmm.whole); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	SPI.transfer(DMAH_ADDRESS_WRITE); // set start address high
 | ||
|  | 	SPI.transfer(posAddressHI); | ||
|  | 
 | ||
|  | 	SPI.transfer(DMAL_ADDRESS_WRITE); // set start address low
 | ||
|  | 	SPI.transfer(posAddressLO); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	for(int i = 0; i < size ; i++) | ||
|  | 	{ | ||
|  | 		currentCharMax7456 = chars[i]; | ||
|  | 		SPI.transfer(DMDI_ADDRESS_WRITE); | ||
|  | 		SPI.transfer(currentCharMax7456); | ||
|  | 
 | ||
|  | 	} | ||
|  | 
 | ||
|  | 	//end character (we're done).
 | ||
|  | 	SPI.transfer(DMDI_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(0xff); | ||
|  | 
 | ||
|  | /*
 | ||
|  | 	_regVm0.bits. | ||
|  | 	SPI.transfer(VM0_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(0x4c);*/ | ||
|  | 
 | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,HIGH); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::print
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | 
 | ||
|  | void Max7456::print(double value, byte x, byte y, byte before, byte after, byte blink,byte inv) | ||
|  | { | ||
|  | 	char *strValue = NULL; | ||
|  | 
 | ||
|  | 	strValue = (char*) malloc((before+after+2)* sizeof(char)); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	if(after==0) | ||
|  | 		dtostrf(value,before+after,after,strValue); | ||
|  | 	else | ||
|  | 		dtostrf(value,before+after+1,after,strValue); | ||
|  | 
 | ||
|  | 	for(int i = 0 ; i < before+after+1;i++) | ||
|  | 		{ | ||
|  | 			if(strValue[i] == ' ' || strValue[i] == '-') | ||
|  | 				strValue[i]='0'; | ||
|  | 		} | ||
|  | 	if(value < 0) | ||
|  | 		strValue[0]='-'; | ||
|  | 	if(after==0) //If the result is bigger, we truncate it so the OSD won't be falsed.
 | ||
|  | 		strValue[before]='\0'; | ||
|  | 	else | ||
|  | 		strValue[before+after+1]='\0'; | ||
|  | 
 | ||
|  | 	print(strValue,x,y,blink,inv); | ||
|  | 
 | ||
|  | 	free(strValue); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::giveMax7456CharFromAsciiChar
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | byte Max7456::giveMax7456CharFromAsciiChar(char ascii) | ||
|  | { | ||
|  | #ifdef MAX7456_TABLE_ASCII
 | ||
|  | 	if(ascii >= ' ' && ascii <= 'z') | ||
|  | 		return ascii-' '; | ||
|  | 	else | ||
|  | 		return ascii; | ||
|  | #else
 | ||
|  | 	return ascii; | ||
|  | #endif
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::clearScreen
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::clearScreen() | ||
|  | { | ||
|  | 	_regDmm.bits.clearDisplayMemory = 1 ; | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS, LOW); | ||
|  | 
 | ||
|  | 	SPI.transfer(DMM_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regDmm.whole); | ||
|  | 
 | ||
|  | 	//wait for operation to be complete.
 | ||
|  | 	while(_regDmm.bits.clearDisplayMemory == 1 ) | ||
|  | 	{ | ||
|  | 		SPI.transfer(DMM_ADDRESS_READ); | ||
|  | 		_regDmm.whole = SPI.transfer(0x00); | ||
|  | 	} | ||
|  |     digitalWrite(_pinCS, HIGH); //disable device
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::init
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::init(byte iPinCS) | ||
|  | { | ||
|  | 	_pinCS = iPinCS; | ||
|  | 	_isActivatedOsd = false; | ||
|  | 
 | ||
|  | 	_regVm1.whole = 0b01000111; | ||
|  | 	pinMode(iPinCS, OUTPUT); | ||
|  |     digitalWrite(iPinCS, HIGH); //disable device
 | ||
|  |     delay(100); //power up time
 | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	SPI.transfer(VM0_ADDRESS_WRITE); | ||
|  | 
 | ||
|  | 	_regVm0.whole = 0x00; | ||
|  | 	_regVm0.bits.videoSelect=1; //PAL
 | ||
|  | 	_regVm0.bits.softwareResetBit = 1; | ||
|  | 	SPI.transfer(_regVm0.whole); | ||
|  | 	digitalWrite(_pinCS,HIGH); | ||
|  | 	delay(500); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	for(int x = 0 ; x < 16 ; x++) | ||
|  | 	{ | ||
|  | 		_regRb[x].whole = 0x00; | ||
|  | 		_regRb[x].bits.characterWhiteLevel = 2; | ||
|  | 		SPI.transfer(x+RB0_ADDRESS_WRITE); | ||
|  | 		SPI.transfer(_regRb[x].whole); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	_regVm0.whole = 0x00; | ||
|  | 
 | ||
|  | 	_regVm0.bits.verticalSynch = 1; | ||
|  | 
 | ||
|  | 	SPI.transfer(VM0_ADDRESS_WRITE); | ||
|  | 
 | ||
|  | 	SPI.transfer(_regVm0.whole); | ||
|  | 
 | ||
|  | 
 | ||
|  | 	//  digitalWrite(_pinCS,HIGH);
 | ||
|  | 	//
 | ||
|  | 	//  digitalWrite(_pinCS,LOW);
 | ||
|  | 	//SPI.transfer(VM1_ADDRESS_WRITE);
 | ||
|  | 	//SPI.transfer(0x0C);
 | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,HIGH); | ||
|  | 
 | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::activateOSD
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::activateOSD(bool act) | ||
|  | { | ||
|  | 	if(_isActivatedOsd != act) | ||
|  | 	{ | ||
|  | 
 | ||
|  | 		_regVm0.bits.videoSelect = 1; | ||
|  | 		if(act) | ||
|  | 			_regVm0.bits.enableOSD = 1; | ||
|  | 		else | ||
|  | 			_regVm0.bits.enableOSD = 0; | ||
|  | 
 | ||
|  | 		digitalWrite(_pinCS,LOW); | ||
|  | 		SPI.transfer(VM0_ADDRESS_WRITE); | ||
|  | 		SPI.transfer(_regVm0.whole); | ||
|  | 		digitalWrite(_pinCS,HIGH); | ||
|  | 		_isActivatedOsd = act; | ||
|  | 	} | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::activateExternalVideo
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::activateExternalVideo(bool activExtVid) | ||
|  | { | ||
|  | 	if(!activExtVid) | ||
|  | 		_regVm0.bits.synchSelect = 3; //11
 | ||
|  | 	else | ||
|  | 		_regVm0.bits.synchSelect = 0; //0
 | ||
|  | 
 | ||
|  | 	digitalWrite(_pinCS,LOW); | ||
|  | 	SPI.transfer(VM0_ADDRESS_WRITE); | ||
|  | 	SPI.transfer(_regVm0.whole); | ||
|  | 	digitalWrite(_pinCS,HIGH); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::CARACT2ByteArray
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | byte* Max7456::CARACT2ByteArray(const CARACT car) | ||
|  | { | ||
|  | 	byte *array = NULL; | ||
|  | 	array = new charact; | ||
|  | 	for(int i = 0 ; i < 54 ; i++) | ||
|  | 		array[i]= car.whole[i]; | ||
|  | 
 | ||
|  | 	return array; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::byteArray2CARACT
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | CARACT Max7456::byteArray2CARACT(const charact array) | ||
|  | { | ||
|  | 	CARACT car; | ||
|  | 	for(int i = 0 ; i < 54 ; i++) | ||
|  | 		car.whole[i] = array[i]; | ||
|  | 
 | ||
|  | 	return car; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | // Implements Max7456::getCARACFromProgMem
 | ||
|  | //-----------------------------------------------------------------------------
 | ||
|  | void Max7456::getCARACFromProgMem(const char *table, byte i, charact car) | ||
|  | { | ||
|  | 	unsigned long index; | ||
|  | 	byte read; | ||
|  | 	index = i*54; | ||
|  | 	for(unsigned long j = 0 ; j < 54 ; j++) | ||
|  | 	{ | ||
|  | 		read = pgm_read_byte_near(table +index+j ); | ||
|  | 		car[j] = read; | ||
|  | 		if (car[j] == 0x55) | ||
|  | 			car[j] = 0xff; | ||
|  | 	} | ||
|  | } | ||
|  | 
 |