| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 32 | kaklik | /******************************************************************** |
| 2 | FileName: SCpic18.c |
||
| 3 | Dependencies: See INCLUDES section |
||
| 4 | Processor: PIC18 Microcontrollers |
||
| 5 | Hardware: This demo is natively intended to be used on LPC & HPC Exp board. |
||
| 6 | This demo can be modified for use on other hardware platforms. |
||
| 7 | Complier: Microchip C18 (for PIC18) |
||
| 8 | Company: Microchip Technology, Inc. |
||
| 9 | |||
| 10 | Software License Agreement: |
||
| 11 | |||
| 12 | The software supplied herewith by Microchip Technology Incorporated |
||
| 13 | (the Company) for its PIC® Microcontroller is intended and |
||
| 14 | supplied to you, the Companys customer, for use solely and |
||
| 15 | exclusively on Microchip PIC Microcontroller products. The |
||
| 16 | software is owned by the Company and/or its supplier, and is |
||
| 17 | protected under applicable copyright laws. All rights are reserved. |
||
| 18 | Any use in violation of the foregoing restrictions may subject the |
||
| 19 | user to criminal sanctions under applicable laws, as well as to |
||
| 20 | civil liability for the breach of the terms and conditions of this |
||
| 21 | license. |
||
| 22 | |||
| 23 | THIS SOFTWARE IS PROVIDED IN AN AS IS CONDITION. NO WARRANTIES, |
||
| 24 | WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED |
||
| 25 | TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||
| 26 | PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, |
||
| 27 | IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR |
||
| 28 | CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
||
| 29 | |||
| 30 | ******************************************************************** |
||
| 31 | File Description: |
||
| 32 | |||
| 33 | Change History: |
||
| 34 | Rev Description |
||
| 35 | ---- ----------------------------------------- |
||
| 36 | 1.0 Initial release |
||
| 37 | 1.01 Cleaned up unnecessary variables |
||
| 38 | ********************************************************************/ |
||
| 39 | |||
| 40 | #include <p18cxxx.h> |
||
| 41 | #include "stdio.h" |
||
| 42 | #include "Smart Card/pps18.h" |
||
| 43 | #include "string.h" |
||
| 44 | #include "GenericTypeDefs.h" |
||
| 45 | #include "Smart Card/SCpic18.h" |
||
| 46 | #include "sc_config.h" |
||
| 47 | |||
| 48 | unsigned int gBitTimeDelay; |
||
| 49 | unsigned int bitTime; |
||
| 50 | unsigned int initialBaudReg; |
||
| 51 | unsigned long scReferenceClock; |
||
| 52 | |||
| 53 | unsigned long baudRate; |
||
| 54 | |||
| 55 | //////////////////////////////////////// |
||
| 56 | // Generate delay in microsec resolution |
||
| 57 | // 0 - 2 us |
||
| 58 | // 1 - 3 us |
||
| 59 | // 10 - 12 us |
||
| 60 | // ... |
||
| 61 | //////////////////////////////////////// |
||
| 62 | void WaitMicroSec( WORD microSec ) |
||
| 63 | { |
||
| 64 | while( microSec ) |
||
| 65 | { |
||
| 66 | Nop(); |
||
| 67 | microSec--; |
||
| 68 | } |
||
| 69 | } |
||
| 70 | |||
| 71 | void WaitMilliSec( WORD ms ) |
||
| 72 | { |
||
| 73 | while( ms-- ) |
||
| 74 | WaitMicroSec( 800 ); |
||
| 75 | } |
||
| 76 | |||
| 77 | /////////////////////////////////// |
||
| 78 | // precalculate 1 bit time microsec used for Delay counter |
||
| 79 | |||
| 80 | |||
| 81 | //////////////////////////////////////////////////// |
||
| 82 | //////////////////////////////////////////////////// |
||
| 83 | void SCdrv_SendTxData( BYTE data ) |
||
| 84 | { |
||
| 85 | BYTE txRetryCounter = 0; |
||
| 86 | BOOL noError = TRUE; |
||
| 87 | |||
| 88 | //calculate parity |
||
| 89 | _asm |
||
| 90 | swapf data,0,0 //reducing byte to nibble |
||
| 91 | xorwf data,0,0 |
||
| 92 | addlw 0x41 // bit 1 becomes B0^B1 and bit 7 becomes B6^B7 |
||
| 93 | iorlw 0x7C // for carry propagation from bit 1 to bit 7 |
||
| 94 | addlw 2 // Done! the parity bit is bit 7 of W |
||
| 95 | _endasm |
||
| 96 | |||
| 97 | TXSTAbits.TX9D = WREG >> 7; //copy calc parity bit to the transmitter |
||
| 98 | |||
| 99 | TXREG = data; |
||
| 100 | TXSTAbits.TXEN = 1; |
||
| 101 | |||
| 102 | while( !TXSTAbits.TRMT ) //wait for Tx Complete |
||
| 103 | { |
||
| 104 | Nop(); |
||
| 105 | } |
||
| 106 | |||
| 107 | TXSTAbits.TXEN = 0; |
||
| 108 | |||
| 109 | //turn off uart |
||
| 110 | RCSTAbits.SPEN = 0; |
||
| 111 | |||
| 112 | if( !SCdrv_GetRxPinData() ) // The Receiver did not like our data. it is pulling line low |
||
| 113 | { // to indicate PE or FR errors |
||
| 114 | noError = FALSE; |
||
| 115 | |||
| 116 | RCSTAbits.SPEN = 1; |
||
| 117 | |||
| 118 | //now retransmit the data |
||
| 119 | if( txRetryCounter < 5 ) |
||
| 120 | { |
||
| 121 | txRetryCounter++; |
||
| 122 | SCdrv_SendTxData(data); |
||
| 123 | } |
||
| 124 | } |
||
| 125 | |||
| 126 | if( noError ) //no error detected |
||
| 127 | txRetryCounter = 0; |
||
| 128 | |||
| 129 | RCSTAbits.SPEN = 1; |
||
| 130 | |||
| 131 | if( RCSTA & 0x6 ) //FERR or OERR occured |
||
| 132 | { |
||
| 133 | RCSTAbits.CREN = 0; //clear error flags |
||
| 134 | RCSTAbits.CREN = 1; |
||
| 135 | } |
||
| 136 | |||
| 137 | while(1) // remove rx data recvd from our Tx line |
||
| 138 | { |
||
| 139 | BYTE temp; |
||
| 140 | if( PIR1bits.RCIF ) |
||
| 141 | { |
||
| 142 | temp = RCREG; |
||
| 143 | } |
||
| 144 | else |
||
| 145 | break; |
||
| 146 | } |
||
| 147 | } |
||
| 148 | |||
| 149 | ///////////////////////////////////////////// |
||
| 150 | ///////////////////////////////////////////// |
||
| 151 | BOOL SCdrv_GetRxData( BYTE* pDat, unsigned long nTrys ) |
||
| 152 | { |
||
| 153 | //wait for data byte |
||
| 154 | while( !(PIR1 & 0x20) ) |
||
| 155 | { |
||
| 156 | if( nTrys-- == 0 ) |
||
| 157 | return FALSE; |
||
| 158 | } |
||
| 159 | |||
| 160 | //calculate parity |
||
| 161 | _asm |
||
| 162 | swapf RCREG,0,0 //reducing byte to nibble |
||
| 163 | xorwf RCREG,0,0 |
||
| 164 | addlw 0x41 // bit 1 becomes B0^B1 and bit 7 becomes B6^B7 |
||
| 165 | iorlw 0x7C // for carry propagation from bit 1 to bit 7 |
||
| 166 | addlw 2 // Done! the parity bit is bit 7 of W |
||
| 167 | RLNCF WREG,0,0 //rotate left W reg |
||
| 168 | xorwf RCSTA,0,0 |
||
| 169 | _endasm |
||
| 170 | |||
| 171 | if( WREG & 1 ) //Parity Error detected |
||
| 172 | { |
||
| 173 | RCSTAbits.SPEN = 0; |
||
| 174 | SCdrv_TxPin_Direction(0); //pull it low to tell the card that there was error receiving data |
||
| 175 | |||
| 176 | WaitMicroSec(gBitTimeDelay ); |
||
| 177 | |||
| 178 | SCdrv_TxPin_Direction(1); //release line. Card should retransmit now. |
||
| 179 | |||
| 180 | RCSTAbits.SPEN = 1; |
||
| 181 | return SCdrv_GetRxData( pDat, nTrys ); //Read the data from retransmission |
||
| 182 | } |
||
| 183 | |||
| 184 | *pDat = RCREG; |
||
| 185 | return TRUE; |
||
| 186 | } |
||
| 187 | |||
| 188 | |||
| 189 | /////////////////////////////////////////////////// |
||
| 190 | ////////////////////////////////////////////////// |
||
| 191 | void SCdrv_SetBRG( BYTE speedCode ) |
||
| 192 | { |
||
| 193 | float factorD = 1; |
||
| 194 | unsigned int factorF = 372; |
||
| 195 | BYTE tempCode; |
||
| 196 | unsigned int baudReg; |
||
| 197 | |||
| 198 | tempCode = speedCode & 0x0F; |
||
| 199 | |||
| 200 | // Calculate Factor 'D' from TA1 value |
||
| 201 | switch(tempCode) |
||
| 202 | { |
||
| 203 | case 0x00: |
||
| 204 | case 0x07: |
||
| 205 | case 0x01: |
||
| 206 | break; |
||
| 207 | |||
| 208 | case 0x02: |
||
| 209 | factorD = 2; |
||
| 210 | break; |
||
| 211 | |||
| 212 | case 0x03: |
||
| 213 | factorD = 4; |
||
| 214 | break; |
||
| 215 | |||
| 216 | case 0x04: |
||
| 217 | factorD = 8; |
||
| 218 | break; |
||
| 219 | |||
| 220 | case 0x05: |
||
| 221 | factorD = 16; |
||
| 222 | break; |
||
| 223 | |||
| 224 | case 0x06: |
||
| 225 | factorD = 32; |
||
| 226 | break; |
||
| 227 | |||
| 228 | case 0x08: |
||
| 229 | factorD = 12; |
||
| 230 | break; |
||
| 231 | |||
| 232 | case 0x09: |
||
| 233 | factorD = 20; |
||
| 234 | break; |
||
| 235 | |||
| 236 | case 0x0A: |
||
| 237 | factorD = 0.5; |
||
| 238 | break; |
||
| 239 | |||
| 240 | case 0x0B: |
||
| 241 | factorD = 0.25; |
||
| 242 | break; |
||
| 243 | |||
| 244 | case 0x0C: |
||
| 245 | factorD = 0.125; |
||
| 246 | break; |
||
| 247 | |||
| 248 | case 0x0D: |
||
| 249 | factorD = 0.0625; |
||
| 250 | break; |
||
| 251 | |||
| 252 | case 0x0E: |
||
| 253 | factorD = 0.03125; |
||
| 254 | break; |
||
| 255 | |||
| 256 | case 0x0F: |
||
| 257 | factorD = 0.015625; |
||
| 258 | break; |
||
| 259 | } |
||
| 260 | |||
| 261 | // If you are not using internal clock in Smart Card & are |
||
| 262 | // using external clock to drive Smart Card than calculate |
||
| 263 | // factor 'F' from TA1 value |
||
| 264 | #ifdef ENABLE_SC_EXTERNAL_CLOCK |
||
| 265 | |||
| 266 | tempCode = (speedCode & 0xF0) >> 4; |
||
| 267 | |||
| 268 | // Calculate Factor 'F' from TA1 value |
||
| 269 | switch(tempCode) |
||
| 270 | { |
||
| 271 | case 0x00: |
||
| 272 | case 0x07: |
||
| 273 | case 0x08: |
||
| 274 | case 0x0E: |
||
| 275 | case 0x0F: |
||
| 276 | break; |
||
| 277 | |||
| 278 | case 0x01: |
||
| 279 | factorF = 372; |
||
| 280 | break; |
||
| 281 | |||
| 282 | case 0x02: |
||
| 283 | factorF = 558; |
||
| 284 | break; |
||
| 285 | |||
| 286 | case 0x03: |
||
| 287 | factorF = 744; |
||
| 288 | break; |
||
| 289 | |||
| 290 | case 0x04: |
||
| 291 | factorF = 1116; |
||
| 292 | break; |
||
| 293 | |||
| 294 | case 0x05: |
||
| 295 | factorF = 1488; |
||
| 296 | break; |
||
| 297 | |||
| 298 | case 0x06: |
||
| 299 | factorF = 1860; |
||
| 300 | break; |
||
| 301 | |||
| 302 | case 0x09: |
||
| 303 | factorF = 512; |
||
| 304 | break; |
||
| 305 | |||
| 306 | case 0x0A: |
||
| 307 | factorF = 768; |
||
| 308 | break; |
||
| 309 | |||
| 310 | case 0x0B: |
||
| 311 | factorF = 1024; |
||
| 312 | break; |
||
| 313 | |||
| 314 | case 0x0C: |
||
| 315 | factorF = 1536; |
||
| 316 | break; |
||
| 317 | |||
| 318 | case 0x0D: |
||
| 319 | factorF = 2048; |
||
| 320 | break; |
||
| 321 | } |
||
| 322 | |||
| 323 | if(tempCode == 0x00) // If internal clock used in Smart Card |
||
| 324 | { |
||
| 325 | baudReg = (unsigned int)(FCY/(9600 * factorD) - 1); |
||
| 326 | SPBRG = (unsigned char)baudReg; |
||
| 327 | SPBRGH = (unsigned char)(baudReg >> 8); |
||
| 328 | } |
||
| 329 | else // If externa; clock used to drive Smart Card |
||
| 330 | { |
||
| 331 | baudRate = (scReferenceClock * factorD)/factorF; |
||
| 332 | baudReg = (unsigned int)((FCY/baudRate) - 1); |
||
| 333 | SPBRG = (unsigned char)baudReg; |
||
| 334 | SPBRGH = (unsigned char)(baudReg >> 8); |
||
| 335 | } |
||
| 336 | |||
| 337 | #else // If internal clock used in Smart Card |
||
| 338 | |||
| 339 | baudReg = (unsigned char)(FCY/(9600 * factorD) - 1); |
||
| 340 | SPBRG = (unsigned char)baudReg; |
||
| 341 | SPBRGH = (unsigned char)(baudReg >> 8); |
||
| 342 | |||
| 343 | #endif |
||
| 344 | |||
| 345 | //recalculate bit time |
||
| 346 | gBitTimeDelay = baudReg; |
||
| 347 | gBitTimeDelay *= bitTime; //micro sec for 1 bit @ 9.6kbps |
||
| 348 | gBitTimeDelay /= initialBaudReg; |
||
| 349 | } |
||
| 350 | |||
| 351 | /////////////////////////////////////////////////// |
||
| 352 | ////////////////////////////////////////////////// |
||
| 353 | void SCdrv_CloseUART(void) |
||
| 354 | { |
||
| 355 | SCdrv_DisableClock(); //turn off Clock |
||
| 356 | RCSTAbits.SPEN = 0; //turn off UART |
||
| 357 | RCSTAbits.CREN = 0; |
||
| 358 | } |
||
| 359 | |||
| 360 | |||
| 361 | /////////////////////////////////////////////////// |
||
| 362 | ////////////////////////////////////////////////// |
||
| 363 | void SCdrv_InitUART(void) |
||
| 364 | { |
||
| 365 | unsigned int power2Value = 1; |
||
| 366 | BYTE power2temp; |
||
| 367 | |||
| 368 | SCdrv_PowerPin_Direction(0); //set RB0 as output to power the Smart Card |
||
| 369 | SCdrv_ResetPin_Direction(0); //set RB4 as output for Smart Card Reset Pin |
||
| 370 | SCdrv_CardPresent_Direction(1); //RB3 Input Card Present |
||
| 371 | SCdrv_SimPresent_Direction(1); //RB1 Input Card Present |
||
| 372 | |||
| 373 | SCdrv_SetTxPinData(0); |
||
| 374 | SCdrv_TxPin_Direction(1); // TX1 also act as gpio to pull the line low |
||
| 375 | SCdrv_RxPin_Direction(1); |
||
| 376 | |||
| 377 | SCdrv_EnableCardSimPresentPinPullUp(); //enable pull up, active low |
||
| 378 | |||
| 379 | SCdrv_SetSwitchCardPower(0); //Turn off power to smart card |
||
| 380 | SCdrv_SetSwitchCardReset(0); //keep card in reset state |
||
| 381 | |||
| 382 | // Set the clock value that you want to trigger the smart card. |
||
| 383 | // Dont enable the clock,only set it. |
||
| 384 | Scdrv_ClockSet(); |
||
| 385 | |||
| 386 | power2temp = REF_CLOCK_POWER2_VALUE; |
||
| 387 | |||
| 388 | while(power2temp--) |
||
| 389 | { |
||
| 390 | power2Value = power2Value * (BYTE)2; |
||
| 391 | } |
||
| 392 | |||
| 393 | scReferenceClock = REF_CLOCK_CIRCUIT_INPUT_CLK/(power2Value + REF_CLOCK_DIVISOR_VALUE); |
||
| 394 | |||
| 395 | baudRate = scReferenceClock/(unsigned int)372; |
||
| 396 | |||
| 397 | initialBaudReg = ((FCY/baudRate) - 1); |
||
| 398 | SPBRG = (unsigned char)initialBaudReg; |
||
| 399 | SPBRGH = (unsigned char)(initialBaudReg >> 8); |
||
| 400 | bitTime = (1000000UL)/baudRate + 1; |
||
| 401 | |||
| 402 | gBitTimeDelay = initialBaudReg; |
||
| 403 | gBitTimeDelay *= bitTime; //micro sec for 9.6k baud |
||
| 404 | gBitTimeDelay /= initialBaudReg; |
||
| 405 | |||
| 406 | TXSTAbits.TX9 = 1; //select 9 bit transmission |
||
| 407 | TXSTAbits.SYNC = 0; //Async mode |
||
| 408 | TXSTAbits.BRGH = 1; |
||
| 409 | BAUDCONbits.BRG16 = 1; |
||
| 410 | |||
| 411 | RCSTAbits.CREN = 1; |
||
| 412 | RCSTAbits.RX9 = 1; |
||
| 413 | } |
||
| 414 | |||
| 415 |
Powered by WebSVN v2.8.3