找回密码
 注册

微信扫码登录

使用验证码登录

只需一步,快速开始

胜天工科技销售各种数字电视信号调制卡胜天工科技销售各种数字电视信号码流卡

【游客、新手、注册会员的区别】 【积分策略和会员晋级说明】 【发帖和附件上传规则】 【如何下载感兴趣的资料】 【如何获取梦游币】 【侵权资料处理及免责说明】
查看: 2246|回复: 0

IC电话卡彻底解密

[复制链接]
  • TA的每日心情
    擦汗
    2012-7-22 22:21
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    发表于 2009-5-4 17:14:10 | 显示全部楼层 |阅读模式
    分享到:
    消息来自- 北京
    声明:本资料仅从技术的角度全面探讨IC卡、IC电话卡及其安全性,由此引发的各种争议或个人、集体利用本资料做任何不正当用途本人概不负责。

    目录
    Ⅰ)第一类卡(德国、西班牙、中国、香港、澳门等)
    Ⅰ-1)介绍:
    Ⅰ-2)引脚:
    Ⅰ-3)主要特性:
    Ⅰ-4)时序图:
    Ⅰ-5)内存数据:
    Ⅱ)第二类卡(法国、墨西哥、捷克、瑞典、爱尔兰等)
    Ⅱ-1)介绍:
    Ⅱ-2)引脚:
    Ⅱ-3)主要特性:
    Ⅱ-4)时序图:
    Ⅱ-5)内存数据:
    Ⅱ-6)电气参数:

    Ⅰ) 第一类卡

    Ⅰ-1)介绍

    自从80年代中期出现IC电话卡后,基本已取代了原来流行的电话磁卡,磁卡存在存在严重的安全问题,已逐步淘汰。
    即使IC电话卡,也不能算很安全,卡内所有数据只要有简单的读写装置并按时序操作都能读取,事实上电话卡和信用卡一样内部没有什么秘密信息,仅仅是带串行输出的128位EPROM而已(对二类卡是256位PROM),不要以为弄懂了它是怎么工作你就有办法重新对卡内数据重新填充,其开始的64位是带写保护的,在出厂时其熔丝位已被编程,你已无法对其更改,其后的40位计数单元受内部逻辑控制在写时只能减少不能增加直至到0为止,因此你想用一般的IC电话卡打免费电话是不可能的,除非你能用单片机仿真它(如果你能读懂本文介绍的所有内容)。IC电话卡是一种一次性使用的计数卡,以一次性的计数方式,从写满的计数器中减“1”,直至存储单元减为空为止。

    卡片每次消费计数的“单位价值”根据各种应用系统的实际需要而定。例如:对于中国IC电话卡,如30元卡对应内部计数值为300,每单位值对应0.1元,IC 卡电话机每分钟产生一次扣费信号,扣费值由当地IC电话管理系统设定,一般是价值0.5元或1元,卡片被计数5次和10次。对于其它国家属于第一类IC电话卡而言也是如此,只是内部初始计数值不同,每次扣除额度不一样罢了。其他对于公用加油卡,IC卡计费加油机每一公升(或一加仑)产生一次扣费操作,卡片被操作一次扣2.5元等等,均属于等同原理。事实上,这类卡内部为128位(16字节) NMOS存储器,按如下规律分布:

    64 位 EPPOM(8字节) 写保护区(芯片数据代码区、发行数据代码区)
    40 位 EEPROM(5字节)
    24 位 为全“1”(3字节)
    共16字节数据。
    Ⅰ-2)引脚:
    -------------+-------------
    | 1 | 5 | 引 脚:
    | | | -------
    +-------\ | /-------+
    | 2 +----+ + 6 | 1 : Vcc = 5V 5 : Gnd
    | | | | 2 : Reset 6 : NC
    +--------| |--------+ 3 : Clock 7 : I/O
    | 3 | | 7 | 4 : NC 8 : NC
    | +----+----+ |
    +-------/ | \-------+ Vcc:电源 Gnd:地脚 Reset:复位
    | 4 | 8 |
    | | | Clock:时钟 I/O:数据 NC: 空脚
    -------------+-------------
    因有三个脚为空脚,目前一般有采用8脚和6脚封装的,6脚封装的无最下一排两个空脚

    Ⅰ-3)主要特性:
    -采用单一5V电源供电
    -遵循ISO/IEC7816-3同步协议进行双向数据传输
    -低功耗
    -NMOS技术
    -高可靠性,抗静电干扰能力>4KV

    Ⅰ-4)时序图
    复位:
    为使地址计数器复位到0,先让Reset端变高。紧跟着一个Clock脉冲(从低到高再降到0),Reset重新变低,把Clock脉冲包住。随着Reset端变低,地址0单元的数据从I/O上输出。对应 Clock端的每个脉冲,其上升沿使地址计数器增加。其下降沿使被选通地址单元的数据从I/O上输出。地址计数器增加到127后返回到0。

    __________________
    _____| |_____________________________________________ Reset
    : :
    : _____ : _____ _____ _____ _____
    _____:_______| |____:_| |_____| |_____| |_____| |_ Clk
    : : : : : : : : : : :
    _____:_______:__________:_:_____:_____:_____:_____:_____:_____:_____:_
    _____:___n___|_____0____:_|_____1_____|_____2_____|_____3_____|___4_:_ (Address)
    : : : : : :
    _____: :_______:___________:___________:___________:_
    _____XXXXXXXXXXXXXXXXXXXX_______|___________|___________|___________|_ Data
    Bit n Bit 0 Bit 1 Bit2 Bit3
    写位:
    在Reset和Clk端均为低的情况下,如果某地址单元允许写操作(64-103位,且该位必需为1),则Reset端上的一个脉冲(即从低到高再回低)将允许芯片进行位写操作。在紧跟着的时钟脉冲期间执行写操作,调整写操作维持时间至少10ms,在这个CLK脉冲期间,地址计数器不会增加,在CLK写脉冲下降沿,数据0从I/O端输出。从Reset脉冲的上升沿到CLK写脉冲的下降沿期间,I/O端的数据是无效的。在下一个才CLK脉冲,且Reset为低时,地址计数器又增1,并在下降沿时,把选通的地址单元的数据送到I/O端。

    _____ _____
    _____________| |______________________________| |_______________ Reset
    : :
    ___ : _____ ___ : _____
    ____| |____:__________| |_________| |_____:__________| |____ Clk
    : : : : : : : : :
    ____:________:__________:_____:_________:___:_____:__________:_____:_____
    n | n+1 | n+2 | : n+3 | : (Address)
    ----’--------:----------’-----:---------’---:-----:----------’-----:-----
    : : : : : : :
    _________ _: : : ____________: ___: : :
    _________XXX_XXXXXXXXXXXXXXXXXXX____________ XX___XXXXXXXXXXXXXXXXXXXXXXX I/O
    n n+1 : : n+1 n+2 : :
    : : : :
    write write
    借位写后的字节擦除:
    对位地址72-103的字节单元来说,只要在每个字节的前面一位进行一次正常的写操作,就可以对此字节后一字节进行字节擦除操作。也就是说,每向高一字节进行借位(即写一位0),紧接着的擦除时序可以对后一字节按字节擦除(即整个字节写1)。被擦除的字节总是比借位写的字节低一字节。从以下时序图可以看出,首先,完成一个“位写”操作,在CLK的写脉冲结束后,在CLK为低电平时,在发一个Reset脉冲即启动字节擦除操作。在第二个CLK脉冲完成字节擦除,脉冲维持时间整定为擦除周期时间(至少1ms)。芯片逻辑控制电路验证了借位写确已完成从“1”写“0”后,才擦除其低位字节。从Reset的上升沿到擦除操作的CLK脉冲的下降沿,I/O脚上的数据无效。地址计数器仍然停留在借位写的地址上。

    _____ _____
    ______| |____________________| |_________________________________ Rst
    : :
    : _______ : _______ ___
    ______:___________| |______:_____________| |______| |______ Clk
    : : : : : : : :
    : : : : : : : :
    <------------------------- address n ------------------------>:<--- n+1 ------
    : : : : : : :
    : : : : : : :
    ______: : :______: : :__________: _____
    ______XXXXXXXXXXXXXXXXXXXXX______XXXXXXXXXXXXXXXXXXXXXXX__________XX_____ I/O
    : : n : : n n+1
    : : : :
    Write Erase
    计数方法:
    在67-103地址单元中分为5个不可重置8单元计数器,芯片初始化时,72-103地址单元所对应的4个较低的8单元计数器中可以放0到8个“1”而67-71地址单元所对应的第5个计数器可以放0到5个“1”。所谓计数一次,就是将一个单元从“1”写成“0”。一个计数器中8位全为“0”后,要计数,需借位操作,即将高位计数器的一位从“1”写成“0”而相应其低位计数器整个字节从“0”擦除成“1”。可见4个8单元计数器如此逐一递减,其最大计数为8的4次方=4096。第5个计数器中5个单元因处在最高位只能被写“0”无法擦成“1”。因此只能计数5次。故芯片总计数为5X4096=20480。当全部计数单元(地址67-103)都被写成“0”时,卡片就用完了,不过,芯片出厂初始化时,初置的计数值由国家不同和卡片面值不同而不同,如100元卡初置计数值为1000。

    举例: 100元(1000计数单元预置初始值).
    --------

    Byte9 Byte10 Byte11 Byte12 Byte13
    --------------------------------------------------------------
    000000 - 00000001 - 01111111 - 00011111 - 00000000
    --------------------------------------------------------------
    (3)octal (6)octal (7)octal (1)octal (2)octal
    --------------------------------------------------------------
    Value = 0*8^4 + 1*8^3 + 7*8^2 + 5*8^1 + 0*8^
    --------------------------------------------------------------
    总值 = 1000 Units
    Ⅰ-5)内存数据:
    字节 位 二进制 十六进制
    +-----------+-----+
    1 1 --> 8 | | |
    +-----------+-----+
    2 9 --> 16 | 0010 1111 | $2F | ---> 德国
    | 0011 0111 | $37 | ---> 西班牙
    | 0011 1011 | $3B | ---> 希腊
    +-----------+-----+
    3 17 --> 24 | | |
    4 25 --> 32 | | | ---> 出厂编号(写保护)
    5 33 --> 40 | | |
    6 41 --> 48 | | |
    7 49 --> 56 | | |
    8 57 --> 64 | | |
    +-----------+-----+
    9 65 --> 72 | | | ---> c4096 )
    10 73 --> 80 | | | ---> c512 )
    11 81 --> 88 | | | ---> c64 ) 5个8进制计数区
    12 89 --> 96 | | | ---> c8 )
    13 97 --> 104 | | | ---> c0 )
    +-----------+-----+
    14 105 --> 112 | 1111 1111 | $FF |
    15 113 --> 120 | 1111 1111 | $FF | ---> 所有位都为"1"
    16 120 --> 128 | 1111 1111 | $FF |
    +-----------+-----+
    如需某一国家卡内数据详细数据请与作者联系。

    Ⅱ)第二类卡

    Ⅱ-1)介绍:

    二类卡与一类卡的区别在于,二类卡为256位PROM卡,在计数方式上有区别,一类卡5个计数单元组成5位8进制递减计数单元,有较大的计数范围,而二类卡的计数单元每一位只能计数一次,在写为“1”后该位即无效,另外在引脚设置、操作时序上也不相同。

    Ⅱ-2)引脚:

    -------------+-------------
    | 1 | 5 |
    | | |
    +-------\ | /-------+
    | 2 +----+ + 6 |
    | | | |
    +--------| |--------+
    | 3 | | 7 |
    | +----+----+ |
    +-------/ | \-------+
    | 4 | 8 |
    | | |
    -------------+-------------


    1 : Vcc = 5V 5 : Gnd
    2 : R/W 6 : Vpp = 21V
    3 : Clock 7 : I/O
    4 : Reset 8 : Fuse
    1:电源脚 2:读写控制 3:时钟 4:复位 5:接地 6:熔丝电压 7:输入输出 8:熔丝控制

    Ⅱ-3)主要特性:
    -同步传输协议
    -N-MOS技术
    -256X1位
    -96位带写保护
    -低功率85mW
    -21V熔丝电压
    -响应时间:500ns
    -10年以上数据保持

    Ⅱ-4)时序图:
    +21V _____________
    +5V ____________________________________| |_________________ Vpp
    : :
    +5V ___________________:_____________:_________________ Reset
    0V ________________| : :
    : : :
    +5V ____ : ____ : ______:______
    0V ___| |_______:_____| |________:______| : |__________ Clock
    : : : : : : : : :
    +5V : : : : : :______:______: : _
    0V ___:____:_______:_____:____:________| : |______:__________ R/W
    : : : : : : : : :
    +5V : : :_____: :________: : : :__________
    0V XXXXXXXXXXXXXXXXX_____XXXXXX________XXXXXXXXXXXXXXXXXXXXXX__________ Out
    : : : : : :<-----><---->: :
    : : : : : :10 to 10 to :
    : : : : : :50 ms 50ms :
    卡复位 Bit 1 Bit2 Bit 3
    读 读 Bit2 写为1 读
    -5)内存数据:
    法国和摩洛哥等:

    字节 位 进制 十六进制
    +-----------+-----+
    1 1 --> 8 | | |
    +-----------+-----+
    2 9 --> 16 | 0000 0011 | $03 | ---> 法国卡
    +-----------+-----+
    3 17 --> 24 | | |
    +-----------+-----+
    4 25 --> 32 | | |
    +-----------+-----+
    5 33 --> 40 | | |
    +-----------+-----+
    6 41 --> 48 | | |
    +-----------+-----+
    7 49 --> 56 | | |
    +-----------+-----+
    8 57 --> 64 | | |
    +-----------+-----+
    9 65 --> 72 | | |
    +-----------+-----+
    10 73 --> 80 | | |
    +-----------+-----+
    11 81 --> 88 | | |
    +-----------+-----+
    12 33 --> 40 | 0001 0011 | $13 | ---> 120 units card
    | 0000 0110 | $06 | ---> 50 units card
    | 0000 0101 | $05 | ---> 40 units card
    +-----------+-----+
    13-31 97 --> 248 | | | ---> 计数单元区: 每消耗一单位,该位被写
    | | | 为“1”,一般开始10为为工厂作熔丝
    | | | 测试写为“1”
    | | |
    | | |
    | | |
    | | |
    +-----------+-----+
    32 249 --> 256 | 1111 1111 | $FF | ---> 空卡指示
    +-----------+-----+
    其它国家:
    字节 位 进制 十六进制

    +-----------+-----+
    1 1 --> 8 | | |
    +-----------+-----+
    2 9 --> 16 | 1000 0011 | $83 | ---> 电话卡标记
    +-----------+-----+-----------+-----+
    3-4 17 --> 32 | 1000 0000 | $80 | 0001 0010 | $12 | ---> 10 元 卡
    | | | 0010 0100 | $24 | ---> 22 元 卡
    | | | 0010 0111 | $27 | ---> 25 元 卡
    | | | 0011 0010 | $32 | ---> 30 元 卡
    | | | 0101 0010 | $52 | ---> 50 元 卡
    | | | 0110 0010 | $62 | ---> 60 元 卡
    | | | 1000 0010 | $82 | ---> 80 元 卡
    | 1000 0001 | $81 | 0000 0010 | $02 | ---> 100 元 卡
    | | | 0010 0010 | $22 | ---> 120 元 卡
    | | | 0101 0010 | $52 | ---> 150 元 卡
    +-----------+-----+-----------+-----+
    5 33 --> 40 | | | ---> $00 for sweden.
    +-----------+-----+
    6 41 --> 48 | | |
    +-----------+-----+
    7 49 --> 56 | | |
    +-----------+-----+
    8 57 --> 64 | | |
    +-----------+-----+
    9 65 --> 72 | | |
    +-----------+-----+
    10 73 --> 80 | | |
    +-----------+-----+
    11 81 --> 88 | | | ---> $11 为瑞典
    +-----------+-----+
    12 89 --> 96 | 0001 1110 | $1E | ---> 瑞典
    | 0011 0000 | $30 | ---> 挪威
    | 0011 0011 | $33 | ---> 安道尔
    | 0011 1100 | $3C | ---> 爱尔兰
    | 0100 0111 | $47 | ---> 葡萄牙
    | 0101 0101 | $55 | ---> 捷克
    | 0101 1111 | $5F | ---> 加蓬
    | 0110 0101 | $65 | ---> 芬兰
    +-----------+-----+
    13-31 97 --> 248 | | | ---> 计数单元区: 每消耗一单位,该位被写
    | | | 为“1”,一般开始2为为工厂作熔丝
    | | | 测试写为“1” 。
    | | |
    | | |
    | | |
    | | |
    +-----------+-----+
    32 249 --> 256 | 0000 0000 | $00 |
    +-----------+-----+

    Ⅲ)电气参数:
    +--------+------+------+------+
    | Symbol | Min | Max | Unit |
    +----------------------+--------+------+------+------+
    | Supply voltage | Vcc | -0.3 | 6 | V | 电源电压
    +----------------------+--------+------+------+------+
    | Input voltage | Vss | -0.3 | 6 | V | 输入电压
    +----------------------+--------+------+------+------+
    | Storage temperature | Tstg | -20 | +55 | | 储存温度
    +----------------------+--------+------+------+------+
    | Power dissipassion | Pd | - | 50 | mW | 功率
    +----------------------+--------+------+------+------+

    直流参数:
    +--------+-----+-----+-----+------+
    | Symbol | Min.| Typ.| Max.| Unit |
    +---------------------------+--------+-----+-----+-----+------+
    | Suplly current | Icc | - | - | 5 | mA | 电源电流
    +---------------------------+--------+-----+-----+-----+------+
    | Input Voltage (low) | Vl | 0 | - | 0.8 | V | 输入电压(低)
    +---------------------------+--------+-----+-----+-----+------+
    | Input voltage (high) | Vh | 3.5 | - | Vcc | V | 输入电压(高)
    +---------------------------+--------+-----+-----+-----+------+
    | Input current R | Ih | - | - | 100 | uA | 输入电流(复位)
    +---------------------------+--------+-----+-----+-----+------+
    | Input current Clk | Il | - | - | 100 | uA | 输入电流(时钟)
    +---------------------------+--------+-----+-----+-----+------+
    | Output current (Low) | Iol | - | - | 10 | uA | 输出电流(低电平)
    +---------------------------+--------+-----+-----+-----+------+
    | Output current (High) | Ioh | - | - | 0.5 | mA | 输出电流(高电平)
    +---------------------------+--------+-----+-----+-----+------+

    动态参数:

    +--------+------+------+------+
    | Symbol | Min. | Max. | Unit |
    +----------------------+--------+------+------+------+
    | Pulse duration | tr | 50 | - | us |
    | R address reset | | | | | 复位时复位脉冲持续时间
    +----------------------+--------+------+------+------+
    | Pulse duration | ts | 10 | - | us |
    | R write | | | | | 写位时复位脉冲持续时间
    +----------------------+--------+------+------+------+
    | High level Clk | th | 8 | - | us | 时钟高电位时间
    +----------------------+--------+------+------+------+
    | Low level Clk | tl | 12 | - | us | 时钟低电位时间
    +----------------------+--------+------+------+------+
    | Write window | Twrite | 10 | - | ms | 写位时间
    +----------------------+--------+------+------+------+
    | Erase window | Terase | 10 | - | ms | 擦除时间
    +----------------------+--------+------+------+------+
    | | tv1 | 5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv2 | 3.5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv3 | 3.5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv4 | 3.5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv5 | 3.5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv6 | 5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv7 | 5 | - | us |
    +----------------------+--------+------+------+------+
    | | tv8 | 10 | - | us |
    +----------------------+--------+------+------+------+

    Ⅳ)读卡器电路图:
    简易读卡器电路图(利用电脑打印口,可读一类、二类卡)

    外接5V (可选)

    5V o------,
    | / T2 PNP d13 r7 10
    0V o--, | / BC 177 |\ | _____
    | | ,-------o/ o--*------. E C .--| >+-[_____]--------,
    __+__ | | | \ / |/ | |
    \\\\\ | __|__ Batery | \ / |
    | - 22.5V | --------- |
    ....... | | | _____ | _____ |
    : | __+__ +--[_____]--*--[_____]--, |
    D2 : | \\\\\ r6 150k r5 15k | |
    4 o-------|---------------------------*------------------|-------------, |
    : | | r3 220k / C | |
    Ack : | | _____ |/ T1 - NPN | |
    10 o------|--------. ’--[_____]-*---| BC107 | |
    : | | _____ | |\ | |
    : ,-, ,-, +--[_____]-’ \ E | |
    : | |r2 | |r1 | r4 390k | | |
    : | |220 | |22k __+__ __+__ | |
    : |_| |_| \\\\\ \\\\\ | |
    : | |\ | | | |
    : *--| >+--|----------------*----------------------------------|--*
    : | |/ | | ,-----|-----------------------------, | |
    : | d1 | | | ,----------,----------, | | |
    : | | | *---|--* Fuse | Reset *--|---’ | |
    : | | | | |----------|----------| | |
    D0 : | | | ,-|---|--* I/O | Clk *--|---, | |
    2 o-------|--------|----------’ | | |----------|----------| | | |
    : | | | ’---|--* Vpp | R/W *--|---|----’ |
    Busy : | | | |----------|----------| | |
    11 o------|--------|--------------’ ,---|--* Gnd | 5V * | | |
    : | | | ’----------’-------|--’ | |
    D1 : | | __+__ Chip connector | | |
    3 o-------|--------|--------, \\\\\ | | |
    : | | ’------------------------------|------’ |
    Str : | |\ | | | |
    1 o-------*--| >+--*----*----*----*----*-------------------’ |
    : d2|/ | |d3 |d4 |d5 |d6 |d7 |
    : -+- -+- -+- -+- -+- |
    : /_\ /_\ /_\ /_\ /_\ |
    D3 : | | | | | |\ | d8 |
    5 o----------------*----|----|----|----|---| >+-------*-------------------’
    : | | | | |/ | |
    : | | | | |
    D4 : | | | | |\ | d9 |
    6 o---------------------*----|----|----|---| >+-------*
    : | | | |/ | |
    : | | | |
    D5 : | | | |\ | d10 |
    7 o--------------------------*----|----|---| >+-------*
    : | | |/ | |
    : | | |
    D6 : | | |\ | d11 |
    8 o-------------------------------*----|---| >+-------*
    : | |/ | |
    : | |
    D7 : | |\ | d12 |
    9 o------------------------------------*---| >+-------’
    : |/ |
    :
    :
    25 o------.
    : |
    .......: | d1 to d13: 1N4148
    __+__
    \\\\\

    Ⅴ)读卡程序:
    下面程序为与简易读卡器相配套二类卡读卡源程序(如需一类卡源程序或需C源程序或其可执行程序请与作者联系)

    USES crt,dos;

    CONST port_address=$378; { lpr1 chosen }

    TYPE string8=string[8];
    string2=string[2];

    VAR reg : registers;
    i,j : integer;
    Data : array[1..32] of byte;
    car : char;
    byte_number : integer;
    displaying : char;

    {-----------------------------------------------------------------------------}

    PROCEDURE Send(b:byte);

    BEGIN port[port_address]:=b;
    END;

    {-----------------------------------------------------------------------------}

    FUNCTION Get:byte;

    BEGIN get:=port[port_address+1];
    END;

    {-----------------------------------------------------------------------------}
    { FUNCTION dec2hexa_one(decimal_value):hexa_character_representation; }
    { }
    { - convert a 4 bit long decimal number to hexadecimal. }
    {-----------------------------------------------------------------------------}

    FUNCTION dec2hexa_one(value:byte):char;

    BEGIN case value of
    0..9 : dec2hexa_one:=chr(value+$30);
    10..15 : dec2hexa_one:=chr(value+$37);
    END;
    END;

    {-----------------------------------------------------------------------------}
    { FUNCTION d2h(decimal_byte):string2; }
    { }
    { - convert a decimal byte to its hexadecimal representation. }
    {-----------------------------------------------------------------------------}

    FUNCTION d2h(value:byte):string2;

    VAR msbb,lsbb:byte;

    BEGIN msbb:=0;
    if ( value >= $80 ) then
    BEGIN msbb:=msbb+8;
    value:=value-$80;
    END;
    if ( value >= $40 ) then
    BEGIN msbb:=msbb+4;
    value:=value-$40;
    END;
    if ( value >= $20 ) then
    BEGIN msbb:=msbb+2;
    value:=value-$20;
    END;
    if ( value >= $10 ) then
    BEGIN msbb:=msbb+1;
    value:=value-$10;
    END;

    lsbb:=0;
    if ( value >= $08 ) then
    BEGIN lsbb:=lsbb+8;
    value:=value-$08;
    END;
    if ( value >= $04 ) then
    BEGIN lsbb:=lsbb+4;
    value:=value-$04;
    END;
    if ( value >= $02 ) then
    BEGIN lsbb:=lsbb+2;
    value:=value-$02;
    END;
    if ( value >= $01 ) then
    BEGIN lsbb:=lsbb+1;
    value:=value-$01;
    END;
    d2h := dec2hexa_one(msbb) + dec2hexa_one(lsbb);
    END;

    {-----------------------------------------------------------------------------}

    Function Binary( b : byte):string8;

    var weigth : byte;
    s : string8;

    BEGIN weigth:=$80;
    s:=’’;
    while (weigth > 0) do
    BEGIN if ((b and weigth) = weigth) then s:=s+’1’
    else s:=s+’0’;
    weigth:=weigth div $02;
    END;
    Binary:=s;
    END;

    {-----------------------------------------------------------------------------}

    FUNCTION Units:byte;

    VAR u, i : integer;
    s : string8;

    BEGIN u:=0;
    i:=13;
    while (Data[i] = $FF) do
    BEGIN u:=u+8;
    i:=i+1;
    END;
    s:=Binary(Data[i]);
    while(s[1]=’1’) do
    BEGIN inc(u);
    s:=copy(s,2,length(s));
    END;
    units:=u;
    END;

    {-----------------------------------------------------------------------------}

    function Units_2:LongInt;

    BEGIN Units_2:=4096*Data[9]+512*Data[10]+64*Data[11]+8*Data[12]+Data[13];
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE Card_Type;

    BEGIN case Data[2] of
    $03: BEGIN write(’Telecard - France - ’);
    case Data[12] of
    $13: write(’120 Units - ’,units-130,’ Units left’);
    $06: write(’50 Units - ’,units-60,’ Units left’);
    $15: write(’40 Units - ’,units-40,’ Units left’);
    END;
    END;
    $2F:BEGIN write(’Telecard - Germany - ’, Units_2, ’ Units left’);
    END;
    $3B:BEGIN write(’Telecard - Greece - ’, Units_2, ’ Units left’);
    END;
    $83:BEGIN write(’Telecard’);
    case Data[12] of
    $1E: write(’ - Sweden’);
    $30: write(’ - Norway’);
    $33: write(’ - Andorra’);
    $3C: write(’ - Ireland’);
    $47: write(’ - Portugal’);
    $55: write(’ - Czech Republic’);
    $5F: write(’ - Gabon’);
    $65: write(’ - Finland’);
    END;
    if (Data[12] in [$30,$33,$3C,$47,$55,$65]) then
    BEGIN case ((Data[3] and $0F)*$100+Data[4]) of
    $012: write (’ - 10 Units - ’,units-12,’ Units left’);
    $024: write (’ - 22 Units - ’,units-24,’ Units left’);
    $027: write (’ - 25 Units - ’,units-27,’ Units left’);
    $032: write (’ - 30 Units - ’,units-32,’ Units left’);
    $052: write (’ - 50 Units - ’,units-52,’ Units left’);
    $067: write (’ - 65 Units - ’,units-62,’ Units left’);
    $070: write (’ - 70 Units - ’,units-70,’ Units left’);
    $102: write (’ - 100 Units - ’,units-102,’ Units left’);
    $152: write (’ - 150 Units - ’,units-152,’ Units left’);
    END;
    END;
    { write(’ - N?’,Data[5]*$100+Data[6]);}
    END;
    END;
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE waiting;

    BEGIN send($00);
    write(’Enter a card in the reader and press a key ...’);
    repeat until keypressed;
    gotoxy(1, wherey);
    clreol;
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE Full_Displaying;

    BEGIN writeln(’Memory dump:’);
    for i:=1 to 80 do write(’-’);
    for i:=1 to (byte_number div 6 + 1) do
    BEGIN for j:=1 to 6 do
    BEGIN if j+6*(i-1) <= byte_number then write(binary(Data[j+6*(i-1)]):9);
    END;
    gotoxy(60,wherey);
    for j:=1 to 6 do
    if j+6*(i-1) <= byte_number then write(d2h(Data[j+6*(i-1)]),’ ’);
    writeln;
    END;
    for i:=1 to 80 do write(’-’);
    Card_Type;
    writeln;
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE Short_Displaying;

    VAR j : integer;

    BEGIN for j:=1 to byte_number do
    BEGIN write(d2h(Data[j]),’ ’);
    END;
    writeln;
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE Reading;

    VAR i, j : integer;
    Value : byte;

    BEGIN send($FE);
    send($F8);
    for i:=1 to 32 do
    BEGIN Value:=0;
    for j:=1 to 8 do
    BEGIN Value:=Value*$02 + ((get and $08) div $08);
    send($FB);
    delay(1);
    send($F8);
    END;
    Data[i]:=Value;
    END;
    case displaying of
    ’F’:full_displaying;
    ’S’:short_displaying;
    END;
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE writting;

    VAR i,n:integer;
    car:char;

    BEGIN write(’Which bit do you want to set to "1" : ’);
    readln(n);

    waiting;
    car:=readkey;

    send($FA);
    send($F8);
    for i:=1 to n do
    BEGIN send($F9);
    if i=n then
    BEGIN send($FD);
    delay(20);
    send($FF);
    delay(20);
    END;
    send($FB);
    END;
    reading;
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE Saving;

    VAR filename : string;
    f : text;
    i : word;

    BEGIN write(’Enter the filename: ’);
    readln(filename);
    assign(f, filename);
    rewrite(f);
    for i:=1 to byte_number do write(f,d2h(Data[i]),’ ’);
    close(f);
    END;

    {-----------------------------------------------------------------------------}

    PROCEDURE initialize;

    VAR i : integer;

    BEGIN byte_number:=32;
    displaying:=’F’;
    clrscr;
    writeln(’ 1 - to dump a 256 bits card’);
    writeln(’ 2 - to dump a 128 bits card’);
    writeln(’ F - to display in full format’);
    window(41,1,80,25);
    writeln(’ S - to display in short format’);
    writeln(’ F2 - to save in a file’);
    writeln(’ Q - to exit the program’);
    window(1,4,80,25);
    for i:=1 to 80 do write(’=’);
    window(1,5,80,25);
    END;

    {=============================================================================}

    BEGIN initialize;
    repeat waiting;
    car:=upcase(readkey);
    case car of
    ’W’:writting;
    ’Q’:;
    ’1’:byte_number:=32;
    ’2’:byte_number:=16;
    ’F’,’S’:displaying:=car;
    #00: BEGIN car:=readkey;
    if car=#60 then saving;
    END;
    else reading;
    END;
    until car=’Q’;
    END.
    踩过的脚印
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|数字电视开发网 ( 京ICP备16008897号-5 )

    GMT+8, 2026-5-2 03:58 , Processed in 0.147359 second(s), 27 queries , Gzip On.

    Powered by Discuz! X3.5

    © 2001-2026 Discuz! Team.

    快速回复 返回顶部 返回列表