/******************************************************************************* * File Name : ssd1306.c * Author : lxyppc * Version : V1.0 * Date : 10-01-21 * Description : ssd1306 operations * the SSH1101A is compatible with ssd1306 *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include "stm32l100c_discovery.h" #include "bsp.h" #include "ssd1306.h" #include "DrawText.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define SSD1306_PAGE_NUMBER 8 #define SSD1306_COLUMN_NUMBER 128 #define SSD1306_COLUMN_MARGIN_START 2 #define SSD1306_COLUMN_MARGIN_END 2 #define SSD1306_X_PIXEL 128 #define SSD1306_Y_PIXEL 64 /* Private macro -------------------------------------------------------------*/ #define ssd1306_Buffer (_SSD1306_Buffer + SSD1306_COLUMN_MARGIN_START) /* Private variables ---------------------------------------------------------*/ static uint8_t _SSD1306_Buffer[SSD1306_COLUMN_NUMBER*SSD1306_PAGE_NUMBER + SSD1306_COLUMN_MARGIN_START + SSD1306_COLUMN_MARGIN_END] = {0}; static uint8_t pageIndex = 0; static uint8_t iS_SSD_On = 0; static uint8_t pre_on = 0; static uint8_t curContrast = 0xCC; static uint8_t lastContrast = 0xCC; /* Private function prototypes -----------------------------------------------*/ void WriteCommand(unsigned char command); void WriteData(unsigned char data); void OnPageTransferDone(void); unsigned long ssd1306_OFF(void); unsigned long ssd1306_ON(void); unsigned char* ssd1306_GetBuffer() { return ssd1306_Buffer; } /******************************************************************************* * Function Name : WriteCommand * Description : Write command to the ssd1306 * Input : None * Output : None * Return : None *******************************************************************************/ void WriteCommand(unsigned char command) { SSD_A0_Low(); SPI_SendByte(command); SPI_Wait(); } /******************************************************************************* * Function Name : WriteData * Description : Write data to the ssd1306 * Input : None * Output : None * Return : None *******************************************************************************/ void WriteData(unsigned char data) { SSD_A0_High(); SPI_SendByte(data); SPI_Wait(); } /******************************************************************************* * Function Name : ssd1306_Init * Description : Initialize the ssd1306 * Input : None * Output : None * Return : None *******************************************************************************/ void ssd1306_Init(void) { /* Generate a reset */ SSD_Reset_Low(); uint32_t i; for(i=5000; i>1; i--) SSD_Reset_High(); /************************************************* // ssd1306 Initialization Command *************************************************/ // Lower Column Address WriteCommand(0x00); /* Set Lower Column Address */ GPIO_SetBits(GPIOA,GPIO_Pin_15);//turn on status LED // High Column Address WriteCommand(0x10); /* Set Higher Column Address*/ // Display Start Line WriteCommand(0x40); /* Set Display Start Line */ #ifdef DEBUG_BOARD curContrast = lastContrast = 0x30; #else curContrast = lastContrast = 0xCF; #endif // Contrast Control Register WriteCommand(0x81); /* Set Contrast Control */ WriteCommand(lastContrast); /* 0 ~ 255 0x1f*/ // Re-map WriteCommand(0xA1); /* [A0]:column address 0 is map to SEG0 , [A1]: columnaddress 131 is map to SEG0*/ // Entire Display ON/OFF WriteCommand(0xA4); /* A4=ON */ // Normal or Inverse Display WriteCommand(0XA6); /* Normal Display*/ // Multiplex Ratio WriteCommand(0xA8); /* Set Multiplex Ratio */ WriteCommand(0x3f); /* Set to 36 Mux*/ // Set DC-DC WriteCommand(0xAD); /* Set DC-DC */ WriteCommand(0x8B); /* 8B=ON, 8A=Off */ // Display ON/OFF WriteCommand(0xAE); /* AF=ON , AE=OFF*/ // Display Offset WriteCommand(0xD3); /* Set Display Offset */ WriteCommand(0x00); /* No offset */ // Display Clock Divide WriteCommand(0xD5); /* Set Clock Divide */ WriteCommand(0x20); /* Set to 80Hz */ // Area Color Mode WriteCommand(0xD8); /* Set Area Color On or Off*/ WriteCommand(0x00); /* Mono Mode */ // COM Pins Hardware Configuration WriteCommand(0xDA); /* Set Pins HardwareConfiguration */ WriteCommand(0x12); // VCOMH WriteCommand(0xDB); /* Set VCOMH */ WriteCommand(0x00); // VP WriteCommand(0xD9); /* Set VP */ WriteCommand(0x22); /* P1=2 , P2=2 */ // Set Common output scan direction WriteCommand(0xc8);/* Set COM scan direction */ // For SSD1306 Set the address mode WriteCommand(0x20);/* Set address mode */ WriteCommand(0x00);/* Set address mode horizontal */ // Set the page start address WriteCommand(0xb0); WriteCommand(0x00); WriteCommand(0x10); /* Turn on the controller */ pre_on = ssd1306_ON(); // // Set Charge pump // WriteCommand(0x8D); /* Set Charge pump */ // WriteCommand(0x14); /* 0x14=ON, 0x10=Off */ // // // Turn on the display // WriteCommand(0xaf); } void ssd1306_block_write(void) { // Set col start addr to 0 WriteCommand(0x21); WriteCommand(0x00); // Set col end addr to width - 1 WriteCommand(127); // Set page addr WriteCommand(0x22); WriteCommand(0x00); // start page addr WriteCommand(4); // end page addr (height / 8) uint32_t i = 0; for(i=0;i<1024;i++) WriteData(ssd1306_Buffer[i]); } /******************************************************************************* * Function Name : ssd1306_TurnOff * Description : Turn off the ssd1306 controller * Input : None * Output : None * Return : None *******************************************************************************/ unsigned long ssd1306_TurnOff(void) { pre_on = 0; return iS_SSD_On; } /******************************************************************************* * Function Name : ssd1306_TurnOn * Description : Turn off the ssd1306 controller * Input : None * Output : None * Return : None *******************************************************************************/ unsigned long ssd1306_TurnOn(void) { pre_on = 1; return iS_SSD_On; } /******************************************************************************* * Function Name : ssd1306_SetContrast * Description : Set the ssd1306 contrast * Input : None * Output : None * Return : None *******************************************************************************/ unsigned char ssd1306_SetContrast(unsigned char contrast) { curContrast = contrast; return lastContrast; } /******************************************************************************* * Function Name : ssd1306_GetContrast * Description : Get the ssd1306 contrast * Input : None * Output : None * Return : None *******************************************************************************/ unsigned char ssd1306_GetContrast() { return lastContrast; } /******************************************************************************* * Function Name : ssd1306_OFF * Description : Turn off the ssd1306 controller * Input : None * Output : None * Return : None *******************************************************************************/ unsigned long ssd1306_OFF(void) { if(iS_SSD_On){ #ifdef DEBUG_UI uint32_t i = 0; for(i=0;iCCR &= ((uint32_t)0xFFFFFFFE); DMA1_Channel5->CNDTR = ssd1306_COLUMN_NUMBER+SSD1306_COLUMN_MARGIN_START + SSD1306_COLUMN_MARGIN_END; DMA1_Channel5->CMAR = (uint32_t)(ssd1306_Buffer+SSD1306_COLUMN_NUMBER*pageIndex - SSD1306_COLUMN_MARGIN_START); DMA_SSD_1306->CCR |= ((uint32_t)0x00000001); pageIndex++; #else SSD_A0_High(); DMA_SSD_1306->CCR &= ((uint32_t)0xFFFFFFFE); DMA_SSD_1306->CNDTR = SSD1306_COLUMN_NUMBER*SSD1306_PAGE_NUMBER;//+SSD1306_COLUMN_MARGIN_START + SSD1306_COLUMN_MARGIN_END; DMA_SSD_1306->CMAR = (uint32_t)(ssd1306_Buffer);//+SSD1306_COLUMN_NUMBER*pageIndex); //DMA_Cmd(DMA_SSD_1306, ENABLE); DMA_SSD_1306->CCR |= ((uint32_t)0x00000001); // pageIndex++; pageIndex = SSD1306_PAGE_NUMBER; #endif } /******************************************************************************* * Function Name : DMA1_Channel5_IRQHandler * Description : This function handles DMA1 Channel 5 interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void DMA_Handler_SSD_1306(void) //DMA1_Channel5_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC5)){ DMA_ClearITPendingBit(DMA1_IT_GL5); OnPageTransferDone(); } } /******************************************************************************* * Function Name : StartPageTransfer * Description : Start a new page transfer * Input : None * Output : None * Return : None *******************************************************************************/ void StartPageTransfer(void) { pageIndex = 0; if(pre_on){ if(iS_SSD_On == 0){ pre_on = ssd1306_ON(); } }else{ if(iS_SSD_On){ pre_on = ssd1306_OFF(); } } if( curContrast != lastContrast ){ lastContrast = curContrast; WriteCommand(0x81); /* Set Contrast Control */ WriteCommand(lastContrast); /* 0 ~ 255 0x1f*/ } if(iS_SSD_On){ OnPageTransferDone(); } } /******************************************************************************* Display related functions ******************************************************************************/ /******************************************************************************* * Function Name : ssd1306_DrawBlock * Description : Draw a block with specify data to ssd1306 * Input : None * Output : None * Return : None *******************************************************************************/ unsigned long ssd1306_DrawBlock( Pos_t x, Pos_t y, Pos_t cx, Pos_t cy, const unsigned char* data) { if(x >= SSD1306_X_PIXEL)return 0; if(y >= SSD1306_Y_PIXEL)return 0; if(x+cx > SSD1306_X_PIXEL ) cx = SSD1306_X_PIXEL - x ; if(y+cy > SSD1306_Y_PIXEL ) cy = SSD1306_Y_PIXEL - y ; unsigned char* pStart = ssd1306_Buffer + (y/8)*SSD1306_COLUMN_NUMBER + x; unsigned char offset1 = y%8; unsigned char offset2 = (cy+y)%8; if(data){ unsigned char mask1 = (1<>=8; } if(offset2){ tmp |= ((((unsigned short)data[j*cx])<>=8; // if(j == (cy/8)-1){ // // Last line // *(pStart + (j+1)*ssd1306_COLUMN_NUMBER + i + x) &= ~mask; // *(pStart + (j+1)*ssd1306_COLUMN_NUMBER + i + x) |= tmp; // } // } // } // } return 0; } /******************************************************************************* * Function Name : ssd1306_DrawPoint * Description : Draw a point with specify data to ssd1306 * Input : None * Output : None * Return : None *******************************************************************************/ unsigned long ssd1306_DrawPoint( Pos_t x, Pos_t y, Color_t color) { if(x >= SSD1306_X_PIXEL)return 0; if(y >= SSD1306_Y_PIXEL)return 0; unsigned char* pStart = ssd1306_Buffer + (y/8)*SSD1306_COLUMN_NUMBER + x; unsigned char mask = 1<<(y%8); if(color){ *pStart |= mask; }else{ *pStart &= ~mask; } return 0; } /******************************************************************************* * Function Name : ssd1306_ReadPoint * Description : Read a point from ssd1306 * Input : None * Output : None * Return : None *******************************************************************************/ unsigned long ssd1306_ReadPoint( Pos_t x, Pos_t y) { unsigned char* pStart = ssd1306_Buffer + (y/8)*SSD1306_COLUMN_NUMBER + x; unsigned char mask = 1<<(y%8); return *pStart&mask ? 1 : 0; } /******************************************************************************* * Function Name : ssd1306_ClearScreen * Description : Clear the screen contents * Input : None * Output : None * Return : None *******************************************************************************/ void ssd1306_FillScreen(Color_t color) { unsigned char mask = color ? 0xFF : 0; unsigned long i = 0; for(i=0;i