/*
 * utf8 ru
  *      Author: alexrayne <alexraynepe196@gmail.com>
  ------------------------------------------------------------------------
    Copyright (c) alexrayne

   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
   - Neither the name of ARM nor the names of its contributors may be used
     to endorse or promote products derived from this software without
     specific prior written permission.
   *
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. *
  ------------------------------------------------------------------------
 * MAX6954 driver API
 * MAX6954 is LCD driver for 16/8 symbols, bicolor,
 *        with keyboard scaner up to 32 keys
 *        with 5 PIN GPIO
 * */

#ifndef DRIVERS_HALMCU_DEV_MAX6954_H_
#define DRIVERS_HALMCU_DEV_MAX6954_H_

#include <stdbool.h>
#include <stdint.h>
#include <mcu_ssp.h>
#include <mcu_tim.h>
#include <mcu_gpio.h>



#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

// чстота OSC для залдания мелькания в 1сек
#define MAX6954_BLINK_SECOND_OSCHZ 4000000ul
#define MAX6954_BLINK_TOP_OSCHZ    8000000ul
#define MAX6954_BLINK_LOW_OSCHZ    1000000ul

// минимальное время удержания nCS
#define MAX6954_CS_HOLDNS 50


enum MAX6954_Def{
    // максимальная длтина строки 7сегментной
    MAX6954_LEN_7SEG = 16,
    // максимальная длтина строки 7сегментной 2цветного дисплея,
    //  с расширением цвета по разрядам А
    MAX6954_LEN_7SEG_BICOLORA     = 8,
    // максимальная длтина строки 7сегментной 2цветного дисплея,
    //  с расширением цвета парой соседних сегментов
    MAX6954_LEN_7SEG_BICOLOR_PAIR = 4,
};

enum MAX6954_Style{
    MAX6954_sLEN_Msk = 0xf ,
    MAX6954_ALL_DIGITS = 0, // задание максимальной допустимой длины строки

    // цветовая пара задается digitX+digitXA
    MAX6954_sCOLORED_A = 0x80 ,
    // цветовая пара задается digitX+digit(X+1)
    MAX6954_sCOLORED_PAIR = 0x80 ,
};



// device handle
struct MAX6954h{
    SSP_TypeDef*   io;
    GPIO_TypeDef*  io_cs;
    uint8_t cs_pin;

    // blink control.
    // таймер управляет скоростью мерцания исходя из:
    // 4Мгц == период 1сек == MAX6954_BLINK_TIME_SECOND
    TIM_TypeDef*    blink_tim;

    uint8_t digits;
    //в цветном режиме нужно дублировать знак в цветовые плоскости
    // @sa MAX6954_Style
    uint8_t color_mode;
    uint8_t gpio_mode;
    uint8_t gpio_out;
};
typedef struct MAX6954h MAX6954h;

void MAX6954_init(MAX6954h* io,
                SSP_TypeDef* spi,
                GPIO_TypeDef*  cs_port, unsigned cs_pin);
// активировать и настроить обмен с драйвером
void MAX6954_begin(MAX6954h* io);



//----------------------------------------------------------------
// сбрс драйвера
void MAX6954_reset(MAX6954h* io);

// @arg len - use MAX6954_Style.
bool MAX6954_set_digit_type_all_7segment(MAX6954h* io, unsigned len);



//----------------------------------------------------------------
enum MAX6954_IntensityValue{
    MAX6954_ivMAX   = -1,
    MAX6954_ivLIM   = 0xf,

    MAX6954_ivC1    = 0xf,
    MAX6954_ivC2    = 0xf0,
};
typedef uint_fast8_t MAX6954_IntensityValue;

inline
MAX6954_IntensityValue MAX6954_BiColorVal(
                          MAX6954_IntensityValue c1
                        , MAX6954_IntensityValue c2)
{
    return (c1&MAX6954_ivLIM) | ((c2&MAX6954_ivLIM)<<4);
}

struct MAX6954_IntensitySet {
    uint8_t seg[16];
};
typedef struct MAX6954_IntensitySet MAX6954_IntensitySet;

void MAX6954_enable_individual_segment_brightness(MAX6954h* io);
void MAX6954_control_intensity(MAX6954h* io, MAX6954_IntensitySet* x);

void MAX6954_enable_global_segment_brightness(MAX6954h* io);
void MAX6954_set_global_brightness(MAX6954h* io, int i);



//----------------------------------------------------------------
void MAX6954_turn_off_all_segments(MAX6954h* io);
//void MAX6954_all_segment_test(MAX6954h* io);



//----------------------------------------------------------------
void MAX6954_disable_decode_mode(MAX6954h* io);
void MAX6954_enable_decode_mode(MAX6954h* io);

void MAX6954_write_raw(MAX6954h* io, const char str[]);
// декодирует строку с hex-символами и -,.
void MAX6954_write_string(MAX6954h* io, const char str[]);
bool MAX6954_write_int(MAX6954h* io, long x);
bool MAX6954_write_float(MAX6954h* io, float x);


//----------------------------------------------------------------
void MAX6954_blink_disable(MAX6954h* io);
void MAX6954_blink_enable(MAX6954h* io);

// назначиь таймер OSC для плавного вправления сокростью моргания
void MAX6954_blink_assign(MAX6954h* io, TIM_TypeDef* tim);
void MAX6954_blink_rate_01s(MAX6954h* io, unsigned rate_01s);



//----------------------------------------------------------------
enum MAX6954_KeyMode{
    MAX6954_NOKEYS      = 0,
    MAX6954_1KEYLINE    = 1,
    MAX6954_2KEYLINE    = 2,
    MAX6954_3KEYLINE    = 3,
    MAX6954_4KEYLINE    = 4,

    MAX6954_KEYS_Msk    = 3,
};
typedef enum MAX6954_KeyMode MAX6954_KeyMode;

enum MAX6954_GPIO{
    MAX6954_P0 = 1,
    MAX6954_P1 = 2,
    MAX6954_P2 = 4,
    MAX6954_P3 = 8,
    MAX6954_P4 = 0x10,

    // устанавливается при наличии нажатия клавиатуры
    MAX6954_KEYSIRQ = MAX6954_P4,

    MAX6954_PIO_Msk = 0x1f,
};

enum MAX6954_GPIOMode{
    MAX6954_P0IN = MAX6954_P0,
    MAX6954_P1IN = MAX6954_P1,
    MAX6954_P2IN = MAX6954_P2,
    MAX6954_P3IN = MAX6954_P3,
    MAX6954_P4IN = MAX6954_P4,

    MAX6954_P0OUT = 0,
    MAX6954_P1OUT = 0,
    MAX6954_P2OUT = 0,
    MAX6954_P3OUT = 0,
    MAX6954_P4OUT = 0,
};
typedef uint_fast8_t MAX6954_PortMode;
typedef uint_fast8_t MAX6954_PortState;


// @arg mode -
void MAX6954_port_set_mode(MAX6954h* io, MAX6954_KeyMode keys, MAX6954_PortMode pins);

bool      MAX6954_is_some_keys(MAX6954h* io);
// как и MAX6954_is_some_keys проверяет прерывание кавиатуры
//  но начинает обмен с MAX6954_begin
bool      MAX6954_check_keys(MAX6954h* io);
uint32_t  MAX6954_keys_1line(MAX6954h* io);
uint32_t  MAX6954_keys_2line(MAX6954h* io);
uint32_t  MAX6954_keys_3line(MAX6954h* io);
uint32_t  MAX6954_keys_4line(MAX6954h* io);
// same as  MAX6954_keys_4line
uint32_t  MAX6954_keys(MAX6954h* io);

void MAX6954_gpio_set(MAX6954h* io, MAX6954_PortState );
MAX6954_PortState MAX6954_gpio(MAX6954h* io);




#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* DRIVERS_HALMCU_DEV_MAX6954_H_ */
