1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #include "s7816.h"
19 #include "dma.h"
20 #include "plic.h"
21
22 volatile unsigned int s7816_rst_pin;
23 volatile unsigned int s7816_vcc_pin;
24 volatile unsigned int s7816_rtx_pin;
25 volatile unsigned char s7816_clock;
26 volatile int s7816_rst_time; // us
27 volatile int s7816_atr_time; // us
28 /**
29 * @brief This function is used to set the s7816 clock.
30 * @param[in] div - set the divider of clock of 7816 module.
31 * @return none.
32 * @note system clk is 24MHZ
33 * 7816clk: 0x60-4Mhz 0x40-6Mhz 0x20-12Mhz
34 * baudrate: 0x60-10752 0x40-16194 0x20-32388
35 * the clk-pin is PA0 by default.
36 */
s7816_set_clk(unsigned char div)37 void s7816_set_clk(unsigned char div)
38 {
39 reg_7816_clk_div &= 0x0f;
40 reg_7816_clk_div |= (unsigned char)div;
41 }
42
43 /**
44 * @brief This function is used to set the rst-wait time of the s7816 module.
45 * @param[in] rst_time_us - set the s7816_rst_time.
46 * @param[in] atr_time_us - set the s7816_atr_time.
47 * @return none.
48 */
s7816_set_time(int rst_time_us,int atr_time_us)49 void s7816_set_time(int rst_time_us, int atr_time_us)
50 {
51 s7816_rst_time = rst_time_us;
52 s7816_atr_time = atr_time_us;
53 }
54 /**
55 * @brief This function is used to set the RST pin of s7816.
56 * @param[in] pin_7816_rst - the RST pin of s7816.
57 * @return none.
58 */
s7816_set_rst_pin(gpio_pin_e pin_7816_rst)59 void s7816_set_rst_pin(gpio_pin_e pin_7816_rst)
60 {
61 s7816_rst_pin = pin_7816_rst;
62 gpio_function_en(pin_7816_rst);
63 gpio_output_en(pin_7816_rst);
64 gpio_input_dis(pin_7816_rst);
65 gpio_set_low_level(pin_7816_rst);
66 }
67
68 /**
69 * @brief This function is used to set the VCC pin of s7816.
70 * @param[in] pin_7816_vcc - the VCC pin of s7816.
71 * @return none.
72 */
s7816_set_vcc_pin(gpio_pin_e pin_7816_vcc)73 void s7816_set_vcc_pin(gpio_pin_e pin_7816_vcc)
74 {
75 s7816_vcc_pin = pin_7816_vcc;
76 gpio_function_en(pin_7816_vcc);
77 gpio_output_en(pin_7816_vcc);
78 gpio_input_dis(pin_7816_vcc);
79 gpio_set_low_level(pin_7816_vcc);
80 }
81
82 /**
83 * @brief This function is used to initialize the s7816 module.
84 * @param[in] uart_num - UART0 or UART1.
85 * @param[in] clock - the clock of s7816.
86 * @param[in] f - the clock frequency regulator of s7816,372 by default.
87 * @param[in] d - the bitrate regulator of s7816,1 by default.
88 * @return none.
89 */
s7816_init(uart_num_e uart_num,s7816_clock_e clock,int f,int d)90 void s7816_init(uart_num_e uart_num, s7816_clock_e clock, int f, int d)
91 {
92 unsigned short div;
93 unsigned char bwpc;
94 s7816_clock = clock;
95 s7816_rst_time = 40000 / clock; // us
96 s7816_atr_time = 40000 / clock; // us
97
98 int baud = clock * 1000000 * d / f;
99 if (clock == S7816_4MHZ) {
100 s7816_set_clk(0x60);
101 } else if (clock == S7816_6MHZ) {
102 s7816_set_clk(0x40);
103 } else if (clock == S7816_12MHZ) {
104 s7816_set_clk(0x20);
105 }
106 uart_reset(uart_num);
107 uart_cal_div_and_bwpc(baud, 24 * 1000 * 1000, &div, &bwpc);
108 uart_init(uart_num, div, bwpc, UART_PARITY_EVEN,
109 UART_STOP_BIT_ONE); // 7816 protocol stipulate the parity bit should be even.
110 }
111
112 /**
113 * @brief This function is used to set all the pin of s7816 module.
114 * @param[in] rst_pin - the rst pin of s7816.
115 * @param[in] vcc_pin - the vcc pin of s7816.
116 * @param[in] clk_pin - the clk pin of s7816.
117 * @param[in] trx_pin - the trx pin of s7816.
118 * @return none.
119 */
s7816_set_pin(gpio_pin_e rst_pin,gpio_pin_e vcc_pin,s7816_clk_pin_e clk_pin,s7816_rtx_pin_e rtx_pin)120 void s7816_set_pin(gpio_pin_e rst_pin, gpio_pin_e vcc_pin, s7816_clk_pin_e clk_pin, s7816_rtx_pin_e rtx_pin)
121 {
122 s7816_set_rst_pin(rst_pin);
123 s7816_rst_pin = rst_pin;
124
125 s7816_set_vcc_pin(vcc_pin);
126 s7816_vcc_pin = vcc_pin;
127
128 reg_gpio_func_mux(clk_pin) = (reg_gpio_func_mux(clk_pin) & (~BIT_RNG(0, 1))) | BIT(0);
129 gpio_function_dis(clk_pin);
130
131 s7816_rtx_pin = rtx_pin; // if the trx function set to early,it may trigger interrupt by accident.
132 // so we set the function in coldreset.
133 }
134
135 /**
136 * @brief This function is used to active the IC card,set the trx pin and coldreset.
137 * @param[in] none.
138 * @return none.
139 */
s7816_coldreset(void)140 void s7816_coldreset(void)
141 {
142 gpio_set_high_level(s7816_vcc_pin);
143 delay_us(20); // wait for the vcc stable.
144 reg_7816_clk_div |= BIT(7); // enable the 7816 clk,the pin is A0.
145 delay_us(s7816_rst_time);
146 s7816_set_rtx_pin(s7816_rtx_pin); // uart tx/rx pin set,if the trx pin set before this place,it may
147 gpio_set_high_level(s7816_rst_pin); // the IC card will return the initial ATR.
148 delay_us(s7816_atr_time);
149 }
150
151 /**
152 * @brief This function is used to release the trigger.
153 * @param[in] none.
154 * @return none.
155 */
s7816_release_trig(void)156 void s7816_release_trig(void)
157 {
158 gpio_set_low_level(s7816_rst_pin);
159 reg_7816_clk_div &= (BIT(7) - 1);
160 gpio_set_low_level(s7816_vcc_pin);
161 }
162
163 /**
164 * @brief This function is used to warmreset.
165 * @param[in] none.
166 * @return none.
167 * @note the warmreset is required after the IC-CARD active.
168 */
s7816_warmreset(void)169 void s7816_warmreset(void)
170 {
171 gpio_set_low_level(s7816_rst_pin);
172 delay_us(s7816_rst_time);
173 gpio_set_high_level(s7816_rst_pin); // The IC card will return the initial ATR.
174 delay_us(s7816_atr_time);
175 }
176
177 /**
178 * @brief This function is used to warmreset.
179 * @param[in] uart_num - UART0 or UART1.
180 * @param[in] tx_data - the data need to send.
181 * return none.
182 */
s7816_send_byte(uart_num_e uart_num,unsigned char tx_data)183 void s7816_send_byte(uart_num_e uart_num, unsigned char tx_data)
184 {
185 uart_send_byte(uart_num, tx_data);
186 uart_rtx_pin_tx_trig(uart_num);
187 }
188