

/**
 * @brief Скорость последовательного порта 
 */


TYPE hsal_serial_baudrate_e: DWORD
(
	BAUDRATE_300    := 300,
    BAUDRATE_600    := 600,
    BAUDRATE_1200   := 1200,
    BAUDRATE_2400   := 2400,
    BAUDRATE_4800   := 4800,
    BAUDRATE_9600   := 9600,
    BAUDRATE_14400  := 14400,
    BAUDRATE_19200  := 19200,
    BAUDRATE_38400  := 38400,
    BAUDRATE_57600  := 57600,
    BAUDRATE_115200 := 115200,
    BAUDRATE_230400 := 230400,
    BAUDRATE_460800 := 460800,
    BAUDRATE_500000 := 500000,
    BAUDRATE_921600 := 921600
);
END_TYPE

/**
 * @brief Управление DTR 
 */

TYPE hsal_serial_dtr_ctrl_e: DWORD
(
	DTR_DISABLE := 0,
    DTR_ENABLE,
    DTR_HANDSHAKE
);
END_TYPE

/**
 * @brief Контроль четности
 */

TYPE hsal_serial_parity_e: DWORD
(
	NOPARITY := 0,
    ODDPARITY,
    EVENPARITY
);
END_TYPE

/**
 * @brief Номер последовательного порта в системе 
 */

TYPE hsal_serial_ports_e: DINT
(
	PORT_NONE := -1,
    PORT_1 := 1, 
    PORT_2,
    PORT_3,
    PORT_4,
    PORT_5,
    PORT_6,
    PORT_7,
    PORT_8
);
END_TYPE

/**
 * @brief Управление RTS
 */

TYPE hsal_serial_rts_ctrl_e: DWORD
(
	RTS_DISABLE := 0,
    RTS_ENABLE,
    RTS_HANDSHAKE,
    RTS_TOGGLE
);
END_TYPE

/**
 * @brief Количество стоп-бит
 */

TYPE hsal_serial_stopbits_e: DWORD
(
    STOPBIT_1 := 1,  ///< 1 стоп-бит
    STOPBIT_1_5,    ///< 1,5 стоп-бита
    STOPBIT_2       ///< 2 стоп-бита
);
END_TYPE

/**
 * @brief Стандартные значения таймаутов
 */

TYPE hsal_serial_timeout_e : DWORD
(
    TIMEOUT_NO_WAIT := 0,        ///< нулевой таймаут
    TIMEOUT_INF := 16#FFFFFFFF    ///< Бесконечный таймаут (блок)
);
END_TYPE

/**
 * @brief Структура стандартных настроек последовательного порта  
 */

TYPE hsal_serial_settings:
STRUCT
	port		: hsal_serial_ports_e;               ///< номер порта в системе
    stopbits	: hsal_serial_stopbits_e;        ///< кол-во стопбит
    parity		: hsal_serial_parity_e;            ///< настройки четности
    baudrate	: hsal_serial_baudrate_e;        ///< скорость обмена 
    timeout_ms	: hsal_serial_timeout_e;       ///< межсимвольный таймаут приема/передачи
    fifo_buf_size: DWORD;                 ///< размер приемного буфера 
END_STRUCT
END_TYPE

/**
 * @brief Структура расширенных настроек последовательного порта 
 */


TYPE hsal_serial_ex_settings:
STRUCT
	byte_size		: BYTE;                      ///< размер байта, 4-8 бит                // c_cflag::CSIZE
    binary_mode		: BOOL;                       ///< вкл/выкл канонический режим          // c_lflag::ICANON 
    outx_cts_flow	: BOOL;                     ///< CTS handshake on output              // c_cflag::CRTSCTS
    outx_dsr_flow	: BOOL;                     ///< DSR handshake on output              // поддерживается не на всех платформах, нет явной настройки в POSIX
    dtr_control		: hsal_serial_dtr_ctrl_e;     ///< DTR flow control                     // поддерживается не на всех платформах, нет явной настройки в POSIX
    dsr_sensitivity	: BOOL;                   ///<                                      // ???
    rts_ctrl		: hsal_serial_rts_ctrl_e;        ///< RTS flow control                     // c_cflag::CRTSCTS
    tx_continue_on_off: BOOL;                ///< XOFF continues TX                    // ???
    outX			: BOOL;                              ///< XON/XOFF out flow control            // c_iflag::IXON
    inX				: BOOL;                               ///< XON/XOFF in flow control             // c_iflag::IXOFF
    xon_char		: BYTE;                       ///< TX and RX XON character              // c_cc::VSTART
    xoff_char		: BYTE;                      ///< TX and RX XOFF character             // c_cc::VSTOP
    xon_lim			: DWORD;                       ///< transmit XON threshold               // ???
    xoff_lim		: DWORD;                      ///< transmit XOFF threshold              // ???
END_STRUCT
END_TYPE



@EXTERNAL FUNCTION typedef_HSAL_Serial_open: DINT
VAR_INPUT 
	serial    	:REF_TO HSAL_Serial;
	port		:hsal_serial_ports_e;
END_VAR
END_FUNCTION


@EXTERNAL FUNCTION typedef_HSAL_Serial_open_with_config: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
	config		:REF_TO hsal_serial_settings;
	ex_config	:REF_TO hsal_serial_ex_settings;
END_VAR
END_FUNCTION


@EXTERNAL FUNCTION typedef_HSAL_Serial_configure: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
	config		:REF_TO hsal_serial_settings;
	ex_config	:REF_TO hsal_serial_ex_settings;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_get_config: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
	config		:REF_TO hsal_serial_settings;
	ex_config	:REF_TO hsal_serial_ex_settings;
END_VAR
END_FUNCTION


@EXTERNAL FUNCTION typedef_HSAL_Serial_set_timeout_ms: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
	timeout_ms	:DWORD;
END_VAR
END_FUNCTION


@EXTERNAL FUNCTION typedef_HSAL_Serial_write: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
	buf			:REF_TO BYTE;
	size_t		:size_t;
	timeout_ms	:DWORD;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_read: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
	buf			:REF_TO BYTE;
	size_t		:size_t;
	timeout_ms	:DWORD;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_purge: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_close: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_acquire: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_release: DINT
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_is_open: BOOL
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_HSAL_Serial_reset: BOOL
VAR_INPUT 
	serial  	:REF_TO HSAL_Serial;
END_VAR
END_FUNCTION



TYPE hsal_serial_id:uintptr_t; END_TYPE  // тип для хранения нативного ID или указателя на структуру COM-порта

/**
 * Общий интерфейс компонента Последовательный порт  
 */
TYPE HSAL_Serial:
STRUCT
    /**
     * @brief Открыть последовательный порт (с настройками по умолчанию)
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] port Номер порта в системе
     * @return 0 в случае успеха, <0 - ошибка
     * @note Тред, открывший порт, автоматически становится его первым владельцем
     */
    open : REF_TO typedef_HSAL_Serial_open;
    /**
     * @brief Открыть последовательный порт с заданными настройками
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] config Структура стандартных настроек
     * @param [in] ex_config Структура расширенных настроек
     * @return 0 в случае успеха, <0 - ошибка
     * @note Тред, открывший порт, автоматически становится его первым владельцем
     */
    open_with_config : REF_TO typedef_HSAL_Serial_open_with_config;
    /**
     * @brief Сконфигурировать уже открытый последовательный порт 
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] config Структура стандартных настроек
     * @param [in] ex_config Структура расширенных настроек
     * @return 0 в случае успеха, <0 - ошибка
     */
    configure : REF_TO typedef_HSAL_Serial_configure;
    /**
     * @brief Получить конфигурацию открытого последовательного порта 
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] config Структура стандартных настроек
     * @param [in] ex_config Структура расширенных настроек
     * @return 0 в случае успеха, <0 - ошибка
     */
    get_config : REF_TO typedef_HSAL_Serial_get_config;
    /**
     * @brief Установить межсимвольный таймаут для последовательного порта 
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] timeout_ms Значение межсимвольного таймаута в милисекундах
     * @return 0 в случае успеха, <0 - ошибка
     */
    set_timeout_ms : REF_TO typedef_HSAL_Serial_set_timeout_ms;
    /**
     * @brief Записать данные в последовательный порт 
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] buf Исходный буфер с данными
     * @param [in] size Размер исходных данных, байт
     * @param [in] timeout Таймаут блокировки в мс 
     * @return <:= 0 кол-во реально записанных данных, <0 - код ошибки
     * @note Функция пишет данные до истечения заданного таймаута и может записать меньше запрошенного, если он истек
     */
    write : REF_TO typedef_HSAL_Serial_write;
    /**
     * @brief Прочитать данные из последовательного порта 
     * @param [in] serial Дескриптор последовательного порта
     * @param [in] buf Буфер для чтения данных
     * @param [in] size Размер исходных данных, байт
     * @param [in] timeout Таймаут ожидания данных в мс 
     * @return  <:= 0 - кол-во реально прочитанных байт, < 0 - код ошибки
     * @note Функция читает данные до истечения заданного таймаута и может вернуть меньше запрошенного, если он истек
     */
    read : REF_TO typedef_HSAL_Serial_read;
    /**
     * @brief Очистить входной и выходной буферы последовательного порта
     * @param [in] serial Дескриптор последовательного порта
     * @return 0 в случае успеха, <0 - ошибка
     */
    purge : REF_TO typedef_HSAL_Serial_purge;
    /**
     * @brief Закрыть последовательный порт 
     * @param [in] serial Дескриптор последовательного порта 
     * @return 0 в случае успеха, <0 - ошибка
     */
    close : REF_TO typedef_HSAL_Serial_close;
    /**
     * @brief Захватить дескриптор открытого последовательного порта 
     * @param [in] serial Дескриптор последовательного порта
     * @return 0 в случае успеха, <0 - ошибка
     */
    acquire : REF_TO typedef_HSAL_Serial_acquire;
    /**
     * @brief Освободить дескриптор открытого последовательного порта 
     * @param [in] serial Дескриптор последовательного порта
     * @return 0 в случае успеха, <0 - ошибка
     */
    release : REF_TO typedef_HSAL_Serial_release;
    /**
     * @brief Проверить, открыт ли порт  
     * @param [in] serial Дескриптор последовательного порта
     * @return true - порт открыт, false - порт закрыт 
     */
    is_open : REF_TO typedef_HSAL_Serial_is_open;

    /**
     * @brief Сбросить внутреннее состояние порта  
     * @param [in] serial Дескриптор последовательного порта */

    reset : REF_TO typedef_HSAL_Serial_reset;

    
    /* данные для ознакомления
    settings	: hsal_serial_settings;          // основные настройки порта (для быстрого доступа) 
    id			: REF_TO VOID;                      // нативный для конкретной платформы id
    owner		: REF_TO VOID;                   // тред, занявший порт (-1, если свободен) 
    is_opened	: BOOL;                         // открыт ли порт 
    args		: REF_TO VOID;                             // для возможности расширения в реализациях */
END_STRUCT
END_TYPE

/**
 * @brief Получить указатель на последовательный порт 
 * @param [in] port Номер последовательного порта в системе
 * @return Указатель на последовательный порт, NULL  в случае критической ошибки  и неработоспособности компонента целиком 
 * 
 * @note Первичное обращение к последовательному порту через эту функцию. 
 * Порты существуют в системе статически, отдельные конструкторы не предусмотрены
*/

@EXTERNAL FUNCTION hsal_serial_get: REF_TO HSAL_Serial
VAR_INPUT
    port: hsal_serial_ports_e; 
END_VAR
END_FUNCTION


