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 
19 /********************************************************************************************************
20  * @file	s7816.c
21  *
22  * @brief	This is the source file for B91
23  *
24  * @author	Driver Group
25  *
26  *******************************************************************************************************/
27 #include "s7816.h"
28 #include "dma.h"
29 #include "plic.h"
30 
31 volatile unsigned int  s7816_rst_pin;
32 volatile unsigned int  s7816_vcc_pin;
33 volatile unsigned int  s7816_rtx_pin;
34 volatile unsigned char s7816_clock;
35 volatile int s7816_rst_time;//us
36 /**
37  * @brief      	This function is used to set the s7816 clock.
38  * @param[in]  	div	- set the divider of clock of 7816 module.
39  * @return     	none.
40  * @note        the clk-source of s7816 is 24M-pad,the clk of clk-pin can be divided as follow.
41  * 				div:        0x60-4Mhz     0x40-6Mhz   0x20-12Mhz
42  * 				baudrate:   0x60-10752    0x40-16194  0x20-32388
43  */
s7816_set_clk(unsigned char div)44 void s7816_set_clk(unsigned char div)
45 {
46 	reg_7816_clk_div&=0x0f;
47 	reg_7816_clk_div|=(unsigned char)div;
48 }
49 
50 /**
51  * @brief      	This function is used to set the rst-wait time of the s7816 module.
52  * @param[in]  	rst_time_us - set the s7816_rst_time.
53  * @return     	none.
54  */
s7816_set_time(int rst_time_us)55 void s7816_set_time(int rst_time_us)
56 {
57 	s7816_rst_time=rst_time_us;
58 }
59 /**
60  * @brief      	This function is used to set the RST pin of s7816.
61  * @param[in]  	pin_7816_rst - the RST pin of s7816.
62  * @return     	none.
63  */
s7816_set_rst_pin(gpio_pin_e pin_7816_rst)64 void s7816_set_rst_pin(gpio_pin_e pin_7816_rst)
65 {
66 	s7816_rst_pin=pin_7816_rst;
67 	gpio_function_en(pin_7816_rst);
68 	gpio_output_en(pin_7816_rst);
69 	gpio_input_dis(pin_7816_rst);
70 	gpio_set_low_level(pin_7816_rst);
71 }
72 
73 /**
74  * @brief      	This function is used to set the VCC pin of s7816.
75  * @param[in]   pin_7816_vcc - the VCC pin of s7816.
76  * @return     	none.
77  */
s7816_set_vcc_pin(gpio_pin_e pin_7816_vcc)78 void s7816_set_vcc_pin(gpio_pin_e pin_7816_vcc)
79 {
80 	s7816_vcc_pin=pin_7816_vcc;
81 	gpio_function_en(pin_7816_vcc);
82 	gpio_output_en(pin_7816_vcc);
83 	gpio_input_dis(pin_7816_vcc);
84 	gpio_set_low_level(pin_7816_vcc);
85 }
86 
87 /**
88  * @brief      	This function is used to initialize the s7816 module.
89  * @param[in]  	uart_num     - UART0 or UART1.
90  * @param[in]  	clock        - the clock of s7816.
91  * @param[in]  	f            - the clock frequency regulator of s7816,372 by default.
92  * @param[in]  	d            - the bitrate regulator of s7816,1 by default.
93  * @return     	none.
94  */
s7816_init(uart_num_e uart_num,s7816_clock_e clock,int f,int d)95 void s7816_init(uart_num_e uart_num,s7816_clock_e clock,int f,int d)
96 {
97 	unsigned short div;
98 	unsigned char bwpc;
99 	s7816_clock=clock;
100 	s7816_rst_time=40000/clock;//us
101 
102 	int baud=clock*1000000*d/f;
103 	if(clock==S7816_4MHZ)
104 	{
105 		s7816_set_clk(0x60);
106 	}
107 	else if(clock==S7816_6MHZ)
108 	{
109 		s7816_set_clk(0x40);
110 	}
111 	else if(clock==S7816_12MHZ)
112 	{
113 		s7816_set_clk(0x20);
114 	}
115 	uart_reset(uart_num);
116 	uart_cal_div_and_bwpc(baud, 24*1000*1000, &div, &bwpc);
117 	uart_init(uart_num, div, bwpc, UART_PARITY_EVEN, UART_STOP_BIT_ONE);//7816 protocol stipulate the parity bit should be even.
118 }
119 
120 /**
121  * @brief      	This function is used to set all the pin of s7816 module.
122  * @param[in]  	rst_pin     - the rst pin of s7816.
123  * @param[in]  	vcc_pin     - the vcc pin of s7816.
124  * @param[in]  	clk_pin     - the clk pin of s7816.
125  * @param[in]  	trx_pin     - the trx pin of s7816.
126  * @return     	none.
127  */
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)128 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)
129 {
130 	s7816_set_rst_pin(rst_pin);
131 	s7816_rst_pin=rst_pin;
132 
133 	s7816_set_vcc_pin(vcc_pin);
134 	s7816_vcc_pin=vcc_pin;
135 
136     reg_gpio_func_mux(clk_pin)=(reg_gpio_func_mux(clk_pin)&(~BIT_RNG(0,1)))|BIT(0);
137 	gpio_function_dis(clk_pin);
138 
139 	s7816_rtx_pin=rtx_pin;//if the trx function set to early,it may trigger interrupt by accident.so we set the function in coldreset.
140 }
141 
142 /**
143  * @brief      	This function is used to active the IC card,set the trx pin and coldreset.
144  * @param[in]  	none.
145  * @return     	none.
146  * @note        extra time is needed for initial-atr after the function.
147  */
s7816_coldreset()148 void s7816_coldreset()
149 {
150 	gpio_set_high_level(s7816_vcc_pin);
151 	delay_us(20);//wait for the vcc  stable.
152 	reg_7816_clk_div|=BIT(7); //enable the 7816 clk,the pin is A0.
153 	delay_us(s7816_rst_time);
154 	s7816_set_rtx_pin(s7816_rtx_pin);// uart tx/rx pin set,if the trx pin set before this place,it may
155     gpio_set_high_level(s7816_rst_pin);//the IC card will return the initial ATR.
156 }
157 
158 /**
159  * @brief      	This function is used to release the trigger.
160  * @param[in]  	none.
161  * @return     	none.
162  */
s7816_release_trig()163 void s7816_release_trig()
164 {
165 	gpio_set_low_level(s7816_rst_pin);
166 	reg_7816_clk_div&=(BIT(7)-1);
167 	gpio_set_low_level(s7816_vcc_pin);
168 }
169 
170 /**
171  * @brief      	This function is used to warmreset.
172  * @param[in]  	none.
173  * @return     	none.
174  * @note        the warmreset is required after the IC-CARD active,extra time is needed for initial-atr after the function.
175  */
s7816_warmreset()176 void s7816_warmreset()
177 {
178     gpio_set_low_level(s7816_rst_pin);
179     delay_us(s7816_rst_time);
180     gpio_set_high_level(s7816_rst_pin);//The IC card will return the initial ATR.
181 }
182 
183 /**
184  * @brief      	This function is used to warmreset.
185  * @param[in]  	uart_num - UART0 or UART1.
186  * @param[in]   tx_data  - the data need to send.
187  * return       none.
188  */
s7816_send_byte(uart_num_e uart_num,unsigned char tx_data)189 void s7816_send_byte(uart_num_e uart_num, unsigned char tx_data)
190 {
191 	uart_send_byte(uart_num,tx_data);
192 	uart_rtx_pin_tx_trig(uart_num);
193 }
194