/*! \file gd32f3x0_tsi.c \brief tsi driver */ /* Copyright (C) 2017 GigaDevice 2017-06-06, V1.0.0, firmware for GD32F3x0 */ #include "gd32f3x0_tsi.h" /*! \brief reset TSI peripheral \param[in] none \param[out] none \retval none */ void tsi_deinit(void) { rcu_periph_reset_enable(RCU_TSIRST); rcu_periph_reset_disable(RCU_TSIRST); } /*! \brief initialize TSI plus prescaler,charge plus,transfer plus,max cycle number \param[in] prescaler: CTCLK clock division factor \arg TSI_CTCDIV_DIV1: fCTCLK = fHCLK \arg TSI_CTCDIV_DIV2: fCTCLK = fHCLK/2 \arg TSI_CTCDIV_DIV4: fCTCLK = fHCLK/4 \arg TSI_CTCDIV_DIV8: fCTCLK = fHCLK/8 \arg TSI_CTCDIV_DIV16: fCTCLK = fHCLK/16 \arg TSI_CTCDIV_DIV32: fCTCLK = fHCLK/32 \arg TSI_CTCDIV_DIV64: fCTCLK = fHCLK/64 \arg TSI_CTCDIV_DIV128: fCTCLK = fHCLK/128 \arg TSI_CTCDIV_DIV256: fCTCLK = fHCLK/256 \arg TSI_CTCDIV_DIV512: fCTCLK = fHCLK/512 \arg TSI_CTCDIV_DIV1024: fCTCLK = fHCLK/1024 \arg TSI_CTCDIV_DIV2048: fCTCLK = fHCLK/2048 \arg TSI_CTCDIV_DIV4096: fCTCLK = fHCLK/4096 \arg TSI_CTCDIV_DIV8192: fCTCLK = fHCLK/8192 \arg TSI_CTCDIV_DIV16384: fCTCLK = fHCLK/16384 \arg TSI_CTCDIV_DIV32768: fCTCLK = fHCLK/32768 \param[in] charge_duration: charge state duration time \arg TSI_CHARGE_1CTCLK(x=1..16): the duration time of charge state is x CTCLK \param[in] transfer_duration: charge transfer state duration time \arg TSI_TRANSFER_xCTCLK(x=1..16): the duration time of transfer state is x CTCLK \param[in] max_number: max cycle number \arg TSI_MAXNUM255: the max cycle number of a sequence is 255 \arg TSI_MAXNUM511: the max cycle number of a sequence is 511 \arg TSI_MAXNUM1023: the max cycle number of a sequence is 1023 \arg TSI_MAXNUM2047: the max cycle number of a sequence is 2047 \arg TSI_MAXNUM4095: the max cycle number of a sequence is 4095 \arg TSI_MAXNUM8191: the max cycle number of a sequence is 8191 \arg TSI_MAXNUM16383: the max cycle number of a sequence is 16383 \param[out] none \retval none */ void tsi_init(uint32_t prescaler,uint32_t charge_duration,uint32_t transfer_duration,uint32_t max_number) { uint32_t ctl0,ctl1; if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ if(TSI_CTCDIV_DIV256 > prescaler){ /* config TSI_CTL0 */ ctl0 = TSI_CTL0; /*configure TSI clock division factor,charge state duration time,charge transfer state duration time */ ctl0 &= ~(TSI_CTL0_CTCDIV|TSI_CTL0_CTDT|TSI_CTL0_CDT|TSI_CTL0_MCN); ctl0 |= ((prescaler<<12U)|charge_duration|transfer_duration|max_number); TSI_CTL0 = ctl0; /* config TSI_CTL1 */ ctl1 = TSI_CTL1; ctl1 &= ~TSI_CTL1_CTCDIV; TSI_CTL1 = ctl1; }else{ /* config TSI_CTL0 */ ctl0 = TSI_CTL0; prescaler &= ~0x08U; /*configure TSI clock division factor,charge state duration time,charge transfer state duration time */ ctl0 &= ~(TSI_CTL0_CTCDIV|TSI_CTL0_CTDT|TSI_CTL0_CDT|TSI_CTL0_MCN); ctl0 |= ((prescaler<<12U)|charge_duration|transfer_duration|max_number); TSI_CTL0 = ctl0; /* config TSI_CTL1 */ ctl1 = TSI_CTL1; ctl1 |= TSI_CTL1_CTCDIV; TSI_CTL1 = ctl1; } } } /*! \brief enable sample pin \param[in] sample: sample pin \arg TSI_SAMPCFG_GxPy( x=0..5,y=0..3):pin y of group x is sample pin \param[out] none \retval none */ void tsi_sample_pin_enable(uint32_t sample) { if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ TSI_SAMPCFG |= sample; } } /*! \brief disable sample pin \param[in] sample: sample pin \arg TSI_SAMPCFG_GxPy( x=0..5,y=0..3): pin y of group x is sample pin \param[out] none \retval none */ void tsi_sample_pin_disable(uint32_t sample) { if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ TSI_SAMPCFG &= ~sample; } } /*! \brief enable channel pin \param[in] channel: channel pin \arg TSI_CHCFG_GxPy( x=0..5,y=0..3): pin y of group x \param[out] none \retval none */ void tsi_channel_pin_enable(uint32_t channel) { TSI_CHCFG |= channel; } /*! \brief disable channel pin \param[in] channel: channel pin \arg TSI_CHCFG_GxPy( x=0..5,y=0..3): pin y of group x \param[out] none \retval none */ void tsi_channel_pin_disable(uint32_t channel) { TSI_CHCFG &= ~channel; } /*! \brief configure charge plus and transfer plus \param[in] prescaler: CTCLK clock division factor \arg TSI_CTCDIV_DIV1: fCTCLK = fHCLK \arg TSI_CTCDIV_DIV2: fCTCLK = fHCLK/2 \arg TSI_CTCDIV_DIV4: fCTCLK = fHCLK/4 \arg TSI_CTCDIV_DIV8: fCTCLK = fHCLK/8 \arg TSI_CTCDIV_DIV16: fCTCLK = fHCLK/16 \arg TSI_CTCDIV_DIV32: fCTCLK = fHCLK/32 \arg TSI_CTCDIV_DIV64: fCTCLK = fHCLK/64 \arg TSI_CTCDIV_DIV128: fCTCLK = fHCLK/128 \arg TSI_CTCDIV_DIV256: fCTCLK = fHCLK/256 \arg TSI_CTCDIV_DIV512: fCTCLK = fHCLK/512 \arg TSI_CTCDIV_DIV1024: fCTCLK = fHCLK/1024 \arg TSI_CTCDIV_DIV2048: fCTCLK = fHCLK/2048 \arg TSI_CTCDIV_DIV4096: fCTCLK = fHCLK/4096 \arg TSI_CTCDIV_DIV8192: fCTCLK = fHCLK/8192 \arg TSI_CTCDIV_DIV16384: fCTCLK = fHCLK/16384 \arg TSI_CTCDIV_DIV32768: fCTCLK = fHCLK/32768 \param[in] charge_duration: charge state duration time \arg TSI_CHARGE_xCTCLK(x=1..16): the duration time of charge state is x CTCLK \param[in] transfer_duration: charge transfer state duration time \arg TSI_TRANSFER_xCTCLK(x=1..16): the duration time of transfer state is x CTCLK \param[out] none \retval none */ void tsi_plus_config(uint32_t prescaler,uint32_t charge_duration,uint32_t transfer_duration) { uint32_t ctl0,ctl1; if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ if(TSI_CTCDIV_DIV256 > prescaler){ /* config TSI_CTL0 */ ctl0 = TSI_CTL0; /*configure TSI clock division factor,charge state duration time,charge transfer state duration time */ ctl0 &= ~(TSI_CTL0_CTCDIV|TSI_CTL0_CTDT|TSI_CTL0_CDT); ctl0 |= ((prescaler<<12U)|charge_duration|transfer_duration); TSI_CTL0 = ctl0; /* config TSI_CTL1 */ ctl1 = TSI_CTL1; ctl1 &= ~TSI_CTL1_CTCDIV; TSI_CTL1 = ctl1; }else{ /* config TSI_CTL */ ctl0 = TSI_CTL0; prescaler &= ~0x08U; /*configure TSI clock division factor,charge state duration time,charge transfer state duration time */ ctl0 &= ~(TSI_CTL0_CTCDIV|TSI_CTL0_CTDT|TSI_CTL0_CDT); ctl0 |= ((prescaler<<12U)|charge_duration|transfer_duration); TSI_CTL0 = ctl0; /* config TSI_CTL2 */ ctl1 = TSI_CTL1; ctl1 |= TSI_CTL1_CTCDIV; TSI_CTL1 = ctl1; } } } /*! \brief configure TSI triggering by software \param[in] none \param[out] none \retval none */ void tsi_sofeware_mode_config(void) { if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ TSI_CTL0 &= ~TSI_CTL0_TRGMOD; } } /*! \brief configure TSI triggering by hardware \param[in] trigger_edge: the edge type in hardware trigger mode \arg TSI_FALLING_TRIGGER: falling edge trigger TSI charge transfer sequence \arg TSI_RISING_TRIGGER: rising edge trigger TSI charge transfer sequence \param[out] none \retval none */ void tsi_hardware_mode_config(uint8_t trigger_edge) { if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ /*enable hardware mode*/ TSI_CTL0 |= TSI_CTL0_TRGMOD; /*configure the edge type in hardware trigger mode*/ if(TSI_FALLING_TRIGGER == trigger_edge){ TSI_CTL0 &= ~TSI_CTL0_EGSEL; }else{ TSI_CTL0 |= TSI_CTL0_EGSEL; } } } /*! \brief configure TSI pin mode when charge-transfer sequence is IDLE \param[in] pin_mode: pin mode when charge-transfer sequence is IDLE \arg TSI_OUTPUT_LOW: TSI pin will output low when IDLE \arg TSI_INPUT_FLOATING: TSI pin will keep input_floating when IDLE \param[out] none \retval none */ void tsi_pin_mode_config(uint8_t pin_mode) { if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ if(TSI_OUTPUT_LOW == pin_mode){ TSI_CTL0 &= ~TSI_CTL0_PINMOD; }else{ TSI_CTL0 |= TSI_CTL0_PINMOD; } } } /*! \brief configure the max cycle number of a charge-transfer sequence \param[in] max_number: max cycle number \arg TSI_MAXNUM255: the max cycle number of a sequence is 255 \arg TSI_MAXNUM511: the max cycle number of a sequence is 511 \arg TSI_MAXNUM1023: the max cycle number of a sequence is 1023 \arg TSI_MAXNUM2047: the max cycle number of a sequence is 2047 \arg TSI_MAXNUM4095: the max cycle number of a sequence is 4095 \arg TSI_MAXNUM8191: the max cycle number of a sequence is 8191 \arg TSI_MAXNUM16383: the max cycle number of a sequence is 16383 \param[out] none \retval none */ void tsi_max_number_config(uint32_t max_number) { if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ uint32_t maxnum; maxnum = TSI_CTL0; /*configure the max cycle number of a charge-transfer sequence*/ maxnum &= ~TSI_CTL0_MCN; maxnum |= max_number; TSI_CTL0 = maxnum; } } /*! \brief start a charge-transfer sequence when TSI is in software trigger mode \param[in] none \param[out] none \retval none */ void tsi_software_start(void) { TSI_CTL0 |= TSI_CTL0_TSIS; } /*! \brief stop a charge-transfer sequence when TSI is in software trigger mode \param[in] none \param[out] none \retval none */ void tsi_software_stop(void) { TSI_CTL0 &= ~TSI_CTL0_TSIS; } /*! \brief enable TSI module \param[in] none \param[out] none \retval none */ void tsi_enable(void) { TSI_CTL0 |= TSI_CTL0_TSIEN; } /*! \brief disable TSI module \param[in] none \param[out] none \retval none */ void tsi_disable(void) { TSI_CTL0 &= ~TSI_CTL0_TSIEN; } /*! \brief configure extend charge state \param[in] extend: enable or disable extend charge state \arg ENABLE: enable extend charge state \arg DISABLE: disable extend charge state \param[in] prescaler: ECCLK clock division factor \arg TSI_EXTEND_DIV1: fECCLK = fHCLK \arg TSI_EXTEND_DIV2: fECCLK = fHCLK/2 \arg TSI_EXTEND_DIV3: fECCLK = fHCLK/3 \arg TSI_EXTEND_DIV4: fECCLK = fHCLK/4 \arg TSI_EXTEND_DIV5: fECCLK = fHCLK/5 \arg TSI_EXTEND_DIV6: fECCLK = fHCLK/6 \arg TSI_EXTEND_DIV7: fECCLK = fHCLK/7 \arg TSI_EXTEND_DIV8: fECCLK = fHCLK/8 \param[in] max_duration: value range 1...128,extend charge state maximum duration time is 1*tECCLK~128*tECCLK \param[out] none \retval none */ void tsi_extend_charge_config(ControlStatus extend,uint8_t prescaler,uint32_t max_duration) { uint32_t ctl0,ctl1; if(RESET == (TSI_CTL0 & TSI_CTL0_TSIS)){ if(DISABLE == extend){ /*disable extend charge state*/ TSI_CTL0 &= ~TSI_CTL0_ECEN; }else{ if(TSI_EXTEND_DIV3 > prescaler){ /*configure extend charge state maximum duration time*/ ctl0 = TSI_CTL0; ctl0 &= ~TSI_CTL0_ECDT; ctl0 |= TSI_EXTENDMAX((max_duration-1U)); TSI_CTL0 = ctl0; /*configure ECCLK clock division factor*/ ctl0 = TSI_CTL0; ctl0 &= ~TSI_CTL0_ECDIV; ctl0 |= (uint32_t)prescaler<<15U; TSI_CTL0 = ctl0; /*enable extend charge state*/ TSI_CTL0 |= TSI_CTL0_ECEN; }else{ /*configure extend charge state maximum duration time*/ ctl0 = TSI_CTL0; ctl0 &= ~TSI_CTL0_ECDT; ctl0 |= TSI_EXTENDMAX((max_duration-1U)); TSI_CTL0 = ctl0; /*configure ECCLK clock division factor*/ ctl0 = TSI_CTL0; ctl0 &= ~TSI_CTL0_ECDIV; ctl0 |= (prescaler & 0x01U)<<15U; TSI_CTL0 = ctl0; ctl1 = TSI_CTL1; ctl1 &= ~TSI_CTL1_ECDIV; ctl1 |= (prescaler & 0x06U)<<28U; TSI_CTL1 = ctl1; /*enable extend charge state*/ TSI_CTL0 |= TSI_CTL0_ECEN; } } } } /*! \brief enable TSI interrupt \param[in] source: select interrupt which will be enabled \arg TSI_INT_CCTCF: charge-transfer complete flag interrupt enable \arg TSI_INT_MNERR: max cycle number error interrupt enable \param[out] none \retval none */ void tsi_interrupt_enable(uint32_t source) { TSI_INTEN |= source; } /*! \brief disable TSI interrupt \param[in] source: select interrupt which will be disabled \arg TSI_INT_CCTCF: charge-transfer complete flag interrupt disable \arg TSI_INT_MNERR: max cycle number error interrupt disable \param[out] none \retval none */ void tsi_interrupt_disable(uint32_t source) { TSI_INTEN &= ~source; } /*! \brief clear TSI interrupt flag \param[in] source: select flag which will be cleared \arg TSI_INT_FLAG_CTCF_CLR: clear charge-transfer complete flag \arg TSI_INT_FLAG_MNERR_CLR: clear max cycle number error \param[out] none \retval none */ void tsi_interrupt_flag_clear(uint32_t flag) { TSI_INTC |= flag; } /*! \brief get TSI interrupt flag \param[in] status: \arg TSI_INT_FLAG_CTCF: charge-transfer complete flag \arg TSI_INT_FLAG_MNERR: max Cycle Number Error \param[out] none \retval FlagStatus:SET or RESET */ FlagStatus tsi_interrupt_flag_get(uint32_t flag) { FlagStatus flag_status; uint32_t tsi_inten; tsi_inten = TSI_INTEN; if(TSI_INT_FLAG_CTCF == flag){ if(TSI_INT_CCTCF & tsi_inten){ if(TSI_INTF & flag){ flag_status = SET; }else{ flag_status = RESET; } }else{ flag_status = RESET; } }else if(TSI_INT_FLAG_MNERR == flag){ if(TSI_INT_MNERR & tsi_inten){ if(TSI_INTF & flag){ flag_status = SET; }else{ flag_status = RESET; } }else{ flag_status = RESET; } }else{ flag_status = RESET; } return flag_status; } /*! \brief clear flag \param[in] source: select flag which will be cleared \arg TSI_FLAG_CTCF_CLR: clear charge-transfer complete flag \arg TSI_FLAG_MNERR_CLR: clear max cycle number error \param[out] none \retval none */ void tsi_flag_clear(uint32_t flag) { TSI_INTC |= flag; } /*! \brief get flag \param[in] status: \arg TSI_FLAG_CTCF: charge-transfer complete flag \arg TSI_FLAG_MNERR: max Cycle Number Error \param[out] none \retval FlagStatus:SET or RESET */ FlagStatus tsi_flag_get(uint32_t flag) { FlagStatus flag_status; if(TSI_INTF & flag){ flag_status = SET; }else{ flag_status = RESET; } return flag_status; } /*! \brief switch on hysteresis pin \param[in] group_pin: select pin which will be switched on hysteresis \arg TSI_PHM_GxPy(x=0..5,y=0..3): pin y of group x switch on hysteresis \param[out] none \retval none */ void tsi_hysteresis_on(uint32_t group_pin) { TSI_PHM |= group_pin; } /*! \brief switch off hysteresis pin \param[in] group_pin: select pin which will be switched off hysteresis \arg TSI_PHM_GxPy(x=0..5,y=0..3): pin y of group x switch off hysteresis \param[out] none \retval none */ void tsi_hysteresis_off(uint32_t group_pin) { TSI_PHM &= ~group_pin; } /*! \brief switch on analog pin \param[in] group_pin: select pin which will be switched on analog \arg TSI_ASW_GxPy(x=0..5,y=0..3):pin y of group x switch on analog \param[out] none \retval none */ void tsi_analog_on(uint32_t group_pin) { TSI_ASW |= group_pin; } /*! \brief switch off analog pin \param[in] group_pin: select pin which will be switched off analog \arg TSI_ASW_GxPy(x=0..5,y=0..3):pin y of group x switch off analog \param[out] none \retval none */ void tsi_analog_off(uint32_t group_pin) { TSI_ASW &= ~group_pin; } /*! \brief enbale group \param[in] group: select group to be enabled \arg TSI_GCTL_GEx(x=0..5): the x group will be enabled \param[out] none \retval none */ void tsi_group_enable(uint32_t group) { TSI_GCTL |= group; } /*! \brief disbale group \param[in] group: select group to be disabled \arg TSI_GCTL_GEx(x=0..5):the x group will be disabled \param[out] none \retval none */ void tsi_group_disable(uint32_t group) { TSI_GCTL &= ~group; } /*! \brief get group complete status \param[in] group: select group \arg TSI_GCTL_GCx(x=0..5): get the complete status of group x \param[out] none \retval FlagStatus: group complete status,SET or RESET */ FlagStatus tsi_group_status_get(uint32_t group) { FlagStatus flag_status; if(TSI_GCTL & group){ flag_status = SET; }else{ flag_status = RESET; } return flag_status; } /*! \brief get the cycle number for group0 as soon as a charge-transfer sequence completes \param[in] none \param[out] none \retval group0 cycle number */ uint16_t tsi_group0_cycle_get(void) { return (uint16_t)TSI_G0CYCN; } /*! \brief get the cycle number for group1 as soon as a charge-transfer sequence completes \param[in] none \param[out] none \retval group1 cycle number */ uint16_t tsi_group1_cycle_get(void) { return (uint16_t)TSI_G1CYCN; } /*! \brief get the cycle number for group2 as soon as a charge-transfer sequence completes \param[in] none \param[out] none \retval group2 cycle number */ uint16_t tsi_group2_cycle_get(void) { return (uint16_t)TSI_G2CYCN; } /*! \brief get the cycle number for group3 as soon as a charge-transfer sequence completes \param[in] none \param[out] none \retval group3 cycle number */ uint16_t tsi_group3_cycle_get(void) { return (uint16_t)TSI_G3CYCN; } /*! \brief get the cycle number for group4 as soon as a charge-transfer sequence completes \param[in] none \param[out] none \retval group4 cycle number */ uint16_t tsi_group4_cycle_get(void) { return (uint16_t)TSI_G4CYCN; } /*! \brief get the cycle number for group5 as soon as a charge-transfer sequence completes \param[in] none \param[out] none \retval group5 cycle number */ uint16_t tsi_group5_cycle_get(void) { return (uint16_t)TSI_G5CYCN; }