#include "mik32_hal_ssd1306.h"

// Адрес ведомого
uint16_t slave_address = 0b00111100;


uint8_t data_test[] = {
    DATS, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

/*Символы для SSD1306 128x32*/

/* Символ ":)" */
uint8_t data_symbol_smile[] = {
    DATS,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
    0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0,
    0x00, 0x01, 0x02, 0x07, 0x0F, 0x1E, 0x3C, 0x38, 0x38, 0x78, 0x70, 0x70, 0x70, 0x70, 0x70, 0x78, 0x38, 0x38, 0x3C, 0x1E, 0x0F, 0x07, 0x02, 0x01, 0x00
};

/* Символ ":" */
uint8_t data_symbol_colon[] = {
    DATS,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/* Символ "0" */
uint8_t data_symbol_null[] = {
    DATS,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x00, 0x00
};

/* Символ "1" */
uint8_t data_symbol_one[] = {
    DATS,
    0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00
};

/* Символ "2" */
uint8_t data_symbol_two[] = {
    DATS,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xFC, 0xFC, 0xFC, 0xFC, 0x1F, 0x1F, 0x1F, 0x1F, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF1, 0xF1, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00
};

/* Символ "3" */
uint8_t data_symbol_three[] = {
    DATS,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x00, 0x00,
    0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x00, 0x00
};

/* Символ "4" */
uint8_t data_symbol_four[] = {
    DATS,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xE3, 0xE3, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00
};

/* Символ "5" */
uint8_t data_symbol_five[] = {
    DATS,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0x00, 0x00,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFE, 0xFE, 0xFE, 0xFE, 0x0F, 0x0F, 0x0F, 0x0F, 0x01, 0x01, 0x01, 0x00, 0x00
};

/* Символ "6" */
uint8_t data_symbol_six[] = {
    DATS,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x38, 0x38, 0x38, 0xF8, 0xF8, 0xF8, 0xF8, 0xC0, 0xC0, 0xC0, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x00, 0x00
};

/* Символ "7" */
uint8_t data_symbol_seven[] = {
    DATS,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x8F, 0x8F, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

/* Символ "8" */
uint8_t data_symbol_eight[] = {
    DATS,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xF8, 0xF8, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x1F, 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x00, 0x00
};

/* Символ "9" */
uint8_t data_symbol_nine[] = {
    DATS,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0x00, 0x03, 0x03, 0x03, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
};


HAL_StatusTypeDef HAL_SSD1306_Init(I2C_HandleTypeDef *hi2c, uint8_t brightness)
{   
    // for (volatile int i = 0; i < 1000; i++);
    uint8_t Set_MUX_Ratio, Set_COM_Pins;
    #ifdef SSD1306_128x64
    Set_MUX_Ratio = 0x3F;
    Set_COM_Pins = 0x12;
    #endif

    #ifdef SSD1306_128x32
    Set_MUX_Ratio = 0x1F;
    Set_COM_Pins = 0x02;
    #endif

    /* Массив для стандартной инициализации */
    uint8_t data_init[] = {
    COM, 0xA8, COM, Set_MUX_Ratio, // Set MUX Ratio // 0x3F - 128x64; 0x1F - 128x32
    COM, 0xD3, COM, 0x00, // Set Display Offset
    COM, 0x40, // Set Display Start Line
    COM, 0xA1, // Set Segment re-map 
    COM, 0xC8, // Set COM Output Scan Direction
    COM, 0xDA, COM, Set_COM_Pins,// Set COM Pins hardware configuration. 0x12 - 128x64; 0x02 - 128x32
    COM, 0x81, COM, brightness, // Set Contrast Control 
    COM, 0xA4, // Disable Entire Display On 
    COM, 0xA6, // Set Normal Display
    COM, 0xD5, COM, 0x80, // Set Osc Frequency
    COM, 0x8D,COM, 0x14, // Enable charge pump regulator
    COM, 0xAF // Display On
    };

    /* Oled_init - инициализация экрана в стандартном режиме */
    return HAL_I2C_Master_Transmit(hi2c, slave_address, data_init, sizeof(data_init), I2C_TIMEOUT_DEFAULT);
}

HAL_StatusTypeDef HAL_SSD1306_SetBorder(I2C_HandleTypeDef *hi2c, uint8_t start_col, uint8_t end_col, uint8_t start_page, uint8_t end_page)
{
    uint8_t data_SetBorder[] = {
        COM, 0x21, // установка адреса колонок
        COM, start_col, // номер стартовой колонки
        COM, end_col, // номер конечной колонки

        COM, 0x22, // установка адреса страницы
        COM, start_page, // номер стартовой страницы
        COM, end_page, // номер конечной страницы
    };

    /* set_border - установка границ вывода на дисплей */
    return HAL_I2C_Master_Transmit(hi2c, slave_address, data_SetBorder, sizeof(data_SetBorder), I2C_TIMEOUT_DEFAULT);
}

HAL_StatusTypeDef HAL_SSD1306_CLR_SCR(I2C_HandleTypeDef *hi2c)
{  
    uint8_t data_CLR_SCR[517] =   {COM, 0x20, COM, 0x00, // Horizontal Addressing Mode
                                    DATS};
    int counter = 5;
    for (int page = 0; page < 4; page++) 
    {
        for(int col = 0; col < 128; col++) 
        {
            data_CLR_SCR[counter] = (uint8_t)0;
            counter++;
        }
    }

    /* CLR_SCR - очищение всего экрана в горизонтальном режиме*/
    return HAL_I2C_Master_Transmit(hi2c, slave_address, data_CLR_SCR, sizeof(data_CLR_SCR), I2C_TIMEOUT_DEFAULT);

}

HAL_StatusTypeDef HAL_SSD1306_Write(I2C_HandleTypeDef *hi2c, uint8_t symbol)
{
    // for (volatile int i = 0; i < 1000; i++);
    HAL_StatusTypeDef error_code = HAL_OK;
    switch (symbol)
    {
    case 0:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_null, sizeof(data_symbol_null), I2C_TIMEOUT_DEFAULT);
        break;
    case 1:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_one, sizeof(data_symbol_one), I2C_TIMEOUT_DEFAULT);
        break;
    case 2:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_two, sizeof(data_symbol_two), I2C_TIMEOUT_DEFAULT);
        break;
    case 3:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_three, sizeof(data_symbol_three), I2C_TIMEOUT_DEFAULT);
        break;
    case 4:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_four, sizeof(data_symbol_four), I2C_TIMEOUT_DEFAULT);
        break;
    case 5:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_five, sizeof(data_symbol_five), I2C_TIMEOUT_DEFAULT);
        break;
    case 6:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_six, sizeof(data_symbol_six), I2C_TIMEOUT_DEFAULT);
        break;
    case 7:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_seven, sizeof(data_symbol_seven), I2C_TIMEOUT_DEFAULT);
        break;
    case 8:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_eight, sizeof(data_symbol_eight), I2C_TIMEOUT_DEFAULT);
        break;
    case 9:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_nine, sizeof(data_symbol_nine), I2C_TIMEOUT_DEFAULT);
        break;
    case SYMBOL_SMILE:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_smile, sizeof(data_symbol_smile), I2C_TIMEOUT_DEFAULT);
        break;
    default:
        error_code = HAL_I2C_Master_Transmit(hi2c, slave_address, data_symbol_colon, sizeof(data_symbol_colon), I2C_TIMEOUT_DEFAULT);
        break;
    }

    return error_code;

}