CN101253667A - 电池充电器和利用交变dc充电电流的方法 - Google Patents

电池充电器和利用交变dc充电电流的方法 Download PDF

Info

Publication number
CN101253667A
CN101253667A CNA2006800258568A CN200680025856A CN101253667A CN 101253667 A CN101253667 A CN 101253667A CN A2006800258568 A CNA2006800258568 A CN A2006800258568A CN 200680025856 A CN200680025856 A CN 200680025856A CN 101253667 A CN101253667 A CN 101253667A
Authority
CN
China
Prior art keywords
battery
call
led
bit
equ
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CNA2006800258568A
Other languages
English (en)
Other versions
CN101253667B (zh
Inventor
托马斯·菲尼斯·约翰逊
约翰·S·怀廷
约翰·F·沃尔德伦
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Schumacher Electric Corp
Original Assignee
Schumacher Electric Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Schumacher Electric Corp filed Critical Schumacher Electric Corp
Publication of CN101253667A publication Critical patent/CN101253667A/zh
Application granted granted Critical
Publication of CN101253667B publication Critical patent/CN101253667B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Classifications

    • HELECTRICITY
    • H02GENERATION; CONVERSION OR DISTRIBUTION OF ELECTRIC POWER
    • H02JCIRCUIT ARRANGEMENTS OR SYSTEMS FOR SUPPLYING OR DISTRIBUTING ELECTRIC POWER; SYSTEMS FOR STORING ELECTRIC ENERGY
    • H02J7/00Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries
    • H02J7/007Regulation of charging or discharging current or voltage
    • H02J7/00711Regulation of charging or discharging current or voltage with introduction of pulses during the charging process
    • HELECTRICITY
    • H02GENERATION; CONVERSION OR DISTRIBUTION OF ELECTRIC POWER
    • H02JCIRCUIT ARRANGEMENTS OR SYSTEMS FOR SUPPLYING OR DISTRIBUTING ELECTRIC POWER; SYSTEMS FOR STORING ELECTRIC ENERGY
    • H02J5/00Circuit arrangements for transfer of electric power between ac networks and dc networks
    • HELECTRICITY
    • H02GENERATION; CONVERSION OR DISTRIBUTION OF ELECTRIC POWER
    • H02JCIRCUIT ARRANGEMENTS OR SYSTEMS FOR SUPPLYING OR DISTRIBUTING ELECTRIC POWER; SYSTEMS FOR STORING ELECTRIC ENERGY
    • H02J7/00Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries
    • HELECTRICITY
    • H02GENERATION; CONVERSION OR DISTRIBUTION OF ELECTRIC POWER
    • H02JCIRCUIT ARRANGEMENTS OR SYSTEMS FOR SUPPLYING OR DISTRIBUTING ELECTRIC POWER; SYSTEMS FOR STORING ELECTRIC ENERGY
    • H02J7/00Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries
    • H02J7/0042Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries characterised by the mechanical construction
    • H02J7/0045Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries characterised by the mechanical construction concerning the insertion or the connection of the batteries
    • HELECTRICITY
    • H02GENERATION; CONVERSION OR DISTRIBUTION OF ELECTRIC POWER
    • H02JCIRCUIT ARRANGEMENTS OR SYSTEMS FOR SUPPLYING OR DISTRIBUTING ELECTRIC POWER; SYSTEMS FOR STORING ELECTRIC ENERGY
    • H02J7/00Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries
    • H02J7/02Circuit arrangements for charging or depolarising batteries or for supplying loads from batteries for charging batteries from ac mains by converters

Landscapes

  • Engineering & Computer Science (AREA)
  • Power Engineering (AREA)
  • Charge And Discharge Circuits For Batteries Or The Like (AREA)

Abstract

本发明揭示一种电池充电器,其用于例如汽车和轮船型电池等各种电池。根据本发明的一方面,充电电流在非零DC充电电流电平之间交变。通过使所述充电电流在非零DC充电电平之间交变,电池可较快地充电到较高的容量(即,安培小时),因此缩短充电时间且同时允许所述电池充电器的额定值增加。根据本发明的另一重要方面,用于使所述充电电流交变的技术可在线性和开关模式电池充电器两者中实施。

Description

电池充电器和利用交变DC充电电流的方法
相关申请案的交叉参考
本申请案主张2005年7月15日申请的第60/700,059号美国临时申请案的优先权和权益。
技术领域
本发明涉及一种电池充电器,且更明确地说涉及一种针对线性和开关模式电池充电器两者的用于包含汽车和轮船型电池的各种类型电池的电池充电器,其中DC充电电流在非零平均DC充电电流电平之间交变,这允许缩短充电时间且还增加了电池充电器的容量。
背景技术
此项技术中已知各种类型的电池充电器。两种最普遍类型的电池充电器称为线性和开关模式电池充电器。线性电池充电器提供作为输入电压的线性函数的输出电压。未使用的充电功率被完全耗散。开关模式电池充电器较有效。利用此类开关模式电池充电器,仅消耗比产生充电电压和电流所需的输入功率稍多的功率。关于此类开关模式电池充电器存在。
电池充电器的充电特性通常经配置以与待充电电池的电池化学性质匹配。举例来说,通常用于汽车和轮船应用中的铅酸电池通常以恒定功率、恒定电流或恒定电压或其组合充电。已知此类电池用线性以及开关模式电池充电器两者充电。转让给与本发明的受让人为同一受让人的第US 2005/0088144 A1号美国专利申请公开案揭示用于汽车和轮船电池应用的开关模式电池充电器的实例。
许多不同考虑因素影响针对特定应用选择特定的电池化学性质。举例来说,铅酸电池由于其传递相对较大量的功率的能力而通常用于汽车和轮船电池应用中。在汽车应用中,需要初始功率突发来启动引擎。在轮船应用(例如,海岸警卫队应用)中,为了用于由美国海岸警卫队部署在美国周围海域中以将天气信息传输给海员的浮标中,电池容量是一个重要的考虑因素。
电池容量通常以安培小时为单位进行测量。理论上,安培小时容量是电池可传递指定电平的输出电流的小时数。由于电池内的损失的缘故,已知电池的安培小时输出能力稍小于安培小时输入。
在充电期间,有必要在不超过电池制造商所规定的电压、电流或温度(超过的话可能损坏电池)的情况下将电池充电到其完全充电状态。图1中说明示范性轮船电池的示范性电池充电特性曲线。在此实例中,曲线20说明充电电流。最大充电电流受电池制造商所提出的各种参数的限制,例如温度断开(TCO)、温度相对于时间的变化速率(dT/dt)、电流和其它参数。电池充电温度用曲线22标识。曲线24说明电池电压,而曲线26说明周围空气温度。在此特定实例中,在恒定电流模式期间在时间段t1期间,最大充电电流限于稍大于40安培的值。基于图1中说明的充电特性,标称充电循环的结束展示于点27处。可通过求得曲线20下方的面积的积分来获得由充电器施加到电池的安培小时。在此示范性情况下,输入到电池的安培小时为40.65Ah。
如上文所提及,由于电池内的内部损失的缘故,电池的输出容量将稍低于40.65安培小时。依据图2说明示范性放电曲线。如图所示,当测量端子电压时,根据图1的完全充电的示范性电池在10安培处放电。对于标称12伏汽车电池,所述电池在10安培处放电,直到端子电压达到约10.5安培为止,这约为235分钟,如点29所指示。因此,输出容量为10安培X 235分钟X 1小时/60分钟,或约39.2安培小时。
已知的充电器存在若干问题。首先,充电时间相对较长。第二,已知电池充电器的充电特性要求此类电池充电器额定在相对较低的值。
发明内容
本发明涉及一种电池充电器,其用于例如汽车和轮船型电池等各种类型的电池。根据本发明的一方面,充电电流在非零DC充电电流电平之间交变。通过使DC充电电流在两个非零充电电平之间交变,电池可较快地充电到较高的容量(即,安培小时),因此缩短充电时间且同时允许此类充电器的额定值用于相对较高电流应用中。根据本发明的另一重要方面,用于使平均DC充电电流交变的技术可在线性和开关模式电池充电器两者中实施。
附图说明
参看以下说明书和附图将容易理解本发明的这些和其它优点,附图中:
图1是通过已知电池充电器对示范性轮船电池进行充电的示范性充电曲线。
图2是结合图1利用的示范性轮船电池的示范性放电曲线。
图3是通过根据本发明的电池充电器对示范性轮船电池进行充电的示范性充电曲线。
图4是图3中说明的电池的示范性放电曲线。
图5是由根据本发明的开关模式电池充电器产生的示范性充电循环的图。
图6是说明叠加在同一照片上的由根据本发明的开关模式和线性电池充电器产生的示范性充电循环的图。
图7说明用于本发明的示范性100安培开关模式电池充电器的控制板的示范性示意图。
图8说明图7中说明的100安培开关模式电池充电器的配电板的示范性示意图。
图9是示范性60安培高频开关模式型电池充电器的控制板的示范性示意图。
图10是图9中说明的60安培电池充电器的配电板的示范性示意图。
图11是线性型电池充电器的控制板的示范性示意图。
图12是图11中说明的电池充电器的配电板的示范性示意图。
图13是线性推动的(linear-wheeled)线性电池充电器的控制板的示范性示意图。
图14是图13中说明的电池充电器的配电板的示范性示意图。
图15是说明总体控制回路的线性电池充电器的示范性流程图。
图16是说明主要控制回路的线性或高频电池充电器的示范性流程图。
图17是说明根据本发明的快速充电方法的线性或高频电池充电器的示范性流程图。
具体实施方式
本发明涉及一种电池充电器和一种对电池进行快速充电并增加电池的放电容量的方法。所述电池充电器用于(例如)各种类型的电池,例如汽车和轮船型电池、铅酸电池、深循环电池、AGM电池和其它电池类型,且可在线性和开关模式电池充电器拓扑两者中实施。根据本发明的一重要方面,平均DC充电电流在非零充电电流电平之间交变。通过使平均DC充电电流在非零充电电平之间交变,电池可充电到较高的电平,因此提供增加的输出容量且还可更快地进行充电。
图3中说明根据本发明的电池充电器的示范性充电曲线,而图4中说明示范性放电曲线。首先参看图3,通常由参考标号28标识的曲线说明充电电流。曲线30说明充电电压,而曲线32说明周围温度。曲线34说明电池温度。如图所示,曲线28说明在电池充电器的第一阶段(标识为t1)期间,平均DC充电电流波形在两个非零值之间交变,其中最大值稍许超过40安培且最小值约为15安培。最小和最大充电电流值具有以几秒、几十秒等计的周期。最小和最大充电电流的每一周期表示在零安培与某一正DC值之间变化的若干DC充电脉冲的DC平均值。举例来说,已知线性电池充电器产生120赫兹的充电电流脉冲。已知开关模式电池充电器产生高得多的频率的充电电流脉冲。然而,这些充电电流脉冲,不论是由线性电池充电器还是开关模式电池充电器产生,均具有预定工作循环、频率和量值,且可在特定时间段内进行平均以确定其平均值,例如通过DC安培计进行测量。本发明涉及使线性和开关模式电池充电器两者的充电电流脉冲的平均值在两个非零值之间变化。举例来说,如图3中所说明,DC平均值在15安培与40安培之间变化。
如图3中所说明,点35说明在约10.3小时处的完全充电状态。如上文所提及,曲线28下方的面积表示对于示范性电池的总体输入容量。在此实例中,以126.1安培小时对电池进行充电;其超过对于图1和2中说明的相同类型的电池的输入充电(input charge)的三倍。
如上文所提及,电池的放电容量由于电池内的内部损失的缘故而稍小于输入充电。如图4中所说明,电池在10安培处放电直到端子电压达到10.5伏为止。如点38所指示,认为电池在点38处或约646分钟时放电。因此,放电容量为10安培X 646分钟X一小时/60分钟或约107.7安培小时:与通过如图1和2中说明的已知电池充电器充电时的电池容量相比,存在150%的改进。
交变DC充电波形提供若干益处。首先,根据本发明的充电器允许较快地将较多能量抽运到电池中,藉此减少充电时间。第二,根据本发明的充电器允许电池充电器的额定值增加。举例来说,使用根据本发明的技术允许(例如)在40安培应用中使用15安培电池充电器。
根据本发明的一重要方面,DC交变充电电流技术适用于线性和开关模式充电器两者。图5说明开关模式充电器的示范性平均DC充电电流波形,而图6说明开关模式和线性充电器两者的示范性波形。
如图5所示,以参考标号40标识的示范性波形在两个非零平均DC电流值10安培与30安培之间交变,周期为270秒(420-150)或4分钟。如图所示,所述示范性波形提供30安培的平均DC充电电流持续75秒(240-165),以及10安培的平均DC充电电流持续150秒(420-270),总共225秒。
如图所示,电流波形可能由于实际DC充电脉冲(由示波器所测量)的相对较高频率的缘故而并非完美的方波,且事实上,可能在两个非零值之间斜线上升和斜线下降。举例来说,如图5中所说明,波形40的上升沿(以参考标号42标识)在(例如)15秒的一个示范性递增时间段中,在10安培的第一非零DC值与30安培的第二非零DC电流值之间斜线变化。波形40的下降沿(以参考标号44标识)在(例如)30安培的两个示范性递增时间段中,在标称30安培与10安培之间下降。
图6说明其它示范性充电波形。明确地说,图6说明对于开关模式和线性电池充电器两者在15安培DC与40安培DC之间交变的示范性DC充电电流波形。明确地说,曲线46说明开关模式充电波形,其类似于图5。曲线48说明线性型电池充电器的示范性交变充电波形。如图所示,线性型电池充电器的波形大体上为方波,其中波形的上升沿50和下降沿52实质上垂直于水平轴。
应理解,本发明的原理适用于具有各种周期的各种波形配置。还应了解,充电循环中的交变DC电流充电波形不需要为均一的。举例来说,在同一充电循环内,波形可在不同的上与下DC电流值之间变化,或者可相对恒定。并且,在特定充电循环内,波形的周期可变化。所有此类实施例均预期在本发明的当前范围内。
硬件
如上文所提及,本发明的原理适用于开关模式和线性模式电池充电器两者。图7-12中说明各种示范性线性和开关模式示意图。2005年4月28日公开的美国专利申请公开案US 2005/0088144 A1(以引用的方式并入本文中)中大体描述了示范性开关模式充电器硬件。图7-10说明开关模式电池充电器的示范性示意图,而图11-14说明线性型电池充电器的示范性示意图。明确地说,图7说明100安培开关模式电池充电器的控制板的示范性示意图。图8说明图7中说明的100安培开关模式电池充电器的配电板的示范性示意图。图9是示范性60安培高频开关模式型电池充电器的控制板的示范性示意图。图10是图9中说明的60安培电池充电器的配电板的示范性示意图。图11是线性型电池充电器的控制板的示范性示意图。图12是图11中说明的电池充电器的配电板的示范性示意图。图13是线性推动的线性电池充电器的控制板的示范性示意图。图14是图13中说明的电池充电器的配电板的示范性示意图。
本发明的原理适用于基本上任何线性或开关模式电池充电器或充电电路。一般来说,图7-14中说明的包含各种电池充电器电路的此类电池充电电路均包含功率电路和控制电路。处于控制电路的控制下的功率电路经配置以传递预定充电电流。举例来说,图7和8中说明的开关模式电池充电器经配置以传递2安培、15安培和40安培的可选择充电电流,以及100安培的引擎起动充电电流。图9和10说明经配置以传递2安培和60安培的可选择充电电流的示范性开关模式电池充电器。图11-13说明具有可选择的慢速、中速、快速和开始(或起动)充电电流的示范性线性电池充电器。
参看图7-14,所述示范性电池充电器的每一者包含若干选择器开关SW1、SW2和SW3,其使得能够选择所需的充电电流。如将更详细论述,这些开关的组合可用于特殊功能,例如手动模式。所述示范性电池充电器还可包含显示器和/或指示灯,其用于指示选定的充电模式且视需要可用于指示适当的启动序列。
每一电池充电器,不论是线性还是开关模式的,均包含微处理器或微控制器,例如ST Microelectronics型号ST6225C,如图7、9、11和13中大体说明。微控制器用于控制电池充电器并执行下文论述的软件。作为所述控制的一部分,微控制器监视开关SW1、SW2和SW3的状态如何并且还驱动指示灯,如下文将更详细论述。
还应理解,本发明的原理还适用于仅在单一充电电平下进行充电的电池充电器。换句话说,本发明的原理适用于其中充电电流不可选的电池充电器。认为所有此类配置均在本发明范围内。
软件
下文提供各种电池充电器的源代码。明确地说,文件6,000-P8.asm和10,000-PA.asm中标识的源代码分别针对图9、10和7、8中说明的60和100安培开关模式电池充电器。标识为71223D.asm;71224D.asm;和30060.asm的源代码文件可用于图11-14中说明的线性电池充电器。
图15-17中还说明根据本发明的电池充电器的示范性流程图。尽管图15和17适用于线性电池充电器(接通SCR的步骤除外),但这些图15和17通常也适用于开关模式电池充电器。图16和18适用于线性和开关模式电池充电器两者。
首先参看图15,说明总体控制回路。控制回路在电池充电器被加电的任何时间连续运作。明确地说,步骤100说明加电或重设状态。加电或重设之后,在步骤102中,系统检查电池充电器是否已置于测试模式中。可(例如)通过按下测试模式开关(未图示)或按下上文提及的开关SW1、SW2、SW3的组合来启始测试模式。如果电池充电器已置于测试模式中,那么系统在步骤104中依次点亮指示灯(例如,LED)中的每一者,并在步骤106中将控制转移到图16中说明的主要控制回路。
在步骤108中,系统检查电池充电器是否已置于手动模式中。可通过单独的开关(未图示)或通过按下开关SW1、SW2、SW3的组合或通过按下开关SW1、SW2、SW3中的一者或一者以上持续预定的时间段来选择手动模式。在手动模式中,电池充电器接通持续预定的时间段,而不管电池是否连接到电池充电器。如果电池充电器不处于手动模式中,那么系统在步骤110中通过检查电池充电器输出端子的电压是否小于预定值(例如,小于0.1伏DC)来检查电池是否连接到电池充电器。如果所述电压小于预定值,那么系统认为无电池连接到电池充电器端子并沿回路返回步骤100。如果电池充电器端子处的电压大于(例如)0.1伏DC,那么系统认为有电池连接到电池充电器端子并前进到步骤112、114和116,其说明图16中所说明的主要程序回路中的各个步骤。
在步骤116中,系统离开主要回路。在步骤118中,系统等待定时器中断或不可屏蔽中断(NMI)。明确地说,微控制器测量传入的AC输电线并响应于零交叉而产生不可屏蔽中断(NMI)。NMI用于切断SCR。NMI还启始软件定时器。当定时器超时时,在步骤121中接通SCR。切断SCR之后,在步骤122中读取并存储电池电压。在步骤122中还可维持电池电压的移动平均值。
图16是主要控制回路的流程图。初始地,在步骤124中,系统在加电或重设后启始。加电或重设后,在步骤126中,通过初始化I/O、RAM、闲置定时器和测试器模式而初始化电池充电器。一旦电池充电器初始化,就在步骤128中初始化任何电池显示。接着在步骤130中,针对特殊启动模式检查开关SW1、SW2、SW3的状态。举例来说,在线性电池充电器中,系统检查已借助开关SW1、SW2、SW3选择了“慢速”、“中速”还是“快速”充电模式。在步骤132中,系统检查电池充电器是否处于通电自检(POST)模式。如果不是,那么系统在步骤134中检查电池充电器是否处于手动模式,如上文所论述。如果不是,那么系统进入虚线框136内所示的主要程序回路。如果系统确定选择了手动模式,那么在系统进入主要程序回路136之前,在步骤138中设定软件旗标。
或者,如果系统在步骤132中确定电池充电器处于POST模式,那么在步骤140中依次点亮各个指示灯或LED。LED点亮之后,系统返回步骤130并检查开关SW1、SW2、SW3以获得选定充电速率。接着,系统再次检查电池充电器是否处于POST模式,如上文所论述。假定系统既不处于POST模式也不处于手动模式,那么电池充电器进入主要控制回路136。
进入主要控制回路开始于步骤142,其中系统检查电池充电器是否由于(例如)传入的AC功率的暂时损失的缘故而处于(例如)异常结束模式。如果是,那么系统前进到异常结束模式(状态8)。接着,系统在步骤146中检查电池充电器是否处于手动模式。如果是,那么在步骤148中电池充电器采取手动模式(状态15)。
在步骤150中,系统检查电池充电器在引擎启动之后是否正在冷却,即自从电池充电器提供100安培的电流以启动汽车引擎之后是否已过去了预定时间段。如果是,那么系统在步骤152中确定电池容量(例如,以%计)。检查电池容量之后,系统在步骤154中检查电池是否连接到电池充电器端子(如上文所论述)(在步骤154中),并在步骤168中根据选定的充电速率对电池进行充电。如果不是,那么系统在步骤156中采取默认充电状态(状态0)。
如果系统在步骤150中确定电池充电器不处于引擎冷却模式(如上文所论述),那么系统在步骤158中检查是否已针对特定充电速率(即,快速、中速或慢速)按下开关SW1、SW2、SW3。如果是,那么闲置模式,即不选择任何充电速率时的模式终止。接着,在步骤160中,电池检查是否已选择引擎启动模式。如果是,那么系统前进到步骤152并更新电池容量。如果不是,那么系统前进到步骤162并更新电池容量的任何显示。然后,系统在步骤164中检查电池充电器是否进入了闲置模式(即,充电速率开关被取消选定)。如果不是,那么系统在步骤166中检查电池充电器当前是否正在对电池进行充电。如果是,那么系统在步骤154中检查电池是否连接到电池充电器。如果是,那么系统在步骤168中跳到对应于选定的充电速率的状态。如果电池充电器不处于充电模式,如步骤166中所确定,那么系统前进到步骤168并前进到适当状态。
如果系统在步骤164中确定电池充电器处于闲置模式,那么系统在步骤170中检查是否已超过闲置时间限制。如果是,那么系统前进到步骤156,进入默认充电状态。如果未超过闲置时间限制,那么系统保持在闲置模式,除非电池充电器正在充电(如步骤166中所确定),且电池连接到电池充电器端子(如步骤154中所确定)。如果电池充电器不在充电(如步骤166中所确定),那么系统前进到步骤168并跳到适当状态。
图17是说明对于利用本发明原理并提供如上文所论述处于两个交变非零平均DC充电电流的充电波形的电池充电器的控制的流程图。图17中说明的流程图可配置为来自图15和16的主要程序的分支,只要选择器开关SW1、SW2、SW3选择了充电速率(例如,慢速(2安培)、中速(15安培)或快速(40安培))中的一者或一者以上。
如上文所提及,根据本发明的电池充电器提供如上文所论述处于交变非零平均DC电流值的充电电流的充电波形,从而界定快速充电模式。在步骤174中,设定较低平均DC充电电流值。明确地说,设定工作循环以及针对较低平均DC充电电流的定时器。举例来说,参看图5,设定所述波形将供应10安培的平均DC充电电流的工作循环和时间段。接着在步骤176中,系统检查针对较低平均DC充电电流的定时器是否已超时。如果不是,那么系统在步骤183中检查电池电压是否小于(例如)14.2伏。如果电池电压小于14.2伏,那么在步骤186中设定工作循环以实现恒定电流。如果电池电压大于14.2伏,那么系统在步骤188中继续充电。
如果较低速率定时器已超时,那么系统途经步骤180而前进到步骤178并设定工作循环和定时器以实现较高的平均DC值。参看图5,此对应于电池充电器供应30安培的工作循环和时间段。在步骤180中,系统首先确定电池充电器尚未在较高的平均DC充电电流下充电。如果电池充电器正在较高的平均DC充电电流下充电(如步骤182中所确定),那么系统在步骤184中检查电池电压是否小于(例如)Vmax+0.2伏。如果是,那么在步骤186中调节工作循环以实现恒定的平均DC充电电流。或者,如果电池正以较低速率被充电,那么系统在步骤183中检查电池电压是否已达到14.2伏。如果是,那么系统前进到步骤186并如上文所论述调节工作循环。系统接着在步骤176中检查针对较高平均DC充电电平的定时器是否已超时。一旦电池电压超过Vmax+0.2伏(如步骤184中所确定),就在步骤186中设定工作循环以实现较低平均DC充电电流,且系统在步骤188中继续在较低平均DC充电电流下充电。当在较低平均DC充电电流下充电时,在系统已检测到大于Vmax+0.2伏的电池电压之后,系统在步骤190中检查电池电压是否已整平。如果电池电压已整平,那么在步骤192中调节工作循环以实现恒定的充电电压,例如恒定15.5伏DC。系统在步骤194中检查工作循环是否已整平。如果不是,那么系统在步骤196中检查工作循环是否设定为最小值。如果不是,那么系统沿回路返回步骤192。如果是,那么在步骤198中调节工作循环以实现恒定的浮动电压,例如13.2伏。
如果系统在步骤190中确定电池电压电平未整平,那么系统在步骤200中检查电池电压是否=Vmax。如果是,那么系统返回步骤192并调节工作循环以实现恒定的充电电压。如果不是,那么系统返回步骤188并继续充电。
源代码
6000-P8.asm
Checksum
;Raw Code:76E28
;With Info:74B3D
;***************************************************************************
;*   COPYRIGHT 2006 SCHUMACHER ELECTRIC  *
;*     ALL RIGHTS RESERVED  *
;*     Schumacher High Frequency Auto Charger/Starter  *
;*  This code is for the SGS-THOMPSON micro-controler  *
;*  Part number ST62T15/ST62E15/ST62T25/ST62E25  *
;*         *
;*;*  ;***************************************************************************
 .title″HFS Ver.0.80″
 .LINESIZE 131
 .vers″ST6225″
 .romsize 4
 .W_ON
DEBUG.SET 1;1->normal,0->Ignore Type and Rate switches after SS5
SloRmp.SET 1;1->normal,0->Ramp slowly from min to max offset
NoDrop.SET 1;1->normal,0->Don′t calculate cable drop
ShoOff.SET 1;1->normal,0->Show OFFSET Alt% mode during charging
ShoReg.SET 1;1->normal,0->Flash LED′s to indicate up/down change
FastBI.SET 1;1->normal,0->7 minute Burn-In instead of 60 minutes
FastCP.SET 1;1->normal,0->7 min ChkProg interval instead of 60 min
;***************************************************************************
;*Define the port hardware locations  *
;***************************************************************************
;*At times,the.def statement is followed by a value and″!m″.The !m *
;*is used by the simulator/emulator for debugging.This symbol tells the  *
;*equipment what registers the user wants to monitor during debuging.     *
;***************************************************************************
X.def 80h!m         ;Index register
Y.def 81h           ;Index register
V.def 82h           ;Short direct register
W.def 83h           ;Short direct register
A.def 0ffh!m        ;Accumulator
DRA.def 0c0h!m         ;Port a data register
DRB.def 0clh!m         ;Port b data register
DRC.def 0c2h          ;Port c data register
DDRA.def 0c4h          ;Port a direction register
DDRB.def 0c5h          ;Port b direction register
DDRC.def 0c6h          ;Port c direction register
ORA.def 0cch         ;Port a option register
ORB.def 0cdh         ;Port b option register
ORC.def 0ceh         ;Port c option register
ADR.def 0d0h!m        ;A/D data register
ADCR.def 0d1h          ;A/D control register
PSC.def 0d2h        ;Timer prescaler register
TCR.def 0d3h!m       ;Timer counter register
TSCR.def 0d4h        ;Timer status control register
WDR.def 0d8h        ;Watchdog register
IOR.def 0c8h!m     ;Interrupt option register
DRWR.def 0c9h        ;Data rom window register
;***************************************************************************
;*   These are the ram equates used by the battery charger.     *
;***************************************************************************
DRAbuf .def 084h ;shadow ram for port A data register
DRBbuf .def 085h ;shadow ram for port B data register
DRCbuf .def 086h ;shadow ram for port C data register
ATemp .def 087h ;Accumulator temporary storage
XTEMP .def 088h ;X register temporary storage
MSECs1 .def 089h ;storage for 8.333ms tics-count of 120=1sec
SECs1 .def 08Ah ;storage for timer1 seconds
MINs1 .def 08Bh ;storage for timer1 minutes
HRs1 .def 08Ch ;storage for timer1 hours
TicFlag1 .def 08Dh ;overflow flags for SECs1,MINs1,and hours
MSECs2 .def 08Eh ;millisecond one counter
SECs2 .def 08Fh ;storage for timer2 seconds
MINs2 .def 090h ;storage for timer2 minutes
HRs2 .def 091h ;storage for timer2 hours
TicFlag2 .def 092h ;overflow flags for secs1,MINs2,and hours1
Tries .def 093h ;used by battery detect routines
TEMP .def 094h ;scratch pad area
TEMP1 .def 095h ;scratch pad area
Temp2 .def 096h ;count used for FreshBV
CurVolt .def 097h ;current battery voltage
MaintVolt .def 098h ;storage for MAINTAIN voltage level
OldVolt .def 099h ;previous battery voltage.used for dy/dt
CCDcnt .def 09Ah ;display countdown during crank cool down
OldOff .def 09Bh ;old value of OFFSET used in dI/dt
BADlo .def 09Ch ;low bits battery voltage average
BADhi .def 09Dh ;hi bits battery voltage average
Vmax .def 09Eh ;maximum battery voltage(per Battery Type)
Vref .def 09Fh ;ref voltage for desulfation
OFFSET .def 0A0h ;storage for phase delay value
FreshBV .def 0A1h ;avg batt volt used for di/dt ref
FBVTotLo .def 0A2h ;low byte of total used for FreshBV
FBVTotHi .def 0A3h ;high byte of total used for FreshBV
CurentSS .def 0A4h ;stores current charger state
Flags .def 0A5h ;charger configuration states
  ;bit 0(BatTypeA):0 for Ref,1 for D/C
  ;bit 1(BatTypeB):0 for Norm,1 for AGM/GEL
  ;bit 2(Rate):0 for Slow,1 for Fast
  ;bit 3(Crank):1 if in Boost mode
  ;bit 4(CrankWait):1 during E/S cool down
  ;bit 5(Started):1 if charging started
  ;bit 6(MtrUnits):0 for Volts,1 for %
  ;bit 7(MtrScale):0 for Batt,1 for Alt
Flags2.def 0A6h;stores the following Flags
  ;bit 0(Batt):1 if battery connected
  ;bit 1(NoOff):1 if no PWM off time(full on)
  ;bit 2(HiPwr):1 if outputis>10A
  ;bit 3(LoPwr):1 if output is on
  ;bit 4(NMInt):1 if NMI interrupt,0 if Timer
  ;bit 5(ChMode):1 if in Charger Mode
  ;bit 6(Wait0P):1 if waiting for % to change from 0
  ;bit 7(Alert):1 indicates Alert condition
Flags3.def 0A7h;stores the following Flags
  ;bit 0(Rmpng):1 during Rapid->Fast transition
  ;bit 1(Settle):1 during voltage settle time
  ;bit 2(RmpInt):1 during 1st half of each Ramp interval
  ;bit 3(Idle):1 until a button is pressed
  ;bit 4(RampUp):0->ramping down,1->ramping up
  ;bit 5(NxtCnt):1->1st second of count
  ;bit 6(Manual):1 if in Manual Mode
  ;bit 7(BurnIn):1 if in Burn-in Mode
SwDown.def 0A8h;Indicates state of switches(1->pressed)
  ;bit 4=SwOff flag(debugging)
  ;bit 5=Type switch
  ;bit 6=Rate switch
  ;bit 7=Meter switch
DigiDat2.def 0A9h;data for 8 of 16 segments of digital LED (0->ON,1->off)
  ;bit 0=digit 3 segments B & C
  ;bit 1=digit 2 segment F
  ;bit 2=digit 2 segment G
  ;bit 3=digit 2 segment A
  ;bit 4=digit 2 segment B
  ;bit 5=digit 2 segment C
  ;bit 6=digit 2 segment D
  ;bit 7=digit 2 segment E
DigiDat1.def 0AAh;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 1 segment C
  ;bit 1=digit 1 segment G
  ;bit 2=digit 1 segment D
  ;bit 3=digit 1 segment E
  ;bit 4=digit 2 decimal point
  ;bit 5=digit 1 segment F
  ;bit 6=digit 1 segment A
  ;bit 7=digit 1 segment B
SwData.def 0ABh;data for the 3 Rate and 3 Type LEDs(0->ON,1->off)
  ;bit 0=not used
  ;bit 1=Reg battery type LED
  ;bit 2=D/C battery type LED
  ;bit 3=AGM battery type LED
  ;bit 4=60A charge rate LED
  ;bit 5=10A charge rate LED
  ;bit 6=30A charge rate LED
  ;bit 7=2A charge rate LED
BitCnt .def 0ACh ;Index of bit sent to display
BytCnt .def 0ADh ;Index of word sent to display
DataBuf .def 0AEh ;Temp storage for Data bits
VltCnt .def 0AFh ;Counter for voltage display interval
LastBatt .def 0B0h ;stores battery reading used to monitor progress
RmpCnt .def 0B1 h;counts ramp intervals until next ramp
LEDnum .def 0B2h ;stores number to be shown on digital LED
Percent .def 0B3h ;stores percent to be shown on digital LED
Index .def 0B4h ;used for look up table access
Vdrop .def 0B5h ;estimate of voltage drop in output cable
VRcnt .def 0B6h ;Counter for voltage regulation interval
PcntL .def 0B7h ;NMI counter for percent display update
PcntH .def 0B8h ;Interval counter for percent display update
DspPcnt .def 0B9h ;storage for last percent displayed
Flags4 .def 0BAh ;stores the following Flags
  ;bit 0(IdleSet):1 if 10 minute Idle timer was started
  ;bit 1(NoRamp):1 during Manual Fast charge
  ;bit 2(SOC):  1 if at start of charge(1st 5s)
;free .def 0BBh ;free
;free .def 0BCh ;free
;free .def 0BDh ;free
;free .def 0BEh ;free
;free .def 0BFh ;free
;0BFh=last RAM location
;***************************************************************************
;*These are the constants used by the battery charger.*
;***************************************************************************
Volts005 .equ 008h ;0.5VOLTS
Volts0 .equ 00Ah ;0.7VOLTS
Volts01 .equ 00Fh ;1.0VOLTS
Volts09 .equ 087h ;very discharged battery voltage
Volts10 .equ 096h ;10.0VOLTS
BattMin .equ 0AFh ;lowest value in Battery % LUT
Volts12 .equ 0B4h ;low battery voltage
Volts122 .equ 0B7h
Volts125 .equ 0BCh
BattMax .equ 0BDh ;highest value in Battery % LUT
Volts127 .equ 0BEh
Volts128 .equ 0C0h ;good battery test voltage
Volts13 .equ 0C3h
Volts132 .equ 0C6h
Volts135 .equ 0CAh
AltMin .equ 0CBh ;lowest value in Alternator % LUT
Volts138 .equ 0CFh
Volts14 .equ 0D2h
Volts142 .equ 0D5h ;start monitoring dv/dt voltage
Volts1435 .equ 0D7h
Volts144 .equ 0D8h
Volts146 .equ 0DAh ;maximum allowed voltage for reg/gel mode
Volts147 .equ 0DCh ;start trickle timer voltage
Volts149 .equ 0E0h ;14.87V
Volts15 .equ 0E1h ;maximum allowed voltage for RV/DC Marine
Volts15a .equ 0E2h ;15.07V
AltMax .equ 0E7h ;highest value in Alternator % LUT
Volts155 .equ 0E9h ;maximum allowed voltage for Auto/Marine Starting
Volts16 .equ 0F0h ;maximum allowed voltage
Volts165 .equ 0F7h ;maximum allowed voltage for deep cycle 2
MaxVolts .equ 0FFh ;maximum voltage reading -17.0V
MaxDrpH .equ 00Eh ;maximum output cable voltage drop @ high power
MaxDrpL .equ 005h ;maximum output cable voltage drop @ low power
SRIM .equ 002h ;slow ramp interval multiplier=>secs/int
RCinit .equ 064h ;100 3/8-second intervals yields 37.5 seconds
RCinitX2 .equ 0C8h ;200 3/8-second intervals yields 75 seconds
RIinit .equ 02Dh ;45 NMI interrupts yields 0.375 seconds
;RIinit .equ 0B4h ;180 NMI interrupts yields 1.5 seconds
MSINIT .equ 078h ;millisecond initialization value(120)
MSS00 .equ 03Ch ;millisecond counter value for 500mS(60)
MS200 .equ 018h ;millisecond counter value for 200mS(24)
;MSINIT .equ 07Fh ;millisecond initialization value(127)
;MS500 .equ 03Fh ;millisecond counter value for 500mS(60)
SeeInit .equ 03Ch ;second initialization value(60)
MININIT .equ 03Ch ;minute initialization value(60)
MaxHrs .equ 25 ;maximum allowed charge hours+1
CPint .equ 60 ;minutes per charge progress interval
HR .equ 000h ;hours bit of TicFlag1 and TicFlag2
MIN .equ 001h ;minutes bit of TicFlag1 and TicFlag2
SEC .equ 002h ;seconds bit of TicFlag1 and TicFlag2
MSEC .equ 003h ;milliseconds bit of TicFlag1 and TicFlag2
VLO .equ 0C0h ;low line limit-100 VAC
VHI .equ 0EEh ;high line voltage limit-130 VAC
PCint .equ 00Ah ;number of 1-second intervals between % updates
FULLTIME .equ 0B4h ;half second when AC power is OFF
MinOff .equ 005h ;Min offset->max duty cycle
SlowAmps .equ 2 ;Nominal amps out at Slow rate
FastAmps .equ 10 ;Nominal amps out at Fast rate
RapAmps .equ 30 ;Nominal amps out at Rapid rate
CrnkAmps .equ 60 ;Nominal amps out at Crank rate
CodeRev .equ 0 ;software revision level
OffS1ow .equ 07Fh ;Nominal offset for slow charge(~20%)
OffRap .equ 071h ;Nominal offset for rapid charge(~40%)
OffBI .equ 0A4h ;Offset for max Burn-In charge(~6%)
OffCrank .equ 036h ;OFFSET for Crank standby
HiOff .equ 0A7h ;high limit for OFFSET variable
ABORT .equ 008h ;abort state
LEDslow .equ 007h ;Slow LED-bit of SwData
LEDrap .equ 006h ;Rapid LED-bit of SwData
LEDfast .equ 005h ;Fast LED-bit of SwData
LEDboost .equ 004h ;Crank LED-bit of SwData
LEDgel .equ 003h ;AGM/Gel LED-bit of SwData
LEDdeep .equ 002h ;Dp Cycl LED-bit of SwData
LEDreg .equ 001h ;Regular LED-bit of SwData
LEDdone .equ 000h ;Charged LED-PORT A
LEDchgng .equ 001h ;Charging LED-PORT A
LEDalert .equ 002h ;Fault LED-PORT A
LEDprcnt .equ 003h ;Percent LED-PORT A
LEDvolt .equ 004h ;Voltage LED-PORT A
LEDalt .equ 005h ;Altrntr LED-PORT A
SerData .equ 006h ;Serial Data-PORT A
ClrData .equ 007h ;Data Clear-PORT A
ShftClk .equ 000h ;Shift Clock-PORT B
LtchClk .equ 001h ;Latch Clock-PORT B
PWMlo .equ 002h ;Lo PWM crrl-PORT B
Disable .equ 003h ;Disable ctrl-PORT B
PWMhi .equ 007h ;Hi PWM ctrl-PORT B
FanCtl .equ 004h ;Fan control-PORT C
TypeSw .equ 005h ;Type switch-PORT C
RateSw .equ 006h ;Rate switch-PORT C
MeterSw .equ 007h ;Meter switch-PORT C
SwOff .equ 004h ;bit in SwDown for disabled Type & Rate switches
BatTypeA .equ 000h ;bit in Flags for battery type:0=Reg,1=D/C
BatTypeB .equ 001h ;bit in Flags for battery type:1=AGM/Gel Cell
Rate .equ 002h ;bit in Flags for charge rate:0=Slow,1=Fast
Crank .equ 003h ;bit in Flags that indicates engine start
CrankWait .equ 004h ;bit in Flags that indicates cool down between cranks
Started .equ 005h ;bit in Flags that indicates charge started
MtrUnits .equ 006h ;bit in Flags for meter units:0=volts,1=%
MtrScale .equ 007h ;bit in Flags for meter scale:0=batt,1=altrntr
Batt .equ 000h ;bit in Flags2:1 if battery is connected
NoOff .equ 001h ;bit in Flags2:1 if no PWM off time
HiPwr .equ 002h ;bit in Flags2:1 if output is>10A
LoPwr .equ 003h ;bit in Flags2:1 if output is on
NMInt .equ 004h ;bit in Flags2:1 if NMI interrupt,0 if Timer
ChMode .equ 005h ;bit in Flags2:1 if in Charger mode(not Tester)
Wait0P .equ 006h ;bit in Flags2:1 if battery>10V
Alert .equ 007h ;bit in Flags2:1 indicates trouble
Rmpng .equ 000h ;bit in Flags3:1 during Rapid->Fast transition
Settle .equ 001h ;bit in Flags3:1 during voltage settle time
RmpInt .equ 002h ;bit in Flags3:1 during 1st half each Ramp interval
Idle .equ 003h ;bit in Flags3:1 until a button is pressed
RampUp .equ 004h ;bit in Flags3:0->ramping down,1->ramping up
NxtCnt .equ 005h ;bit in Flags3:0 during last half of CCDcnt interval
Manual .equ 006h ;bit in Flags3:1 during Manual modes
BurnIn .equ 007h ;bit in Flags3:1 during Burn-In mode
IdleSet .equ 000h ;bit in Flags4:1 if 10 minute Idle timer was started
NoRamp .equ 001h ;bit in Flags4:1 during manual fast charge
SOC .equ 002h ;bit in Flags4:1 during Start Of Charge(1st 5 sec)
CrankOff .equ 002h ;crank off time in minutes(2)
CrankON .equ 008h ;crank on time in seconds(8)
CCDint .equ 001h ;crank cool down display counter interval(seconds)
CrankSS .equ 010h ;crank SS is state 16=10hex
Decimal .equ 004h ;bit in DigiDat1 for decimal point
Digit1 .equ 000h ;bit in DigiDat2 for most significant 1
DigiOffa .equ 11111111b ;bit pattern for all segements off
DigiOffb .equ 11111111b ;bit pattern for all segements off
DigiONa .equ 00000000b ;bit pattern for all segements ON
DigiONb .equ 00000000b ;bit pattern for all segements ON
Dashes1 .equ 11111101b ;bit pattern for all segements ON
Dashes2 .equ 11111011b ;bit pattern for all segements ON
SwsOff .equ 11111111b ;bit pattern for all switches off
DigiRev1 .equ 00010000b ;bit pattern to display_8
DigiRev2 .equ 01100001b ;bit pattern to display_P_
;***************************************************************************
;*               COLD START                         *
;***************************************************************************
;.org 0880h ;for ST6210/15
 .org 0100h ;for ST6220/25
RESET
CALL RstWDR ;reset watch dog timer
;***************************************************************************
;*             Clear The Ram Area              *
;***************************************************************************
RAMCLR
 LDI X,084h  ;point X to lst RAM Location
RAMCLR1
 CLR A  ;clear A
 LD(X),A  ;store A at location pointed to by X
 INC X  ;increment X
 LD A,X  ;get pointer in A
 CPI A,0C0h  ;test for end ofRAM
 JRNZ RAMCLR1  ;do again if not finished
;***************************************************************************
;*          Now Set Up The Hardware I/O Ports       *
;***************************************************************************
PORTA
 ;Bit 0=LED-Done(Ontput,0=ON)
 ;Bit 1=LED-Charging(Output,0=ON)
 ;Bit 2=LED-Alert(Output,0=ON)
 ;Bit 3=LED-Battery%(Output,0=ON)
 ;Bit 4=LED-Volts DC(Output,0=ON)
 ;Bit 5=LED-Altrntr%(Output,0=ON)
 ;Bit 6=Serial Data(Output,0=ON)
 ;Bit 7=Display Clear(Output,0=clear)
 ;Bit# 76543210
LDI DDRA,11111111b ;Set all bits as outputs
LDI ORA,11000000b ;open-drain outputs 0-5;6-7 push-pull
LDIDRA,11111111b ;Set initial values to 1(off)
LDI DRAbuf,11111111b ;store settings in shadow RAM
PORTB
 ;Bit 0=Shift clock (Output,0->1=Shift)
 ;Bit 1=Latch clock(Output,0->1=Latch)
 ;Bit2=0-10A PWM(Output,0=Off,1=10A)
 ;Bit 3=Disable out(Output,1=disabled)
 ;Bit 4=Remote sense(not used)
 ;Bit 5=Batt Voltage(Input,Analog)
 ;Bit 6=High Voltage(Input,Analog)
 ;Bit 7=10A-60A PWM(Output,0=10A,1=60A)
 ;Bit# 76543210
LDI DDRB,10011111b ;bits 5&6 are inputs,others are outputs
LDI ORB,00101111b ;Set push-pull outputs*,analog input
  ;*bit 7 is open drain output
LDI DRB,10111011b ;Set push-pull output,inputs=0
LDI DRBbuf,10111011b ;store settings in shadow RAM
PORTC
 ;Bit 4=Fan Control(Output,0=off,1=ON)
 ;Bit 5=Type switch(Input,0=IN/change)
 ;Bit 6=Rate switch(Input,0=IN/change)
 ;Bit 7=Meter switch(Input,0=IN/change)
  ;Bit# 76543210
 LDI DDRC,00011111b ;bit 4 is output,others are inputs
 LDI ORC,00011111b ;non-interrupt inputs,push-pull output
 LDI DRC,00001111b ;Set internal pull-ups for bits 5-7
 LDI DRCbuf,00001111b ;store settings in shadow RAM
 TSCRINIT
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 SET 4,IOR      ;enable interupts
 RETI
 CALL InitState  ;initialize to slow(2A)auto mode
;The next three lines are to set the maximum idle tester time
 CALL IniTime1  ;initialize timer 1
 LDI MINs1,0Ah  ;set timer 1 for 10 minutes
 SET Idle,Flags3  ;indicates no buttons pressed yet
;The next three lines set the unit for Tester(not Charger)mode
 RES ChMode,Flags2 ;set for Tester Mode
 CALL ShowData  ;initialize display
INIT_01
;JP MAIN  ;debug
;***************************************************************************
;*   Test Routines   *
;*This routine checks the switches at power up to determine whether to *
;*enter one of the test modes.The possible test modes and the switch *
;*combinations that trigger them are as follows.  *
;*        *
;*Meter Rate Type Test Mode      *
;*Y x N Power On Self Test(POST):LED′s light in sequence *
;*N Y N Manual Slow Charge(1 hour max for all manual mode)*
;*N N  Y Manual Medium Charge(Fast for boost models)*
;*N Y  Y Manual Fast Charge(Fast-Rapid for boost models)*
;*Y x Y Burn-In Mode:Fast/Rapid Charge for 60 minutes *
;*       *
;*Y->pressed,N->not pressed,x->either(not checked) *
;*       *
;***************************************************************************
TEST
 JRS MeterSw,DRC,NoPOST ;Skip ahead if Meter Mode button not pressed
 JRS TypeSw,DRC,POST ;Skip to POST if Type button not pressed
 JP TestBI  ;...otherwise,skip ahead to Burn-In setup
NoPOST
 JRR RateSw,DRC,TEST1 ;Check Type switch if Rate switch is pressed
 JRS TypeSw,DRC,NoTest ;go to MAIN if no switch is pressed
  ;Set for Manual Fast Charge
 RES HiPwr,Flags2  ;turn off high power mode
 SET Rate,Flags  ;turn on Fast LED
 SET NoRamp,Flags4 ;set for Fast rate w/o ramp up to Rapid
 SET NoOff,Flags2 ;set for full low power mode(Fast rate)
 .IFC EQ SloRrmp ;assemble next line only if debugging
 SET HiPwr,Flags2 ;turn on high power mode
 RES NoOff,Flags2 ;activate PWM(<100% duty cycle)
 .ENDC
 JP TestMM1  ;set for Manual charge
 NoTest
 JP MAIN  ;skip test and go to MAIN
TEST1  ;Set for manual Slow Charge
 JRR TypeSw,DRC,TEST2 ;if Type switch is pressed,set for Fast Test
RES NoOff,Flags2 ;activate PWM(<100% duty cycle)
LDI OFFSET,OffSlow ;set Offset for 2A
RES Rate,Flags  ;turn on Slow LED
 JP TestMM1  ;set for Manual charge
TestBI  ;Set for 60 minute Burn-In
 SET BurnIn,Flags3  ;Set for Burn-In mode
TEST2  ;set for Manual Rapid Charge
 SET Manual,Flags3 ;set for Manual mode
 SET Rate,Flags  ;turn on Fast LED
 SET HiPwr,Flags2 ;turn on high power
 RES NoOff,Flags2 ;activate PWM(variable duty cycle)
 RES NoRamp,Flags4 ;set for ramping
;JRS BurnIn,Flags3,TestRap ;don′t set for ramp down if Burn-In
 RES RampUp,Flags3 ;set for ramp down
 LDI RmpCnt,RCinit ;100 3-second intervals yields 2.5 minutes
 LDI OFFSET,OffRap ;set Offset for Rapid Charge
 CALL SetRamp  ;set ramping parameters
TestRap
 JP TestMM1  ;set for Manual charge
POST
 CALL Reset LEDs  ;turn off all type,rate & Status LED′s
 CALL MeterOff  ;turn off all meter mode LED′s
 CALL DigitsOff  ;turn off 3-digit LED
 RES LoPwr,Flags2 ;make sure output will be off
 CALL SetReg  ;set battery type for Regular
  CALL HoldType  ;show Type and wait a Fifth second
 SET BatTypeA,Flags  ;turn on Deep Cycle & turn off Regular LED
  CALL HoldType  ;show Type and wait a Fifth second
 SET BatTypeB,Flags  ;turn on Gel/AGM LED
 RES BatTypeA,Flags  ;turn on Gel/AGM LED
  CALL HoldType  ;show Type and wait a Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 SET ChMode,Flags2  ;must set flag to show rate LED′s
 RES Crank,Flags ;turn off Crank LED
 RES Rate,Flags  ;turn on Slow LED
 LDI LEDnum,SlowAmps ;set digital LED to show Slow rate
  CALL HoldRate  ;show Rate and wait a Fifth second
 SET Rate,Flags  ;turn on Fast LED
 LDI LEDnum,FastAmps ;set digital LED to show Fast rate
  CALL HoldRate  ;show Rate and wait a Fifth second
 SET HiPwr,Flags2 ;turn on Rapid LED
 LDI LEDnum,RapAmps ;set digital LED to show Rapid rate
  CALL HoldRate  ;show Rate and wait a Fifth second
 RES ChMode,Flags2 ;clear flag to disable output
 LDI LEDnum,CrnkAmps ;set digital LED to show Crank rate
 CALL ShowNum  ;get data to show the LED number
 CALL ShowCrank  ;turn on Crank(Boost)LED
 CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowData  ;update display
 SET MtrUnits,Flags ;set for % LEDs ON,volts LED off
 RES MtrSoale,Flags ;set for Alternator % LED off
 CALL HoldMtrMd  ;show meter mode and wait one fifth second
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
;CALL HoldMtrMd  ;show meter mode and wait one fifth second
;SET MtrUnits,Flags ;set for % LEDs ON,volts LED off
;SET MtrScale,Flags ;set for Alternator % LED ON
 LDI DigiDat1,DigiRev1 ;set digital LED to show Code Revision
 LDI DigiDat2,DigiRev2 ;set digital LED to show Code Revision
 CALL ShowData  ;update display
 CALL HoldMtrMd  ;show meter mode and wait one fifth second
 CALL MeterOff  ;turn off all meter mode LED′s
 CALL AlertON  ;turn on Alert(Red)LED
 CALL FifthSecond ;wait one Fifth second
 CALL ShowChgng     ;light Charging LED
 CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 LDI LEDnum,5  ;initialize to 5 to show 4 1st
POST2
 DEC LEDnum  ;the next number will be 1 less
 CALL NumData  ;get data for,and show LED number
 CALL FifthSecond ;wait one fifth second
 LD A,LEDnum  ;check for last number
 JRZ POST3  ;skip ahead if there
 JP POST2  ;...otherwise,loop back & repeat
POST3
 ADDI A,20  ;adding 20 changes 2nd digit
 LD LEDnum,A  ;prepare to show new number
 CALL NumData  ;get data for,and show LED number
 CALL FifthSecond ;wait one fifth second
 LD A,LEDnum  ;check latest number
 CPI A,100  ;compare to last number
 JRZ POST4  ;skip ahehad if there
 JP POST3  ;...otherwise,loop back & repeat
POST4
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ResetStatus ;turn off all three status LEDs
 CALL InitState  ;reset to Slow,TypeA charge mode
 RES ChMode,Flags2 ;set for Tester mode
 JP TEST  ;repeat POST if necessary
TestMM1  ;Set for manual charge
 SET Manual,Flags3 ;set for Manual mode
 SET ChMode,Flags2 ;set for Charger Mode(output enabled)
RES Disable,DRBbuf ;enable output
 LDI CurentSS,15 ;State 15 is Manual charge
 .IFC EQ SloRmp ;assemble next line only if debugging
 JRS BumIn,Flags3,TstBI
 LDI OFFSET,HiOff ;set Offset for minimum charge rate
;LDI OFFSET,150 ;set Offset for minimum charge rate**TEMP**
 LDI Tries,SRIM ;initialize ramp interval multiplier
 LDI CurentSS,6 ;State 6 slowly ramps charge rate
 LDI RmpCnt,240 ;...and re-initialize initerval counter(2 sec)
TstBI
 .ENDC
 SET Started,Flags ;set Flags for charge started
 SET LoPwr,Flags2 ;tell PwrCon charger is on
CALL IniTime1  ;initialize Timer1
LDIHRsl,1  ;set Timer1 for 1 hour
.IFC EQ FastBI ;assemble next line only if not debugging
LDI MINsl,7  ;set Timer1 for 0 hrs,7 mins
.ENDC
.IFC EQ SloRmp ;assemble next line only if debugging
JRS BurnIn,Flags3,TestMM2
LDI SECsl,15  ;set Timer1 for 15 seconds
.ENDC
JRR BurnIn,Flags3,MAIN ;skip next 2 lines if not Burn-in
TestMM2
;LDI HRsl,4  ;set Timer1 for 4 hours
;LDI MINs1,19  ;set Timer1 for 3 hrs,19 mins
CALL IniTime2  ;reset Timer2
LDI MINs2,1  ;set timer for counter interval(1 minute)
.IFC EQ FastBI ;assemble next line only if debugging
LDI CCDcnt,7  ;set Burn-in minute counter to 7
.ELSE
LDI CCDcnt,60  ;set Burn-in minute counter to 60
.ENDC
;***************************************************************************
;*                MAIN                    *
;***************************************************************************
;***************************************************************************
;*Because the A/D voltage is being averaged,it would take considerable  *
;*time to notice that a battery has become disconnected.To overcome this *
;*DELAY the program will monitor the instantaneous voltage each time thru *
;*the loop to detect this condition.This check will be made only if the  *
;*unit is in a charging mode.                            *
;***************************************************************************
MAIN
 CALL RstWDR  ;reset watch dog timer
 LD A,CurentSS  ;get current state
 SUBI A,ABORT  ;check for abort
 JRNZ MainMore  ;continue Main if not Abort
 JP MAIN3  ;don′t continue Main if Abort
MainMore
 JRR Manual,Flags3,MainAuto ;continue Main if not Manual Mode
 .IFC EQ SloRmp  ;assemble next line only if debugging
 JRS BurnIn,Flags3,MainBI
 JP SS6  ;slowly ramp charge rate
MainBI
 .ENDC
 JP SS15  ;otherwise,goto Manual charge
MainAuto
 JRS CrankWait,Flags,MAIN1;don′t check switches during Crank wait
 CALL CheckSw  ;check if switch is being pressed
MAIN4
 JRS Crank,Flags,MAIN0  ;skip ahead if during Crank
 CALL GetPercent  ;update the percentage reading
 CALL UpdateBP    ;update % to display
 CALL GetMeter  ;update display
 JRR Idle,Flags3,MAIN0  ;skip ahead if not idle
 JRR Batt,Flags2,MAIN0  ;don′t check idle time limit if no battery
 JRS IdleSet,Flags4,MAIN5;don′t set idle timer if already set
 CALL IniTimel  ;...otherwise initialize timer 1
 LDI MINs1,0Ah  ;set timer 1 for 10 minutes
 SET IdleSet,Flags4  ;Idle timer started,set flag
MAIN5
 JRR MIN,TicFlag1,MAIN0 ;...otherwise,check idle time limit
 RES Disable,DRBbuf  ;...enable output after idle time limit
 JP MAIN2  ;...and re-initialize if reached
MAIN0   ;not Crank,check for 0 or 1
 JRS LoPwr,Flags2,MAIN1 ;charger is ON,goto 0V check
 JRR LEDchgng,DRAbuf,MAIN1 ;charger is almost on,goto 0V check
 JP MAIN3  ;charger is OFF,goto Main3
MAIN1  ;Check for disconnected battery
;CALL Get Percent ;update the percentage reading
 CALL CheckBatt  ;check for disconnected battery
 JRS Batt,Flags2,MAIN3 ;skip ahead if connected
MAIN2  ;0V detected,prepare to start over from state 0
 LDI DspPcnt,0  ;initialize display Percent to 0
 CALL InitState  ;initialize to Slow Regular Charge mode
MAIN3
;***************************************************************************
;*            SEQUENCE STATE JUMP TABLE                 *
;*Determine what routine to execute on this pass through the the loop.Only*
;*one routine is executed each time through the loop.             *
;***************************************************************************
NSS0
 LD A,CurentSS
 JRNZ NSS1
 JP SS0 ;* SS0-BATTERY DETECT *
NSS1
 CPI A,001h
 JRNZ NSS2
 JP SS1;* SS1-BATTERY DETECTDELAY *
NSS2
 CPI A,002h
 JRNZ NSS3
 JP SS2;* SS2-AUTOMATIC CHARGE START *
NSS3
CPI A,003h
JRNZ NSS4
JP SS3 ;*SS3-BELOW 9 Volts *
NSS4
 CPI A,004h
 JRNZ NSS5
 JP SS4;* SS4-BELOW 12 Volts *
NSS5
 CPI A,005h
 JRNZ NSS6
 JP SS5 ;* SS5-NORMAL CHARGE *
NSS6
 CPI A,006h
 JRNZ NSS8
 JP SS6;* SS6-RAMP CHARGE RATE * *DEBUG*
;NSS7
;CPI A,007h
;JRNZ NSS8
;JP SS7;* SS7-CHARGE COMPLETE *NOT USED
NSS8
 CPI A,008h
 JRNZ NSS9
 JP SS8;* SS8-ABORT CHARGE *
NSS9
 CPI A,009h
 JRNZ NSS11
 JP SS9;* SS9-DESULFATION *
;NSS10
;CPI A,00Ah
;JRNZ NSS11
;JP SS10;* SS10-RESTORE CHARGE *
NSS11
 CPI A,00Bh
 JRNZ NSS12
 JP SS11;* SS11-dV/dtMONITOR *
NSS12
 CPI A,00Ch
 JRNZ NSS13
 JP SS12;*SS12-dI/dtMONITOR *
NSS13
 CPI A,00Dh
 JRNZ NSS14
 JP SS13;*SS13-ENDCHARGE *
NSS14
 CPI A,00Eh
 JRNZ NSS15
 JP SS14;* SS14-MAINTAIN *
NSS15
 CPI A,00Fh
 JRNZ NSS16
 JP SS15;* SS15-Manual *
NSS16
 CPI A,010h
 JRNZ NSS17
 JP SS16;* SS16-CRANK *
NSS17
 CPI A,011h
 JRNZ NSS18
 JP SS17;* SS17-CRANK *
NSS18
 CPI A,012h
 JRNZ NSS19
 JP SS18;* SS18-CRANK *
NSS19
 CPI A,013h
 JRNZ NSS20
 JP SS19;* SS19-CRANK *
NSS20
 CPI A,014h
 JRNZ NSS21
 JP SS20;* SS20-CRANK *
NSS21
 LDI WDR,001h    ;invalid sequence state,reset
;***************************************************************************
;*                 END OF MAIN    *
;*Wait for NMI,which indicates end of FET on period,before measruing *
;*battery voltage.                           *
;***************************************************************************
ExitMain
XMain
WAIT   ;wait for interupt
JRS NMInt,Flags2,XMain ;timer interupt???
;***************************************************************************
;*             READ BATTERY VOLTAGE                   *
;*  This routine is executed at or near zero cross.The current voltage *
;*is stored in CurVolt and the reading is added to BADhi(two locations).*
;*BADhi will contain a running average of the last 256 readings.      *
;***************************************************************************
BADREAD
 LD A,BADlo  ;get average reading
 SUB A,BAdhi  ;subtract one reading from the running total
 JRNC BADREAD1  ;no carry,go on
 DEC BADhi  ;adjust high order bits
BADREAD1
 LD BADlo,A  ;store new value
 LDI ADCR,0B0h ;start A/D conversion
 LDI ADCR,0B0h ;do again to insure a valid start
 WAIT   ;let the interupt notify us when data is ready
 LD CurVolt,A ;save current reading
 ADD A,BADlo  ;add into running average
 JRNC BADREAD2  ;no carry,go on
 INC BADhi  ;increment high bits
BADREAD2
 LD BADlo,A  ;store new low bits
;LDI ORB,01Fh
;LDI ORB,09Fh
;***************************************************************************
;*             di/dt AVERAGE CALCULATION              *
;*For use by the di/dt,about four times every second the average of the *
;*previous 32 curvolt readings is stored in FreshBV for comparison to a *
;*reading taken once every second.     *
;***************************************************************************
DIDTAVG
 LD A,Temp2   ;if Temp2=0 then first reading
 JRNZ DIDTAVG1 ;skip init if not 1st reading
 LDI Temp2,020h ;initialize Temp2 to 32
DIDTAVG1
 LD A,FBVTotLo;
 ADD A,CurVolt ;add current voltage to total
 JRNC DIDTAVG2 ;don′t inc high byts if no carry
 INC FBVTotHi ;inc high byte
DIDTAVG2
 LD FBVTotLo,A ;update total
 DEC Temp2 ;update Temp2
 JRZ DIDTAVG3 ;compute avg
 JP DIDTAVGX ;exit to Main
DIDTAVG3
 LDI Temp2,003h ;prepare to shift 3 times
DIDTAVG6
 LD A,FBVTotHi ;load high byte of total into accumulator
 SLA A  ;shift accumulator left
 LD FBVTotHi,A ;update high byte of total
 LD A,FBVTotLo ;load low byte of total into accumulator
 SLA A  ;shift accumulator
 LD FBVTotLo,A ;update low byte of total
 JRNC DIDTAVG4 ;msb was zero,skip next line
 INC FBVTotHi;
DIDTAVG4
 DEC Temp2 ;dec loop counter
 JRZ DIDTAVG5 ;if zero,finish average
 JP DIDTAVG6 ;not zero,shift again
DIDTAVG5
 LD A,FBVTotHi ;store average in FreshBV
 LD FreshBV,A
 CLR FBVTotHi
 CLR FBVTotLo
DIDTAVGX
 JP MAIN
;***************************************************************************
;*This is where the sequence states are defined.The number of a given    *
;*sequence state has no relevance to the order in which it is actually  *
;*executed.Any given state can give control to any other state.       *
;***************************************************************************
;***************************************************************************
;*              BATTERY DETECT                   *
;*This is the charger idle state.The program remains here until a battery *
;*is detected.Dectection is determined by finding a positive voltage    *
;*greater than one volt.                               *
;***************************************************************************
SS0
 .IFC EQ DEBUG ;assemble next line only if debugging
 RES SwOff,SwDown ;set to check Type and Rate switches
 .ENDC
;LDI Percent,0  ;set Percent to 0
 CALL ShutOff  ;low & high power,fan,& crank off;min duty
 CALL ShowRate  ;turn on charge rate LED(Slow or Fast)
 CALL ShowType  ;turn on battery type LED(Reg,D/C or Gel)
 RES SOC,Flags4 ;clear Start Of Charge flag
 JRS ChMode,Flags2,Ready ;continue routine if in Charger Mode
 CALL CheckBatt  ;...otherwise,check if tester should show 0′s
 JP SS0EXIT  ;...and exit
Ready
 JRR Started,Flags,SS00;skip if output hasn′t been on
 RES Started,Flags ;set Flags for charge not started
SS00
 LD A,FreshBV  ;check latest average voltage
 JRNZ SS0_1  ;Is it 0(exactly)?
 CALL ShowRed  ;turn on Red LED until battery is detected
 JP SS0EXIT  ;...Yes:must be rev.batt,so stop
SS0_1
 CALL IniTime1  ;set up timer
 LDI SECs1,002h ;adjust for 2 seconds
 LDI Tries,005h ;5 Tries for debounce
 SET 0,CurentSS  ;go on to BATTERY DETECT DELAY
SS0EXIT
 JP ExitMain
;***************************************************************************
;*BATTERY DETECT DELAY   *
;*This state checks that a voltage is present for three seconds.If the *
;*voltage drops below 1 Vdc,the timer is restarted and the″try″counter *
;*is decremented.If after 5 Tries the voltage has not been above 1 Vdc *
;*for 3 seconds,go back to battery detect.This delay has the effect of *
;*debouncing the leads being connected to the battery.  *
;***************************************************************************
SS1
 CALL CheckBatt  ;check for connected battery
 JRS Batt,Flags2,SS1_1 ;yes,check if it has been two seconds
 JP SS1_2  ;no,subtract a try
SS1_1
 CALL ShowChgng ;turn Charging LED on
 JRR 2,TicFlag1,SS1EXIT ;go on if time is up,otherwise exit
 LDI OldVolt,000h ;clear OldVolt before entering SS2
 LDI TEMP1,000h ;clear Temp1 before entering SS2
 INC CurentSS  ;go on to start charge
 JP SS1_3  ;set timer for 2 seconds
SS12_;NOTE:Tries set to 5 in SS0
 DEC Tries  ;subtract a try
 JRNZ SS1_3  ;try again if not too many Tries
 DEC CurentSS  ;...otherwise,go back to idle(state 0)
 JP SS 1EXIT  ;...and exit routine
SS1_3
 CALL IniTime1  ;reset timer and try again
 LDI SECs1,002h ;adjust for 2 seconds
SS1EXIT
 JP ExitMain
;***************************************************************************
;*  AUTOMATIC CHARGE START   *
;*This state gets the battery voltage and decides how to continue the *
;*the charge.The maximum allowed charge time is also started.*
;***************************************************************************
SS2
;NOTES:OldVolt SET TO 0 IN SS1
;TEMP1 SETTO 0 AT RESET
FASTAVG
 DEC TEMP1  ;decrease Temp1 one count(starts at 0)
   ;have we counted down to 0?
 JRZ FASTDONE  ;yes,jump to FASTDONE
 LD A,TEMP  ;no,load previous TEMP value
 ADD A,CurVolt  ;add CURVOLT,Did we overflow the counter?
 JRNC OVER  ;no,jump to OVER
 INC OldVolt  ;yes,bump up the running average
OVER
 LD TEMP,A  ;store the latest value in TEMP
JP SS2EXIT  ;exit and go update CurVolt
FASTDONE
 LD A,TEMP  ;load previous TEMP value
 ADD A,CurVolt  ;Did we overflow the counter one last time?
 JRNC OVER2  ;no,jump to OVER2
 INC OldVolt  ;yes,bump up the running average one last time
OVER2
 CALL CheckBatt  ;Check to see if battery was removed during FastAvg
 JRS Batt,Flags2,SS2_0c ;Still connected-continue
 LDI CurentSS,0 ;not connected-go back to state 0
 JP SS2EXIT  ;...and exit State 2
SS2_0c
 LD A,OldVolt  ;get 0ldVolt(initial battery voltage)
 LD BADhi,A  ;initialize BADhi to OldVolt
;LD A,Percent  ;get updated %
 LD A,DspPcnt  ;compare to last % displayed
 JRNZ SS2_GP  ;if % previously shown,skip ahead
 CALL GetPercent ;update Percent for initial voltage
 LD A,Percent  ;get latest %
 LD DspPcnt,A  ;store latest % in Display Percent
 RES Wait0P,Flags2 ;set flag to indicate not waiting
 JP SS2_BP  ;skip ahead
SS2_GP
 CPI A,100  ;check for 100%
 JRNZ SS2_BP  ;continue State 2 if not 100%
 JP SS5_Maint  ;...otherwise,go to Maintain
SS2_BP
 CALL ShowChgng  ;turn Charging LED on
 CALL IniTime1  ;initialize timer 1
 LDI MINs1,1  ;set timer 1 for 1 minute
 LDI SECs1,005h ;set timer 1 for 5 seconds
 LDI CCDcnt,MaxHrs ;set interval counter to MaxHrs
 SET SOC,Flags4 ;set Start Of Charge flag
 CALL IniTime2  ;initialize timer 2
 LDI SECs2,001h ;set timer for 1 second
 LDI MSECs2,MS500 ;set timer for 500 milliseconds(0.5secs)
 LDI MINs2,006h ;set timer for 5 minutes and 2 seconds
 LDI HRs2,005h  ;set timer for 4 hours,5 minutes & 2 seconds
 RES HiPwr,Flags2  ;turn off high power rnode
 JRS Rate,Flags,SS2_0 ;skip ahead if set for 10A
  ;...otherwise,set for 2A charge
 RES NoOff,Flags2 ;activate PWM(<100% duty cycle)
 LDI OFFSET,OffSlow ;set Offset for 2A
 JP SS2_0a  ;skip ahead and read voltage
SS2_0  ;set for 10A charge
 SET NoOff,Flags2 ;de-activate PWM(100% duty cycle)
 LDI OFFSET,HiOff ;set Offset for minimum duty cycle
 CALL SetRmpUp ;prepare to ramp from Fast to Rapid
SS2_0a
 LD A,BADhi  ;get latest avg batt voltage
 CPI A,Volts09  ;very low battery?
 JRNC SS2_2  ;no,try next limit
SS2_1  ;Battery<9V
 LDI_A,003h  ;yes,service it,below 9 VOLT SS
 JP SS2_5
SS2_2  ;Battery>9V
 CPI A,Voltsl2  ;low battery state?
 JRNC SS2_4  ;no,goto SS5
SS2_3  ;9V<Battery<12V
 LDI A,004h  ;yes,service it,below 12 VOLT SS
 JP SS2_5
SS2_4  ;Battery>12V
 LDI A,005h  ;normal charge SS
SS2_5
 LD CurentSS,A  ;prepare to go to the correct state(3,4 or 5)
 SET Started,Flags  ;set Flags for charge started
 CALL TurnON  ;turn output,Fan,and Charging LED on
 SET Settle,Flags3  ;initial charge voltage settle mode
SS2EXIT
 JP ExitMain
;***************************************************************************
;*              BELOW 9 Volts    *
;*  Battery is extremely discharged and may be bad.Charge for a maximum *
;*of five minutes.If voltage does not come above 9 Volts in this time *
;*period,abort charge.Otherwise,go to below 12 Volts.  *
;***************************************************************************
SS3
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRS SEC,TicFlag2,SS3_0;continue if voltage settle time expired
 JP SS3EXIT  ;...otherwise,just exit
SS3_0
 RES Settle,Flags3 ;clear settle flag
 JRR MIN,TicFlag2,SS3_1 ;check if time has expired
 LDI CurentSS,ABORT ;yes,time to abort
 JP SS3EXIT
SS3_1  ;not 5 mins yet
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts09  ;is battery up to 9V?
 JRC SS3EXIT          ;continue state 3 if<9V
 INC CurentSS  ;...otherwise,go to state 4
SS3EXIT
 JP ExitMain
;***************************************************************************
;*              BELOW 12 Volts                *
;*Battery is very low.Allow a maximum of 4 hours for the voltage to  *
;*rise above 12 volts under charge.If voltage does not come up,go to  *
;*abort charge.Otherwise go to normal charge.                    *
;***************************************************************************
SS4
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRS SEC,TicFlag2,SS4_0 ;continue if voltage settle time expired
 JP SS4EXIT  ;...otherwise,just exit
SS4_0
 RES Settle,Flags3  ;clear settle flag
 JRR HR,TicFlag2,SS4_i ;check if time(4 hours)has expired
 LDI CurentSS,ABORT ;yes,time to abort
 JP SS4EXIT  ;exit routine
SS4_1
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Voltsl2  ;is battery up to 12V?
 JRC SS4EXIT           ;...fi not,just exit
 INC CurentSS  ;...otherwise,go to state 5
SS4EXIT
 JP ExitMaiu
;***************************************************************************
;*   NORMAL CHARGE    *
;*Program stays here until the voltage reaches 14.2 volts or the maximum *
;*charge time is exceded.If the voltage limit is reached the program *
;*will transfer to:     *
;*A.SSB(dV/dt)if the the battery has been charging more than 5  *
;*  minutes or         *
;*B.SS9(Desulfation)if the OCV was less than 12.2 volts or  *
;*C.SS14(Maintain)if the OCV was more than 12.2 volts  *
;*      *
;*If the maximum charge time is exceded the program will abort  *
;*         *
;***************************************************************************
SS5
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL ChkRapid  ;update Ramp timer,if necessary
 .IFC EQ DEBUG ;assemble next line only if debugging
 SET SwOff,SwDown ;set to ignore Type and Rate switches
 .ENDC
 JRS SEC,TicFlag2,SS5_0 ;continue if voltage settle time expired
 JP SS5EXIT  ;...otherwise,just exit
SS5_0
 RES Settle,Flags3  ;clear flag
 CALL BattProg  ;check battery voltage for charge progress
 JRR HR,TicFlag1,SS5_0a ;skip next line if max time not expired
;  NOTE:CurentSS set to ABORT by BattProg.ChkProg
 JP SS5EXIT  ;exit(and abort)if max time expired
SS5_0a
 CPI_A,Volts142  ;check if up to 14.2 volts yet
 JRNC SS5_2  ;yes,check if>5 minutes
 JP SS5EXIT  ;otherwise,just return
SS5_2
 LDIHRsl,CCDcnt ;set Timer1 hours(minutes set by BattPRog)
 RES HiPwr,Flags2  ;set for low power mode
 RES Rmpng,Flags3  ;clear flag before moving on
 RES RmpIut,Flags3  ;clear flag before moving on
 RES Settle,Flags3  ;clear flag before moving on
 JRS MIN,TicFlag2,SS5_3 ;if>5 min,go to dV/dt
 LD A,OldVolt  ;otherwise,check initial voltage
 CPI A,Volts122  ;initial voltage<12.2V?
 JRC SS5_5  ;Yes:then desulfate
 JP SS5_Maint  ;No:goto Maintain
SS5_5
 LDI CurentSS,009h ;battery is sulfated
 LDI MaintVolt,Volts16 ;try to hold battery at 16V
 LDI Vref,Volts15  ;and see if it drops to 15V
 CALL IniTime2  ;
 LDI HRs2,002h  ;in less than 2 hours
 JP SS5EXIT  ;
SS5_3
 JRR Rate,Flags,SS5_6 ;check for Fast charge rate
 LDI OFFSET,MinOff ;min Fast offset value(max current)
SS5_6
 LD A,OFFSET  ;get OFFSET
 LD OldOff,A  ;store OFFSET into OldOff
 LDI CurentSS,00Bh  ;goto wait for dv/dt trip voltage
 LDI Percent,77  ;set Percent to 77
 CALL IniTime2
 LDI MINs2,0Dh  ;set to 13 minutes for dV/dt
 LD A,BADhi  ;get latest battery voltage
 LD MaintVolt,A  ;store as maintain voltage for di/dt
 LDI Tries,004h ;initialize dV/dt for 4 Tries (3 intervals)
 JP SS5EXIT  ;
SS5_Maint  ;goto MAINTAIN,battery is already charged???
 LDI Percent,100  ;set Percent to 100
 LDI MaintVolt,Volts132 ;set maintain voltage to 13.2V
 JRR BatTypeB,Flags,SS5_7 ;skip ahead if not Gel/AGM
 LDI MaintVolt,Volts 135 ;set maintain voltage to 13.5V for Gel &AGM
SS5_7
 LDI_CurentSS,00Eh ;Maintain is state 14(0E hex)
 RES NoOff,Flags2 ;activate PWM(<100% duty cycle)
 CALL ShutOff  ;low & high power,fan,& crank off;min duty
 DEC OFFSET  ;MAX offset-1 value->min duty cycle
SS5EXIT
 JP ExitMain
;***************************************************************************
;*         SS6-RAMP CHARGE RATE   *
;*        *
;*Slowly decrease OFFSET from HiOff down to OffRap or MinOff to in- *
;*crease output current for debugging.Reset when done.  *
;*         *
;***************************************************************************
SS6
 .IFC EQ SloRmp ;assemble SS6 routine only if debugging
 CALL ShowRate  ;turn on the 2A or 15A LED
 CALL GetMeter  ;update display
 CALL TurnON  ;turn output,Fan,and Charging LED on
 JRS SEC,TicFlag1,SS6_0 ;wait a few seconds before ramping
 JP SS6_x  ;...otherwise,just exit
SS6_0
 LD A,OFFSET  ;otherwise,get latest offset
 JRR Rate,Flags,SS6_2 ;skip if not set for rapid
 CPI A,OffRap  ;has OFFSET been decreased to OffRap?
 JRZ SS6_3  ;...if so,done ramping
 JP SS6_4  ;...otherwise,keep ramping
SS6_2
 CPIA,MinOff  ;
 JRNZ SS6_4  ;continue if not done ramping
SS6_3
 JP SS6_1  ;finish if done ramping
SS6_4
 DEC RmpCnt  ;decrement interval counter
 JRZ SS6_8  ;update display if interval has elapsed
 JP SS6_x  ;...otherwise,just exit
SS6_8
 JRS_MtrScale,Flags,SS6_6  ;skip ahead if already showing OFFSET
 SET MtrUnits,Flags  ;set for Volts LED off,batt% LED on
 SET MtrScale,Flags  ;set for Alt % LED on,batt% LED off
 JP SS6_7
SS6_6
 RES MtrScale,Flags ;set for Alternator % LED off
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
SS6_7
 DEC Tries  ;decrement interval multilier
 JRNZ SS6_5  ;skip ahead if not zero
 DEC OFFSET  ;...otherwise,increase OFFSET(reduce current)
 LDI Tries,SRIM ;...and re-initialize interval multiplier
SS6_5
 LDI_RmpCnt,240  ;...and re-initialize interval counter(2 sec)
SS6_x
 JP ExitMain  ;wait for next NMI
SS6_1
 JP RESET  ;all done,reset to power up state
 .ENDC
SS7
;***************************************************************************
;*        SS8-ABORT CHARGE   *
;*       *
;*Turn off all LED′s.Blink TROUBLE LED at half second interval.If *
;*battery becomes disconnected,re-initialize.   *
;*         *
;***************************************************************************
SS8
 JRS Alert,Flags2,SS8_0 ;skip ahead if flag already set
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL IniTime2  ;initialize Timer2 for output discharge
 LDI SECs2,005h  ;set timer for 5 seconds
SS8_0
 SET Alert,Flags2  ;set Alert flag
 RES Crank,Flags  ;clear Crank Flag
 CALL ShutOff  ;low & high power,fan,& crank off;min duty
 CALL BlinkAlert  ;blink Alert LED
 CALL MeterOff  ;Turn off Meter Mode LEDs
 JRR SEC,TicFlag2,SS8_2 ;wait for Timer2 before checking battery
 JRS BurnIn,Flags3,SS8_2 ;don′t check for battery if Burn-In
 JRS SOC,Flags4,SS8_2 ;don′t check for battery if Start Of Charge
 CALL CheckBatt  ;check for connected battery
 JRR Batt,Flags2,SS8_1 ;if disconnected,end abort routine
SS8_2
 JP SS8EXIT  ;otherwise,just exit
SS8_1
 RES Alert,Flags2 ;reset Alert flag
 JP MAIN2  ;re-initialize
SS8EXIT
 JP ExitMain
;***************************************************************************
;*            SS9-DESULFATION   *
;*Desulfation Mode is entered if the initial battery voltage is less *
;*than 12.2 volts and the voltage reaches 14.0 volts within five *
;*minutes.         *
;*        *
;*The charger tries to hold the voltage at 16.0 volts.As the battery *
;*starts to conduct,the voltage will fall.If the voltage reaches 14.0*
;*in a reasonable time limit(10 hours),we will transition to the *
;*normal charging sequence(SS5).If the voltage doesn′t fall to 14.0 *
;*volts we will transition to the ABORT sequence state(SS8).*
;***************************************************************************
SS9
 LDI Percent,15  ;set to 15%
 CALL BlnkChrg  ;blink Charging LED
 CALL CheckBatt  ;check for connected battery
 JRS Batt,Flags2,SS9_0;continue routine if connected
 JP MAIN2  ;...otherwise,re-initialize
SS9_0
 CALL VoltReg
 JRR SEC,TicFlag2,SS9X ;wait 1 minute
 JR HR,TicFlag2,SS9_1 ;maximum time out?(1 or 2 hours)
 DEC CurentSS  ;ABORT state
 JP SS9X  ;done
SS9_1
 LD A,BADhi  ;get latest average battery voltage
 CP A,Vref  ;are we there?
 JRC SS9_2  ;yes:reduce Vref
 JP SS9X  ;no:wait another minute
SS9_2
 DEC Vref  ;1 count is 0.0667 volts
 DEC Vref  ;reduce Vref by 0.133 volts
 LD A,Vref  ;see if batt is desulfated yet
 CPI A,Volts14  ;is Vref<14.0 Volts?
 JRC SS9_4  ;...if so,go to normal charge
 JP SS9_3  ;...otherwise,try another hour
SS9_4
 LDI_CurentSS,005h ;prepare to go to normal charge
 CALL ShowChgng ;turn Charging LED on(stop blinking)
 LD A,Vmax  ;set MaintVolt to Vmax
 LD MaintVolt,A  ;maintain voltage for state 5
 SET LoPwr,Flags2  ;tell PwrCon charger is on
 CALL IniTime2  ;initialize timer 2
 LDI SECs2,002h ;set timer for 2 seconds(voltage settle time)
 JP SS9X  ;
SS9_3
 CALL IniTime2  ;reset timer
 LDI HRs2,001h  ;set max time for 1 hour
SS9X
 JP ExitMain
SS10
;***************************************************************************
;*   dV/dt MONITOR   *
;*  This state is looking for one of three conditions:  *
;*1.Maximum time is exceded-set for check battery and turn off charger.*
;*2.No change in dV/dt for 45 minutes-battery is about 80% charged.*
;*3.MAX voltage is reached-GOTO dI/dt.   *
;*      *
;***************************************************************************
SS11
 CALL SetON  ;turn cooling fan & output on
;RES Rmpng,Flags3 ;clear flag before moving on
 RES Settle,Flags3  ;clear flag before moving on
 JRR HR,TicFlag1,SS11_1 ;If not max time out,goto SS11_1
 LDI CurentSS,ABORT ;otherwise,go to abort
 JP SS11X
SS11_1
 CALL ShowChgng  ;light Charging LED
 CALL GetBatt  ;get battery voltage adjusted for drop
 CP A,Vmax  ;is batt voltage<MAX voltage?
 JRC SS11_2  ;yes:continue loop
 SET RmpInt,Flags3  ;no: set to boost during D/C EndCharge
 JP SS11_6  ;   ...and prepare to GOTO dI/dt
SS11_2
 JRR MIN,TicFlag2,SS11X ;exit if not time for dy/dt test?
 LD A,Percent  ;get Percent
 CPI A,84  ;is Percent<85?
 JRNC SS11_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_3
 LD A,BADhi  ;get battery voltage
 SUBI A,2  ;maximum allowed positive change is 2
 CP A,MaintVolt ;test for upper limit change
 JRC SS11_4  ;less than 1 count up,test down change
 JP SS11_7  ;otherwise,skip ahead & update MaintVolt
SS11_4
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowGreen  ;turn on Green LED
 .ENDC
 DEC Tries  ;decrement counter
 JRZ SS11_6  ;all done,GOTO dI/dt
 LD A,Percent  ;get Percent
 CPI A,87  ;is Percent<88?
 JRNC SS11_5  ;...if not,skip ahead
 INC Percent ;...otherwise,increase Percent
SS11_5
 JP SS11_8  ;no,reload timer
SS11_6
 INC CurentSS  ;GOTO dI/dt next
 RES NoOff,Flags2  ;set for<100% duty cycle
 LDI Percent,88 ;set Percent to 88-NOTE must always be even
 JRS RmpInt,Flags3,MntMx ;skip ahead if Vmax reached
 CALL GetBatt  ;get battery voltage adjusted for drop
 LD MaintVolt,A ;save BADhi as maintain voltage
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
MntMx
 LD A,Vmax  ;otherwise,set MaintVolt to Vmax
 LD MaintVolt,A  ;MaintVolt used for di/dt
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
SS11_7  ;update MaintVolt
 IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowRed  ;turn on Red LED
 .ENDC
 LD A,BADhi  ;get current battery voltage
 LD MaintVolt,A ;update MaintVolt for dV/dt & di/dt
SS11_9
 LDI Tries,004h ;reset counter(4 matches=3 intervals)
SS11_8
 CALL IniTime2  ;initialize timer
 LDI MINs2,008h ;...for 8 minutes
SS11X
 JP ExitMain
;***************************************************************************
;*   di/dt MONITOR    *
;*In di/dt the on/off relay is opened and closed to hold the voltage *
;*close to the dV/dt value.The interval between opening and closing the *
;*relay will increase.This state is looking for one of two conditions:*
;*1.Maximum time is exceded -set for check battery and turn off charger.*
;*2.No change in on/off relay for 30 minutes -current stabilized at a *
;*low value.Battery is about 97% charged.Goto SS13(EndCharge)for *
;*1 hour.       *
;***************************************************************************
SS12
 CALL SetON  ;turn cooling fan & output on
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100;has % displayed reached 100?
 JRZ SS12_14  ;...ifso,turn on green LED
 CALL ShowYellow ;...otherwise,turn on yellow LED
 JP SS12_15  ;...and skip ahead(leave green off)
SS12_14
 CALL ShowDone  ;turn on charge complete LED
SS12_15
 JRR HR,TicFlag1,SS12_1 ;maximum time out?
 JRS Alert,Flags2,SS12_0 ;If 2nd max time out,goto SS12_0
 SET Alert,Flags2  ;If 1st max time,set Alert flag
 CALL IniTime1  ;and reset timer
 LDI HRs1,004h  ;to alow 4 more hours
SS12_10
 LD A,MaintVolt  ;and get Maintain voltage
 SUBI A,007h  ;then subtract~0.5V
 LD MaintVolt,A ;  and update Maintain voltage
 JP SS12EXIT  ;then restart di/dt
SS12_0
 LDI CurentSS,ABORT  ;go to abort
 RES Alert,Flags2  ;reset Alert flag for Abort timer
 JP SS12EXIT
SS12_1
 JRR MIN,TicFlag2,SS12EXIT ;time for dI/dt test?
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowAlt  ;turn on alternator % LED
 .ENDC
 LD A,Percent  ;get Percent
 CPI A,100  ;is Percent<100?
 JRNC SS12_2  ;...if not,skip ahead
 INC Percent ;...otherwise,increase Percent
 LD A,Percent  ;get percent
 CPI A,100  ;Is percent=100?
 JRZ SS12_2  ;YES,don′t increase anymore
 INC Percent  ;No,increase by 2
SS12_2
 LD A,OFFSET  ;get current OFFSET
;INC A
 CPI A,HiOff-1  ;has OFFSET reached maximum?
 JRNC SS12_13  ;if so,finish di/dt
 DEC A  ;ensure carry if equal
;DEC A  ;allow difference of 1
 CP A,OldOff  ;test for lower limit change
 JRC SS12_4;offset within 1,finish di/dt
 JP SS12_7  ;offset too high,try again
SS12_13
 JP SS12_6
SS12_4
 DEC Tries  ;decrement counter
 JRNZ SS12_5  ;Are we done?
 JP SS12_6  ;yes,all done,clean up and exit
SS12_5  ;no,continue
 LD A,Percent  ;get Percent
 CPI A,99  ;is Percent<100
 JRNC SS12_3  ;...if not,skip ahead
 INC Percant  ;...otherwise,increase Percent
 JP SS12_8  ;reload timer & check again later
SS12_3
 LD A,Tries  ;get the current tries
 CPI A,03  ;Is tries less than 3?
 JRNC SS12_11  ;No,just exit
 LDI Percent,100  ;Yes,show 100% and done
SS12_11
 JP SS12_8  ;reload timer & check again later
SS12_6
 INC CurentSS  ;GOTO EndCharge(SS13)
;CALL ShowChgng  ;turn Charging LED on
;LDI Percent,95  ;set Percent to 95
 CALL IniTime2  ;initialize Timer2
 LDI HRs2,001h  ;charge for 1 more hour(EndCharge)
 LDI MINs2,00Fh  ;charge for only 15 minutes(EndCharge)
 CALL IniTime1  ;initialize Timer1
 LDI HRs1,001h  ;Set to change percent every...
 LDI MINs1,003h  ;Three minutes
 JRR BatTypeA,Flags,SS12_9  ;skip if not Deep Cycle(Voyager)
 JRR RmpInt,Flags3,SS12_9 ;skip if not using higher EndCharge voltage
 INC HRs2  ;otherwise,change HRS2 from 1 to 2
 LDI MINs1,00Fh ;Set to change percent every 15 minutes
 LD A,MaintVolt  ;also,store Main Volt in A
 ADDI A,04h  ;increase A by 4 counts~0.267V
 LD MaintVolt,A  ;store updated value in MainVolt
SS12_9
 JP SS12EXIT
SS12_7
 LD A,OFFSET  ;set new base offset
 LD OldOff,A  ;save in OldOff
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS12_8
 CALL IniTime2  ;initialize Timer 2
 LDI MINs2,008h  ;set Timer 2 for 8 minutes
 LD A,OFFSET  ;Get current offset
 CPI A,MinOff  ;Is the offset=MinOff?
 JRNZ SS12EXIT  ;NO,just exit
 RES RmpInt,Flags3  ;YES,don′t boost voltage for EndCharge
 JP SS12_10  ;Current not falling,reduce voltage by 1/2V
SS12EXIT
 JP ExitMain
;***************************************************************************
;*     ENDCHARGE    *
;*Charge for desired hours after dI/dt at dV/dt voltage.  *
;***************************************************************************
SS13
 LDI Percent,100  ;set to 95%
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRNZ SS13_2  ;...if so,turn on green LED
 CALL ShowDone  ;turn on charge complete LED
SS13_2
 CALL SetON  ;turn cooling fan & output on
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNZ SS13_3   ;...if not,continue EndCharge
 JP SS5_Maint  ;...otherwise,go to Maintain
SS13_3
 JRR HR,TicFlag1,SS13_1;If not time to change percent,goto SS13_1
;INC Percent  ;increase the percentage by 1
 CALL IniTime1  ;reset Timer1
 LDI HRs1,001h  ;Set to change percent...
 LDI MINs1,003h  ;...every three minutes
 JRR BatTypeA,Flags,SS13_1 ;skip next line if not Deep Cycle(Voyager)
 LDI MINs1,00Fh  ;Set to change percent every 15 minutes
SS13_1
 JRR HR,TicFlag2,SS13EXIT ;exit if EndCharge time not up
 JP SS5_Maint  ;otherwise,GOTO MAINTAIN
SS13EXIT
 JP ExitMain
;***************************************************************************
;*   MAINTAIN    *
;*Battery has reached full charge.Stay here and maintain battery *
;*at 13.2 volts until battery is disconnected.   *
;*         *
;***************************************************************************
SS14
 LDI Percent,100  ;set to 100%
 CALL SetLow  ;set for low power mode
 SET LoPwr,Flags2  ;turn output on
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPent  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS14_1  ;...if so,turn on green LED
 CALL ShowYellow ;...otherwise,turn on yellow LED
 JP SS14_2  ;...and skip ahead(leave green off)
SS14_1
 CALL ShowDone  ;turn on charge complete LED
 .IFC EQ DEBUG  ;assemble next line only if debugging
 RES SwOff,SwDown ;set to check Type and Rate switches
 .ENDC
SS14_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRZ SS14_3  ;...if so,shut off fan
 CPI A,HiOff-4  ;check for sustained output
 JRNC SS14_4  ;...if not,leave fan off
 CALL FanON  ;...otherwise,turn fan on
 JP SS14_4  ;...and skip ahead
SS14_3
 CALL FanOff  ;turn cooling fan off
SS14_4
 CALL CheckBatt  ;check for battery
 JRS Batt,Flags2,SS14EXIT;...counected:continue
 JP MAIN2  ;...disconnected:start over firom state 0
SS14EXIT
 JP ExitMain
;***************************************************************************
;*   SS15MANUAL    *
;*Set offset for selected rate.No voltage limit/battery check.  *
;***************************************************************************
SS15
 JRS LoPwr,Flags2,SS15_0 ;power off indicates completed Burn-In
 JP SS15_2  ;skip to end if relay is open
SS15_0
 CALL ShowRate  ;turn on the 2A or 15A LED
;NOTE:output already on,but TurnON saves code space
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL Check17v  ;check for disconnected battery
 JRNZ SS15OK ;if<>17V,then continue
 LDI CurentSS,ABORT  ;...otherwise,Abort
 RES Manual,Flags3  ;...end Manual Mode
 JP SS15EXIT  ;...and skip rest of State 15
SS15OK
 JRS BurnIn,Flags3,SS15BI;skip ahead if Burn-in mode
 RES MtrScale,Flags  ;set for Alternator % LED off
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
 CALL ShowMeter ;update meter LEDs
 JP SS15rmp  ;jump to ramp check
SS15BI
 JRR MIN,TicFlag2,SS15b ;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 CALL IniTime2  ;reset Timer2
 LDI MINs2,1  ;set timer for counter interval(1 minute)
SS15b
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL ShowNum  ;display count on digital LED
 CALL MeterOff  ;turn off all meter mode LED′s
SS15rmp
 CALL ShowData  ;update display
 JRS NoRamp,Flags4,SS15_1;don′t ramp if NoRamp is set
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR Rmpng,Flags3,SS15_1 ;skip ahead if not Rapid->Fast transition
 CALL RampOS  ;otherwise,gradually reduce duty cycle
SS15_1
 JRR HR,TicFlag1,SS15EXIT;continue if not max manual charge time
 JRS BurnIn,Flags3,SS15_2;skip ahead if fiuished Burn-In
 JP RESET  ;...otherwise,reset
SS15_2
 CALL DigitsOff  ;turn off 3-digit LED
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL ShutOff  ;low & high power,fan,& crank off;min duty
SS15EXIT
JP ExitMain
;***************************************************************************
;*   BOOST MODE    *
;*First set the charger offset value for Slow charging.Next,wait *
;*for the voltage to stabilize.Then wait for the voltage to drop *
;*about one volt.When the voltage drops,go full on for 5 seconds.*
;*After five seconds of cranking,wait for 4 minutes and start over.*
;*         *
;***************************************************************************
SS16
 .IFC EQ DEBUG ;assemble next line only if debugging
 RES SwOff,SwDown ;set to check Type and Rate switches
 .ENDC
 CALL VoltMtr  ;set for volt meter and update display
 CALL CheckBatt  ;check for disconnected battery
 JRR Batt,Flags2,SS16_1 ;skip ahead if not connected
 JRS SEC,TicFlag2,BattOK ;skip if>2 seconds since Boost selected
 JP SS16Exit  ;if<2 seconds,then stay off
SS16_1
 CALL TurnOff  ;low & high power and fan off,min duty
 CALL ShowRed  ;turn on Alert LED
 JP SS16Exit  ;if batt<1.6V,then stay off
BattOK
 JRS LoPwr,Flags2,SS16_2 ;skip ahead if already on
 SET SOC,Flags4  ;set Start Of Charge flag
SS16_2
 CALL ShowCrank  ;turn ON Crank LED & turn Alert LED off
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL MaxLow  ;set for full lower power mode
 SET Started,Flags  ;set Flags for charge started
 CALL IniTime2  ;reset timer 2
 LDI SECs2,2  ;set Timer2 for 2s
 LDI MSECs2,MS200  ;set Timer2 for 1.2s
 INC CurentSS  ;set state to 17
SS16Exit
 JP ExitMain  ;goto end of loop
;***************************************************************************
;*   DELAY FOR VOLT READING   *
;***************************************************************************
SS17
 JRS MSEC,TicFlag2,SS17_1 ;Is 200ms up?
SS17_0
 JP SS17EXIT  ;no,just return
SS17_1
 JRS SEC,TicFlag2,SS17_3 ;skip ahead if 1.2s is up
 CALL GetMeter  ;update display
 CALL Check17v  ;check for disconnected battery
 JRC SS17_0  ;just exit if<17V
 JRR SOC,Flags4,SS17_2 ;skip ahead if not just turned on
 JP ChkBatt1  ;prepare to abort permanently
SS17_2
 JP MAIN2  ;disconnected,so start over
SS17_3
 SUBI A,010h  ;adjust for a one volt drop
 LD OldVolt,A  ;save it
 LDI MaintVolt,Volts142 ;try to hold battery at 14.2V
 RES SOC,Flags4  ;clear SOC flag
 INC CurentSS  ;wait for crank
 CALL IniTime2  ;initialize Timer 2
 LDI MINs2,00Ah  ;set Timer 2 for 10 minutes
SS17EXIT
 JP ExitMain
;***************************************************************************
;*   WAIT FOR CRANK    *
;***************************************************************************
SS18
 RES SOC,Flags4 ;clear Start Of Charge flag
 JRR MIN,TicFlag2,SS18_0 ;wait for crank up to 10 minutes
 JP MAIN2  ;then start re-initialize
SS18_0
 CALL FanON  ;turn cooling fan ON
 CALL GetMeter  ;update display
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,FreshBV  ;get current reading
 SUBI A,010h  ;adjust for a one volt drop
 CPA,OldVolt  ;has voltage increased?
 JRC SS18_2  ;if not,then skip ahead
 LD OldVolt,A  ;update OldVolt
 JP SS18_X  ;and exit routine
SS18_2
 LD A,FreshBV  ;get current reading
 CPA,OldVolt  ;1V drop indicates cranking
 JRNC SS18EXIT
SS18_1
 SET LoPwr,Flags2  ;turn output on
 SET HiPwr,Flags2  ;turn on high power mode
 SET NoOff,Flags2  ;set for 100% duty cycle
 INC CurentSS  ;time the cranking
 CALL IniTime2  ;reset Timer2
 LDI SECs2,CrankON ;crank for CrankON(8)seconds
SS18EXIT
 CALL Check17v  ;check for disconnected battery
 JRC SS18_X  ;skip ahead if connected
 JP MAIN2  ;otherwise,start over from state 0
SS18_X
 JP ExitMain
;***************************************************************************
;*   CRANK TIMING     *
;*Allow cranking for CrankON seconds and then go back to charging.*
;***************************************************************************
SS19
 LD A,SECs2  ;get remaining crank seconds
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
 JRS SEC,TicFlag2,SS19_1 ;if time is up,then end routine
 CALL Check17v  ;check for disconnected battery
 JRNC SS19_1  ;stop cranking if not connected
 JP SS19EXIT  ;still connected,wait for crank timer
SS19_1
 INC CurentSS  ;just wait for time to expire
 SET CrankWait,Flags ;indicates crank cool-down time
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL MaxLow  ;set for full lower power mode
 CALL IniTime2  ;reset Timer2
 LDI MINs2,CrankOff ;set timer for off time(two minutes)
 CALL IniTime1  ;reset Timer1
 LDI SECs1,CCDint ;set timer for counter interval(seconds)
 LDI CCDcnt,120 ;set crank cool down counter to 120
SS19EXIT
 JP ExitMain
 ;**************************************************************************
 ;*               INTER-CRANK DELAY                  *
 ;*Stay here until the 4 minute timer has expired then go back to BOOST *
 ;*if switch still engaged,else goto Slow auto(default)  *
 ;**************************************************************************
SS20
 CALL FanON  ;turn cooling fan ON
 JRR SEC,TicFlag1,SS20_0 ;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 CALL IniTime1  ;reset Timer1
 LDI SECs1,CCDint ;set timer for counter interval(seconds)
SS20_0
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 RES Rmpng,Flags3 ;clear flag for CheckBatt
 RES Settle,Flags3  ;clear flag for CheckBatt
 JRS MIN,TicFlag2,SS20_1 ;time up?Yes:GoTo SS20_1
 CALL BlinkCrank  ;No:blink the Crank LED
 JP SS20EXIT  ;and keep waiting
SS20_1
 RES CrankWait,Flags ;reset CrankWait bit of Flags
 LDI CurentSS,010h ;set state to 16 to Crank again
SS20EXIT
 JP ExitMain
;***************************************************************************
;*    SUB ROUTINES START HERE    *
;***************************************************************************
;***************************************************************************
;*Initialize state(Slow charge,Regular batt,State 0)  *
;*         *
;***************************************************************************
InitState
 CLR Flags  ;0 is default for all bits
 CLR Flags2  ;0 is default for all bits
 CLR Flags3  ;set to indicate no Rapid to Fast change
 CLR TEMP1  ;initialize
 CLR CCDcnt  ;initialize
 SET ChMode,Flags2  ;set for Charger Mode(charger mode)
 LDI OFFSET,HiOff-1 ;set for mimimum output current
 LDI SwData,0110111lb ;Initialize switch LEDs for 2A,Reg
 LDI Vmax,Volts155  ;Vmax for Regular batteries
 LDI VltCnt,001h ;initialize VltCnt to 1
 LDI VRcnt,001h ;initialize VRcnt to 1
 LDI PcntL,001h ;initialize PcntL to 1
 LDI PcntH,001h ;initialize PcntH to 1
 LDI CurentSS,000h  ;set charger state to 0
 LDI SECs1,SecInit ;restart TIMER1 second counter
 LDI SECs2,SecInit ;restart TIMER2 second counter
 RET
;***************************************************************************
;*   Reset Watchdog Register   *
;*This routine simiply resets the Watchdog register.RstWDR was *
;*only to save program space(LDI require 3 bytes,CALL requires only 2).*
;*         *
;***************************************************************************
RstWDR
 LDI WDR,OFEH ;reset watch dog timer
 RET
;***************************************************************************
;*   Wait a Fifth Second    *
;*This routine causes the program to wait one fifth second by waiting *
;*for 24 interrupts.      *
;***************************************************************************
FifthSecond
 CALL IniTime1
 LDI MSECs1,MS200;set timer for 1/5 second
WFS_1
 WAIT
 CALL RstWDR  ;reset watch dog timer
 JRR MSEC,TicFlag1,WFS_1 ;wait until timer goes to 0
 RET
;***************************************************************************
;*    Set Ramp Up     *
;*This routine sets the parameters necessary to ramp the duty up from the *
;*fast rate to the rapid rate.It is used before Burn-In and Automatic *
;*Rapid charge.           *
;*        *
;***************************************************************************
SetRmpUp
 LDI RmpCnt,RCinitX2 ;200 0.75-second intervals yields 150 seconds
 SET RampUp,Flags3 ;set for ramp up
SetRamp
 LDI TEMP,RIinit ;180 NMI interrupts yields 1.5 seconds
 SET RmpInt,Flags3 ;counting 1st of two 180 cycle periods
 RES Rmpng,Flags3 ;set for not ramping yet
 RET
;***************************************************************************
;*   CHECK RAPID     *
;*This routine determines whether to reduce or increase the charge rate *
;*from 30A to 10A or vica versa,if necessary.It sets the flags used by *
;*RampOS appropriately.        *
;*      *
;***************************************************************************
ChkRapid
 JRR Rate,Flags,ChkRapX ;if not Fast charge rate,then exit
 JRS Rmpng,Flags3,ChkRapX ;if Rmpng already set,then exit
 DEC TEMP  ;otherwise,update ramp timer
 JRZ RmpTmr  ;update count if time
 JP ChkRapX   ;...otherwise,just exit
RmpTmr
 LDI TEMP,RIinit  ;count 180 more cycles(1.5 sec)
 JRR RmpInt,Flags3,RmpCtr ;skip ahead if just counted 1st half
 RES RmpInt,Flags3  ;...otherwise,start counting 2nd half
 JP ChkRapX  ;...and exit
RmpCtr
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowAlt  ;turn on alternator % LED
 .ENDC
 DEC RmpCnt  ;check if time to ramp
 JRZ StartRamp  ;if so,start ramping
 JP ChkRapX  ;...otherwise,just exit
StartRamp
 SET Rmpng,Flags3  ;set to indicate Rapid to Fast transition
 RES NoOff,Flags2  ;activate PWM(<100% duty cycle)
 LDI RmpCnt,RCinit  ;100 3-second intervals yields 5 minutes
 JRS RampUp,Flags3,StRmpUp ;skip ahead if about to ramp up
 LDI RmpCnt,RCinitX2 ;...otherwise,double inter-ramp time
StRmpUp
 SET HiPwr,Flags2  ;turn on high power
 CALL ShowRate  ;show Rapid LED color
ChkRapX
 RET
;***************************************************************************
;*    RAMP OFFSET      *
;*This routine changes the charge rate from 30A to 10A gradually by *
;*changing OFFSET from OffRap to HiOff at a steady rate.OFFSET is *
;*raised by 1 every 4 seconds.That changes the current from 30A to 10A *
;*in about 4 minutes.       *
;*         *
;***************************************************************************
RampOS
 JRR Rate,Flags,RmpOffX ;if not Fast charge rate,then exit
 DEC TEMP   ;...otherwise,decrement counter
 JRZ RampTime  ;is counter down to zero?
 JP RmpOffX  ;if not,just exit
RampTime    ;...otherwise,time to adjust
 JRS RmpInt,Flags3,RampInt ;skip ahead if only halfway through wait
 JRS RampUp,Flags3,RmpUp ;skip ahead if decreasing OFFSET
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNZ RampMore  ;if not,skip ahead and continue ramping
 RES Rmpng,Flags3  ;ramping complete,clear flag
 RES HiPwr,Flags2  ;turn off high power
 CALL ShowRate  ;show Fast LED color
 SET NoOff,Flags2  ;set for full low power
 SET RampUp,Flags3  ;set to ramp up next time
 JP RmpOffX  ;skip to end of routine
RampMore
 INC OFFSET  ;...otherwise,reduce duty cycle
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowRed  ;turn on Red LED
 .ENDC
 SET Rmplnt,Flags3  ;counting 1st of two 180 cycle periods
 JP RmpOffI  ;skip ahead and re-initialize counter
RmpUp
 LD A,OFFSET  ;get OFFSET
 CPI A,OffRap  ;is it OffRap Yet?
 JRNZ RmpAgain  ;if not,skip ahead and continue ramping
RmpDone
 RES Rmpng,Flags3  ;ramping complete,clear flag
 RES RampUp,Flags3  ;set to ramp down next time
 JP RmpOffX  ;skip to end of routine
RmpAgain
 DEC OFFSET  ;...otherwise,reduce duty cycle
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowGreen  ;turn on Green LED
 .ENDC
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 JP RmpOffI  ;skip ahead and re-initialize counter
RampInt
 RES RmpInt,Flags3  ;counting last two 180 cycles of interval
RmpOffI
 LDI TEMP,RIinit  ;set counter for 180 cycles(1.5 more sec)
RmpOffX
 RET
;***************************************************************************
;*    SHOW NUMBER    *
;*This routine determines what three digits to display on the digital LED *
;*to represent the number stored in LEDNum.The three digits will be *
;*displayed next time the ShowData routine is called.   *
;*        *
;***************************************************************************
ShowNum
 CLR Index  ;initialize LUT Index to 0
 CALL DigiOff  ;set registers for all segments off
 LD A,LEDnum  ;store LEDnum in accumulator
 CPI A,10  ;check for single digit number
 JRNC ChkMaxNum  ;...if not,check for max number
 JP Next001  ;...otherwise skip to 3rd digit
ChkMaxNum
 CPI A,199  ;check for highest displayable number
 JRC Check100  ;if less,check value
 LDI A,199  ;...otherwise,displaly 199
Check100
 CPI A,100  ;check whehter to show most significant 1
 JRC Check010  ;if not,check for 10
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,100  ;...and subtract 100 from accumulator
Check010
 CPIA,10  ;check if<10
 JRC Check001  ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,10  ;...and subtract 10 from Acumulator
 JP Check010  ;...and check for next higher value
Check001
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD ATemp,A  ;save Accumulator
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for second digit
 LD DigiDat2,A ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to reminder of LEDnum
;CLR Index  ;initialize LUT Index to 0
Next001
;CPI A,1   ;check if<1
;JRC ShoNum001  ;...if so,skip ahead to end of routine
;INC INdex  ;...otherwise,show next higher value
;SUBI A,1  ;...and subtract 1 from Acumulator
;JP Next001  ;...and check for next higher value
;ShoNum001
LDI DRWR,Digits00x.w ;look up table(LUT)for 3rd digit
 LDI X,Digits00x.d ;initialize LUT
;LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1 ;...set bits in A for segments
 LD DigiDat1,A ;...store A into DigiDat1
ShowNumX
 RET
;***************************************************************************
;*     GetBatt      *
;*This routine adjusts the battery voltage stored in BADhi for the cable *
;*drop by calling GetDrop,then stores the result in the accumulator.*
;*         *
;***************************************************************************
GetBatt
 CALL GetDrop  ;get approx batt cable voltage drop
 LD A,BADhi  ;get latest avg batt voltage
 SUB A,Vdrop  ;adjust for voltage drop in cable
 RET
;***************************************************************************
;*   GET VOLTAGE DROP   *
;*This routine determines what value to use for the output cable voltage *
;*drop based on the value of OFFSET,the state of the HiPwr and NoOff *
;*flags,and the values in the DropOffs look-up table.*
;*          *
;***************************************************************************
GetDrop
 LD ATemp,A  ;save Accumulator
 CLR Vdrop  ;set Vdrop to 0
 CLR Index  ;initialize LUT index to 0
 JRR ChMode,Flags2,GDX ;leave 0 if in tester mode
 JRR LoPwr,Flags2,GDX ;also leave 0 if output is off
 .IFC EQ NoDrop ;assemble next line only if debugging
 JP GDX  ;leave 0 if in No Drop mode(debugging)
 .ENDC
 JRR HiPwr,Flags2,VDlow ;skip ahead if not high power
 CALL ChkHiOff ;check for max OFFSET(PWM full off)
 JRNZ GDhi  ;...if not,check for rate>Fast
 LDI Index,MaxDrpL ;...otherwise,set for rate=Fast
 JP GDX
GDhi
 LDI Index,MaxDrpH ;max index for High Power mode
 JP GDLUT
VDlow
 LDI Index,MaxDrpL ;initialize Vdrop to MaxDrpL
 JRR NoOff,Flags2,GDLUT ;check table if not full low power
 JP GDX  ;...otherwise,exit routine
GDLUT
 LDI DRWR,DropOffs.w ;look up table(LUT)Vdrop offsets
 LDI X,DropOffs.d ;initialize LUT
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 CP A,OFFSET  ;is OFFSET high enough to decrease Vdrop?
 JRNC GDX  ;...if not,skip ahead
 DEC Index  ;...otherwise,decrement index
 JP GDLUT  ;...and check next table entry
GDX
 LD A,Index  ;get Vdrop LUT index
 LD Vdrop,A  ;save new drop into Vdrop
 LD A,ATemp  ;restore Accumulator
RET
;***************************************************************************
;*   GET VOLT DIGITS    *
;*This routine determines what three digits to display on the digital *
;*LED to represent the battery voltage (BADhi).
;*        *
;***************************************************************************
GetVolts
 DEC VltCnt  ;decrement interval counter
 JRZ NewVolt  ;if 0,ready to update display
 JP GetVexit  ;...otherwise,just exit
NewVolt
 LDI VltCnt,MS500 ;re-initialize initerval counter
 CALL DigiOff  ;set registers for all segments off
 JRR ChMode,Flags2,GVT ;if Tester mode,use FreshBV
 CALL GetBatt  ;get battery voltage adjusted for drop
 JPGV10
GVT
 LD A,FreshBV  ;Get latest average battery voltage
GV10
 CLR Index  ;initialize LUT Index to 0
 CPI A,Volts10  ;check for 10V
 JRC Check1V  ;if not 10V then skip ahead
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,Volts10  ;...and subtract 10V from accumulator
Check1V
 CPI A,Volts01  ;check if>1.0V
 JRC Check01V  ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,Volts01  ;...and subtract 1.0V from accumulator
 JP Check1V  ;...and check for next higher value
Check01V
 LD ATemp,A  ;save Accumulator
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d  ;initialize LUT
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for bottom segments
 LD DigiDat2,A  ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
;CLR Index  ;initialize LUT Index to 0
;ChckPnt1
;CPI A,1  ;check fi<1
;JRC ShowV001  ;...if so,skip ahead to end of routine
;INC Index  ;...otherwise,show next higher value
;SUBI A,1  ;...and subtract 1 from Acumulator
;JP ChckPnt1  ;...and check for next higher value
ShowV001
 LDI DRWR,Digits0Vx.w ;look up table(LUT)for 3rd volts digit
 LDI X,Digits0Vx.d ;initialize LUT
;LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 AND A,DigiDat1  ;...set bits in A for bottom segments
 LD DigiDat1,A  ;...store A into DigiDat1
 RES Decimal,DigiDat1 ;turn ON decimal point
GetVexit
;GetVltsX
 RET
;***************************************************************************
;*   VoltMeter    *
;*This routine sets the display to show volts,then calls ShowMeter and *
;*ShowData to update the display with the current battery voltage.  *
;*       *
;*   GetMeter    *
;*This routine calls ShowMeter and ShowData to display the latest  *
;*voltage or percentage(determined by MtrScale & MtrUnits)on the  *
;*3-digit LED display.GetMeter is the last section of VoltMtr.*
;*         *
;***************************************************************************
VoltMtr
 RES MtrScale,Flags ;set for Alternator % LED off
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
GetMeter
 CALL ShowMeter  ;update meter LEDs
 CALL ShowData  ;update display
RET
;***************************************************************************
;*   GET PERCENT    *
;*This routine determines what value to use for the percentage of  *
;*charge before the charge state has reached the dv/dt state.The  *
;*percent is calculated by reading the battery voltage(BADhi)and  *
;*performing the following calculations:      *
;*As Tester      *
;*1.0V<BADhi<11.6V DC=>Percent=(BADhi/16)+1  *
;*11.61V<BADhi<12.8VDC=>Percent=(BADhi-175)*5+15  *
;*12.80V<BADhi=>Percent=100  *
;*As Charger     *
;*1Volt<BADhi<12Volts=>(BADhi/4)+15=Percent  *
;*12Volts<BADhi<dy/dt=>(BADhi/2)-30=Percent  *
;***************************************************************************
GetPercent
 JRS ChMode,Flags2,GPchg ;skip to Charging %
 JP TstrBP ;...otherwise,jump to Battery %
GPchg
 LD A,CurentSS ;get current program state
 CPI A,11  ;has charging reached dV/dt?
 JRC CalcPrcnt ;...if not,calculate percentage
 JP GetPctEnd ;...otherwise,do nothing
CalcPrcnt
 LD A,Percent ;get Percent
 CPI A,76  ;check for highest calculated %
 JRC GPmore ;continue if not there yet
 JP GetPctEnd  ;...otherwise,just exit
GPmore
 JRR HiPwr,Flags2,GP1;continue if not in High Power mode
 JP GetPctEnd ;...otherwise,just exit
GP1
 CALL GetBatt ;get battery voltage adjusted for drop
 CPI A,Volts12 ;is the battery voltage less than 12V?
 JRNC Formula2 ;...No,goto Formula2
 CPI A,Volts01 ;Is battery>1
 JRNC GPform1 ;...if so,skip next line
 JP GPzero ;...if not,set for zero %
GPform1
 CALL Divide4 ;...Yes,use first formula
 ADDI A,15  ;Add 15 and...
 JP GetPctExit ;...store into A
Formula2
 CALL Divide2 ;Divide by 2and
 SUBI A,30  ;...subtract 30
 JP GetPctExit ;skip ahead and finish routine
TstrBP
 LD A,FreshBV ;get latest(avg)battery voltage
 CPI A,Volts128 ;Is battery>12.8V?
 JRC Tstr100 ;...if not,skip ahead
 LDI Percent,100 ;...otherwise,Percent=100
 JP GetPctEnd ;...and end routine
Tstr100
 CPI A,BattMin ;Is battery>BattMin
 JRNC TstrBPhi ;...if so,jump ahead
 CPI A,Volts01 ;Is battery>1
 JRNC TstrBPmed ;...if so,jump ahead
GPzero
 LDI Percent,0 ;...otherwise set Percent to 0
 JP GetPctEnd ;...and end routine
TstrBPhi
 SUBI A,BattMin ;subtract minimum high voltage
 CALL ATimes5 ;multiply by 5
 ADDI A,15  ;add 15
 JP GetPctExit ;...store into A
TstrBPmed
 SUBI A,15  ;A=battery-15
 CALL Divide4 ;A=(battery-15)/4
 CALL Divide4 ;A=(battery-15)/16
 INC A  ;A=(battery-15)/16+1
GetPctExit
 LD Percent,A ;store into Percent
GetPctEnd
 RET
;***************************************************************************
;*  UPDATE BATTERY PERCENT    *
;*This routine controls how the battery percentage displayed is updated.*
;*UpdateBP ensures that under normal circumstances,the battery % dis- *
;*played is updated according to the following two rules.  *
;*1.The % displayed doesn′t change by more than 1% at a time  *
*2.The % displayed is not updated twice in<PCint seconds  *
;*There are a few exceptions.     *
;*1.The % displayed can jump up more than 1 if it was 0  *
;*2.The % displayed will drop to 0 immediately for disconnected batt.*
;*3.The % displayed can change by more than 1 if the scale** changes *
;*        *
;***Scale refers to the % scale,which is either battery or alternator *
;*        *
;***************************************************************************
UpdateBP
 LD A,Percent  ;check whether % is 0
 JRNZ UBP0  ;...if not,wait for update interval
 JP UBPfinish  ;...otherwise finish routine
UBP0
 LD A,DspPcnt  ;get last % displayed
 JRZUBP00  ;continue if 0%
 JP UBP1  ;skip ahead if not 0%
UBP00
 JRS MtrScale,Flags,UBP1;also skip ahead if Alternator %
 JRSWait0P,Flags2,UBPz ;skip ahead if Wait0P flag already set
 SET Wait0P,Flags2;...otherwise,set flag to wait
 CALL IniTime2  ;initialize Timer2
 LDI SECs2,3  ;set Timer2 for 3 seconds
 JRR ChMode,Flags2,UBPz ;skip ahead if in tester mode
 LDI SECs2,5  ;set Timer2 for 5 seconds in charger mode
UBPz
JRR SEC,TicFlag2,UBPz2;skip ahead if still waiting
 JP UBP0a  ;...otherwise,update percent
UBPz2
 JP UBPexit  ;...and just exit
UBP0a
 RES Wait0P,Flags2 ;set flag to indicate not waiting
 LD A,Percent  ;...otherwise,get new %
 JP UBPfinish  ;...and don′t wait to display it
UBP1
 DEC PcntL  ;decrement % interupt counter
 JRZ NewPsec  ;if 0,decrement seconds counter
 JP UBPexit  ;...otherwise,just exit
NewPsec
 LDI PcntL,MSINIT ;re-initialize % interupt counter
 DEC PcntH  ;decrement interval counter
 JRZ NewPrcnt  ;if counter=0,ready to update percent
 JP UBPexit  ;...otherwise,just exit
NewPrcnt
 LDI A,PCint  ;**Temp**
 JRS ChMode,Flags2,NewPct1;**Temp**
 CALL Divide2  ;**Temp**
NewPct1  ;**Temp**
 LD PcntH,A  ;re-initialize % interval counter
;LDI PcntH,PCint ;re-initialize % interval counter
 LD A,DspPcnt  ;get last % displayed
 JRNZ UBP2  ;skip ahead if not 0%
 LD A,Percent  ;get new %
 JP UBPfinish  ;and finish routine
UBP2
 CP A,Percent  ;compare to newest %
 JRZ UBPexit  ;if equal,do nothing
 JRC IncBP  ;if less,increase display % by 1
 JRS ChMode,Flags2,UBPexit ;don′t decrease % if charging
 DEC A  ;...otherwise,decrease % by 1
 JP UBPfinish  ;...and finish
IncBP
 INC A  ;increase display % by 1
UBPfinish
 LD DspPcnt,A  ;store updated display %
UBPexit
 RET
;***************************************************************************
;*   MeterNum    *
;*This routine calls MeterOff,ShowNum,and ShowData to turn off the *
;*display mode LED′s and display LEDnum on the 3-digit LED display.  *
;*         *
;*    NumData     *
;*This routine calls ShowNum and ShowData to display LEDnum on the  *
;*3-digit LED display.NumData is the last section of MeterNum.  *
;*         *
;***************************************************************************
MeterNum
 CALL MeterOff  ;turn off all meter mode LED′s
NumData
 CALL ShowNum  ;get data to show the number
 CALL ShowData  ;show the number
 RET
;***************************************************************************
;*   SHOW DATA    *
;*This routine updates the digital LED and 6 switch LEDs controlled by *
;*the serial to parallel shift registers.It sends the bits of SwData *
;*and DigiData to the registers bit by bit from LSB to MSB using  *
;*SerData.After each bit is sent,ShftClk is toggled to shift the bit *
;*to the next position.After all 24 bits have been sent,LtchClk is  *
;*used to update the outputs,which updates the LEDs.  *
;*         *
;***************************************************************************
ShowData
 CALL RstWDR  ;reset watch dog timer
 RES ClrData,DRAbuf ;clear shift register
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A  ;update port from Accumulator
 SET ClrData,DRAbuf ;prepare to accept data
 LD A,DRAbuf ;update Accumulator from buffer
 LD DRA,A  ;update port from Accumulator
 LDI BitCnt,008h ;initialize bit counter to 8
 LDI BytCnt,003h ;initializie byte counter to 3
 LD A,DigiDat1  ;get first 8 bits of digit data
GetBit
 RLC A  ;send MSB of Acumulator to Carry
 JRC SetBit  ;if Carry=1 then data bit is 1
 RES SerData,DRAbuf ;...otherwise set SerData to 0
 JP SendBit ;skip ahead to SendBit
SetBit
 SET SerData,DRAbuf ;set SerData to 1
SendBit
 LD DataBuf,A  ;store shifted data from A
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A  ;update port from Accumulator
 RES ShftClk,DRBbuf ;set Shift Clock low
 RES LtchClk,DRBbuf ;set Latch Clock low
 LD A,DRBbuf  ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
 SET ShftClk,DRBbuf ;set Shift Clock high
 LD A,DRBbuf  ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
 DEC BitCnt  ;update bit count
 JRZ NextData  ;if all bits sent then skip ahead
 LD A,DataBuf  ;store shifted data back in A
 JP GetBit  ;otherwise,get next bit
NextData
 DEC BytCnt  ;update byte count
 JRNZ NextByte  ;get next byte is count is not 0
 JP LatchData  ;...otherwise,done sending bits
NextByte
 LDI BitCnt,08h  ;set bit count for 8 more bits
 LD A,BytCnt  ;which byte is next?
 CPI A,02h  ;check for 2nd byte is next
 JRZ ScndByte  ;skip ahead if equal
 LD A,SwData  ;get 8 bits of switch LED data
 JP GetBit  ;send bits of second byte
ScndByte
 LD A,DigiDat2  ;get last 8 bits of digit data
 JP GetBit  ;send bits of second byte
LatchData
 SET LtchClk,DRBbuf ;update latches
 LD A,DRBbuf  ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
RET
;***************************************************************************
;*   Show Meter   *
;*This routine sets the digital LED to show either the current voltage *
;*or last percent based on Flags and CurentSS.During Engine start,it *
;*will count down seconds of either remaining crank time or cool down *
;*time.       *
;***************************************************************************
ShowMeter
 JRR Alert,Flags2,ChkMtr ;skip ahead if not abort mode
;CALL MeterOff ;...otherwise,turn off Meter Mode LEDs
 JP SMeXit  ;...and exit
ChkMtr
 JRS MtrUnits,Flags,GetPrcnt ;skip ahead and set for %
 CALL GetVolts  ;...otherwise,get volts
 JRS ChMode,Flags2,SM1 ;skip ahead if not in Tester mode
 CALL ResetStatus  ;...otherwise,turn off3 status LEDs
SM1
 JP ShowMtrX  ;...and skip to end or routine
GetPrcnt
 JRR ChMode,Flags2,TstMtr ;if in tester mode,get %
 JP ShowPrcnt  ;...otherwise,skip ahead & show %
Show0
 LDI Percent,0  ;set to show 0%
 JP ShowPrcnt  ;and skip ahead
TstMtr
 LD A,FreshBV  ;get latest Battery voltage
 JRZ Show0  ;if 0V,show 0%
 JRS MtrScale,Flags,AltTest ;skip ahead if set for Alt%
 JP BattTest  ;...otherwise,skip to Battery%
AltTest
 CPI A,AltMin  ;check for<1st LUT value
 JRNC AltMaxT  ;if not,test for>last LUT value
 JP Show0  ;...otherwise,show 0%
AltMaxT
 CPI A,AltMax  ;check for>last LUT value
 JRC AltVal  ;if not,skip ahead and check LUT
 LDI Percent,199  ;...otherwise,set to max value
 JP ShowPrcnt  ;and skip ahead
AltVal
 LDI DRWR,AltLvls.w ;LUT for alternator %
 LDI X,AltLvls.d  ;initialize LUT
 SUBI A,AltMin  ;diffence is index in look up table
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 LD Percent,A  ;store value into Percent
 JP ShowPrcnt  ;and skip ahead
BattTest
;CALL GetPercent ;get battery percent
ShowPrcnt
 CALL ShowPercent ;otherwise,show percentage
 CALL ShowStatus ;turn on appropriate status LED
ShowMtrX
 CALL ShoMtrMode ;turn on appropriate meter LED
SMeXit
 CALL RstWDR  ;reset watch dog timer
 RET
;***************************************************************************
;*   SHOW METER MODE    *
;*This routine turns on one of the meter units LED′s based on Flags and *
;*Flags2.If the unit is in TesterMode(ChMode=0),the routine will  *
;*also light the appropriate status LED based on the voltage at the  *
;*clamps.       *
;*        *
;***************************************************************************
ShoMtrMode
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
 JRS Crank,Flags,ShowMMX ;leave off if in Crank mode
ShowVolts
 JRS MtrUnits,Flags,ShoPrcnt ;goto ShoPrcnt if set
;RES Decimal,DigiDatl  ;turn ON decimal point
 RES LEDvolt,DRAbuf  ;turn on Voltage LED
JPShowMMX
ShoPrcnt
;SET Decimal,DigiDatl  ;turn off decimal point
 JRS MtrScale,Flags,ShowAlt ;goto ShowAlt if set
 RES LEDprcnt,DRAbuf  ;turn on Battery % LED
 JP ShowMMX
ShowAlt
 RES LEDalt,DRAbuf  ;turn on Alternator % LED
ShowMMX
 LD A,DRAbuf  ;update Accurnulator from buffer
 LD DRA,A  ;update port from Accumulator
RET
;***************************************************************************
;*  Hold Meter Mode LED(depending on mode)  *
;*This routine turns on the Battery%,Volts DC,or Alternator% LED based *
;*on Flags & Flags2 and keeps that LED on for one fifth second.*
;***************************************************************************
HoldMtrMd
 CALL ShoMtrMode ;tuon Meter Mode LED
 CALL FifthSecond ;wait one fifth second
RET
;***************************************************************************
;*    SHOW STATUS    *
;*This routine turns on one of the three status LED′s based on the *
;*battery voltage.This routine is for use in the tester mode.*
;*         *
;***************************************************************************
ShowStatus
 JRR ChMode,Flags2,TstrStat ;check for Tester mode
 JP ShoStatX  ;if not,skip to end
TstrStat
 LD A,FreshBV  ;get latest Battery voltage
 JRS MtrScale,Flags,TesAlt ;skip ahead if set for Alternator
 LD A,DspPcnt  ;get last % displayed
 CPIA,100  ;Is it 100?
 JRZ GrnBatt  ;...if so,show green LED
 CALL ResetStatus  ;...otherwise,turn Status LED′s off
 JP ShoStatX  ;...and skip to end
GrnBatt
 CALL ShowGreen  ;turn on Green LED
 JP ShoStatX   ;skip to end
Test Alt
 CPI A,Voltsl5a  ;Is alternator at least 15.07V?
 JRNC RedAlt  ;...if so,skip ahead and show red
 CPI A,Volts138  ;is alternator at least 13.80V?
 JRC RedAlt  ;...if not,skip ahead and show red
 CPI A,Volts14  ;Is alternator<14.0V?
 JRC YelAlt  ;...if so,skip ahead and show yellow
 CPI A,Volts149  ;is alternator at least 14.87V?
 JRNC YelAlt  ;...if so,skip ahead and show yellow
 CALL ShowGreen  ;...otherwise turn on Green LED
 JP ShoStatX  ;...and skip to end
RedAlt
 CALL ShowRed  ;turn on Red LED
 JP ShoStatX  ;skip to end
YelAlt
 CALL ResetStatus  ;turn Status LED′s off
;CALL ShowChgng  ;turn on yellow LED
;JP ShoStatX  ;...and skip to end
ShoStatX
 RET
;***************************************************************************
;*   METER OFF    *
;*This routine turns off the three meter mode LED′s.   *
;*         *
;***************************************************************************
MeterOff
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
 LD A,DRAbuf  ;update port A from buffer
 LD DRA,A
 RET
;***************************************************************************
;*    DigiOff    *
;*This routine set the registers to turn off the three-digit LED.*
;*         *
;***************************************************************************
DigiOff
 LDI DigiDat1,DigiOffa ;turn off 8 of 16 digital segments
 LDI DigiDat2,DigiOffb ;turn off other 8 of 16 digital segmens
 RET
;***************************************************************************
;*    DIGITS OFF    *
;*This routine turns off the three-digit LED.    *
;*         *
;***************************************************************************
DigitsOff
 CALL DigiOff  ;set registers for all segments off
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    DIGITS ON    *
;*This routine turns ON all segments of the three-digit LED.*
;*         *
;***************************************************************************
DigitsON
 LDI DigiDat1,DigiONa ;turn ON 8 of 16 digital segments
 LDI DigiDat2,DigiONb;turn ON other 8 of 16 digital segments
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    SHOW PERCENT    *
;*This routine turns ON the Battery % LED.  *
;*         *
;***************************************************************************
ShowPercent
 SET MtrUnits,Flags ;set Flags for %(not volts)
;RES MtrScale,Flags ;set Flags for batt(not alt)
;CALL ShoMtrMode ;turn on appropriate indicator(%)
;CALL UpdateBP  ;update % to display
 JRR Wait0P,Flags2,SP1 ;skip ahead if not waiting from 0
 LDI DigiDat1,Dashes1 ;...otherwise,show dashes while waiting
 LDI DigiDat2,Dashes2 ;...otherwise,show dashes while waiting
 JP ShowPx
SP1
 LD A,DspPcnt  ;get Percent value to display
JRR MtrScale,Flags,SP2 ;don′t use Display% for Alternator%
 LD A,Percent  ;...use actual Percent for display
 .IFC EQ ShoOff ;assemble next line only if debugging
 JRR ChMode,Flags2,SP2 ;skip ahead **DEBUG**
 LD A,OFFSET  ;diplay OFFSET **DEBUG**
;JRS Rmpng,Flags3,SP2 ;**DEBUG**
;LD A,RmpCnt  ;display Ramp Count **DEBUG**
 .ENDC
SP2
 LD LEDnum,A  ;...and store it in Accumulator
 CALL ShowNum  ;set digital LED for LEDnum
 SET Decimal,DigiDat1 ;turn OFF decimal point
ShowPx
;CALL ShowData  ;update display
 RET
;***************************************************************************
;*   RESET LEDS    *
;*This routine turns off the Type,Rate,and Status LED′s  *
;*         *
;***************************************************************************
ResetLEDs
 CALL ResetStatus ;turn off all three status LEDs
ClrLEDs
 LDI SwData,SwsOff ;turn off Type and Rate LED′s
;CALL ShowData ;update display
 RET
;***************************************************************************
;*    Reset Status    *
;*This routine turns off the LED′s in the Status area.   *
;*         *
;***************************************************************************
ResetStatus
 SET LEDchgng,DRAbuf ;turn off Charging LED
 SET LEDdone,DRAbuf ;turn off Charged LED
 SET LEDalert,DRAbuf ;turn off Fault(red)LED
 LD A,DRAbuf ;update Accumulator from buffer
 LD DRA,A  ;update port B from Accumulator
 RET
;***************************************************************************
;*   BLINK Charging LED    *
;*This routine blinks the Charging LED at a rate of once per second.*
;***************************************************************************
BlnkChrg
 LD A,MSECs1 ;get MSECs count
 CP1A,MS500 ;test for>1/2 sec
 JRNC BlinkCh1 ;if so,skip ahead
 CALL ResetStatus ;...otherwise,turn off status LEDs
 JP BlinkChX ;...and exit routine
BlinkCh1
 CALL ShowChgng ;Turn on Charging LED
BlinkChX
 RET
;***************************************************************************
;*    Show Charging   *
;*This routine turns the Charging LED on and the rest off.  *
;*         *
;***************************************************************************
ShowChgag
 CALL ResetStatus  ;turn off all Status LEDs
ShowYellow
 RES LEDchgng,DRAbuf ;turn ON Charging LED
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A  ;update port A from Accumulator
 RET
;***************************************************************************
;*    BLINK Alert LED   *
;*This routine blinks the Alert LED at a rate of once per second.*
;*         *
;***************************************************************************
BlinkAlert
 LD A,MSECs1 ;get MSECs count
 CPI A,MS500 ;test for 1/2 sec
 JRNC BlnkAlrt ;if so,skip ahead
 CALL ResetLEDs ;...otherwise,turn off all LEDs
 JRS BurnIn,Flags3,BBI ;skip ahead if not Burn-In
 CALL DigitsON ;...turn on all digital LED segments
 JP BAeXit ;...and exit routine
BBI
 CALL NumData ;get data for,and show LED number
 JP BAeXit ;...and exit routine
BlnkAlrt
 CALL AlertON ;Turn on Alert LED
 CALL DigitsOff ;Turn off 3-digit LED
BAeXit
 RET
;***************************************************************************
;*    Alert LED ON    *
;*This routine turns on the Alert(red)LED and turns the other meter *
;*LEDs off.NOTE:it does not affect the Rate and Type LEDs.*
;***************************************************************************
AlertON
 CALL MeterOff  ;Turn off Meter Mode LEDs
ShowRed
 CALL ResetStatus  ;Turn off Status LEDs
 RES LEDalert,DRAbuf ;Turn on Alert LED
 LD A,DRAbuf  ;write from buffer to port B
 LD DRA,A
 RET
;***************************************************************************
;*    Show Done LED    *
;*This routine turns on the Done(green)LED and turns all the other  *
;*LEDs off.NOTE:it turns off the Rate and Type LEDs.*
;***************************************************************************
ShowDone
 CALL ResetLEDs  ;Turn off all LEDs
 LDI SwData,SwsOff ;set Type & Rate LED′s off
;CALL ShowData  ;update display
 CALL ShowType  ;show Battery Type & update display
ShowGreen
 CALL ResetStatus  ;turn off all three status LEDs
 RES LEDdone,DRAbuf ;Turn on Done LED
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A  ;update port A from Accumulator
 RET
;***************************************************************************
;*     BLINK Crank LED     *
;*This routine blinks the Crank LED at a rate of once per second.*
;***************************************************************************
BlinkCrank
 LD A,MSECs2  ;get MSECs count
 CPI A,MS500  ;test for>1/2 sec
 JRNC BlinkES  ;if so,skip ahead
;CALL ResetLEDs  ;...otherwise,turn off all LEDs
 SET LEDboost,SwData ;...otherwise,turn off Crank LED
 JP BCeXit  ;...and exit routine
BlinkES
 CALL ShowCrank  ;turn on Crank LED
BCeXit
;CALL ShowChgng  ;light Charging LED
 RET
;***************************************************************************
;*    ShowCrank    *
;*This routine turns the Engine Start(Crank/Boost)LED on and turns *
;*the Type and other Rate LEDs off.      *
;***************************************************************************
ShowCrank
;CALL Reset LEDs  ;turn off all LEDs
 CALL ClrLEDs  ;turn off all Rate & Type LEDs
 RES LEDboost,SwData ;turn ON Crank LED
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*S    etSlow     *
;*This routine sets the charger for the Slow rate by setting the appro- *
;*priate flags.       *
;***************************************************************************
;SetSlow
;RES Crank,Flags ;turn off Crank LED
;RES Rate,Flags  ;turn on Slow LED
;RES NoOff,Flags2  ;activate PWM(<100% duty cycle)
;RES HiPwr,Flags2  ;turn off high power mode
;LDI OFFSET,OffSlow ;set Offset for 2A
;RET
;***************************************************************************
;*     MaxLow    *
;*This routine sets the charger for the maximum low power rate(=Fast)*
;*by setting OFFSET and the appropriate flags.    *
;*     SetLow     *
;*This routine sets the charger for the low power mode by setting the *
;*appropriate flags.SetLow is actually part of MaxLow  *
;***************************************************************************
MaxLow
 LDI OFFSET,MinOff ;set Offset for highest low power(10A)
SetLow
 RES NoOff,Flags2 ;activate PWM(<100% duty cycle)
 RES HiPwr,Flags2 ;turn off high power mode
 RET
;***************************************************************************
;*Show Charge Rate LED(depending on mode)*
;*This routine turns on the Slow or Fast LED,based on Flags.*
;*         *
;***************************************************************************
ShowRate
 JRS ChMode,Flags2,ShowSlow ;skip ahead if not Tester
 SET LEDfast,SwData  ;...otherwise,turn off Fast LED
 SET LEDslow,SwData  ;...also,turn off Slow LED
 JP ShoRateX
ShowSlow
 JRS Rate,Flags,ShowFast ;goto ShowFast if set
 RES LEDslow,SwData ;turn on Slow LED
 SET LEDfast,SwData  ;turn off Fast LED
 JP ShoRateX
ShowFast
 SET LEDslow,SwData  ;turn off Slow LED
JRS HiPwr,Flags2,ShowRap ;goto ShowRap if High Power
 RES LEDfast,SwData  ;turn on Fast LED
 SET LEDrap,SwData  ;turn off Rapid LED
 JP ShoRateX
ShowRap
 RES LEDrap,SwData  ;turn on Rapid LED
 SET LEDfast,SwData  ;turn off Fast LED
ShoRateX
 SET LEDboost,SwData  ;turn off Boost LED
;CALL ShowData  ;update display
 RET
;***************************************************************************
;*         *
;*    SetReg    *
;*This routine sets the charger for the Regular battery type by reset- *
;*ting the Deep Cycle and AGM/Gel flags.    *
;*          *
;***************************************************************************
SetReg
 RES BatTypeA,Flags  ;turn on Regular LED
 RES BatTypeB,Flags  ;turn off Gel/AGM LED
 RET
;***************************************************************************
;*Show Charge Type LED(depending on mode)*
;*This routine turns on either the Regular,Deep Cycle,or Gel/AGM LED *
;*based on Flags.The routne also sets Vmax to match  *
;*        *
;***************************************************************************
ShowType
 SET LEDreg,SwData  ;set Regular LED to off
 SET LEDdeep,SwData  ;set Deep Cycle LED to off
 SET LEDgel,SwData  ;set Gel/AGM LED to off
 JRR BatTypeB,Flags,ShowT2  ;skip ahead ifnot Gel/AGM
 RES LEDgel,SwData  ;turn on Gel/AGM LED
 LDI Vmax,Volts144  ;Vmax=14.4V for Gel/AGM MODE
 JP ShoTypeX
ShowT2
 JRS BatTypeA,Flags,ShowT3 ;goto ShowT3 if set
 RES LEDreg,SwData  ;turn on Regular LED
 LDI Vmax,Volts155  ;Vmax=15.5V for Regular MODE
 JP ShoTypeX
ShowT3
 RES LEDdeep,SwData  ;turn on Deep Cycle LED
 LDI Vmax,Volts16  ;Vmax=16V for Deep Cycle battery
ShoTypeX
;CALL ShowData  ;update display
 RET
;***************************************************************************
;*Hold Charge Type LED(depending on mode)*
;*This routine turns on the Regular,Deep Cycle,or Gel/AGM LED based on *
;*Flags and keeps it on for one Fifth second.   *
;***************************************************************************
HoldType
 CALL ShowType  ;turn on Battery Type LED
 CALL ShowData  ;update display
 CALL FifthSecond ;wait one Fifth second
 RET
;***************************************************************************
;*Hold Charge Rate LED(depending on mode)*
;*This routine turns on the Slow,Fast,or 6V LED based on Flags and *
;*keeps it on for one Fifth second.     *
;***************************************************************************
HoldRate
 CALL ShowNum  ;show nominal rate(amps)on digital LED
 CALL ShowRate  ;turn on Charge Rate LED
 CALL ShowData  ;update display
 CALL FifthSecond ;wait one Fifth second
 RET
;***************************************************************************
;*    Check High Offset    *
;*This routine is used to check whether the latest OFFSET is equal to the *
;*maximum value,HiOff.When OFFSET=HiOff,the charge rate is Fast in *
;*high power mode and 0in lower power mode.    *
;***************************************************************************
ChkHiOff
 LD A,OFFSET  ;get current OFFSET
 CPI A,HiOff  ;has OFFSET reached maximum(output off)?
 RET
;***************************************************************************
;*    Check0V     *
;*This routine checks the latest running average of the battery voltage *
;*and sets the Carry bit if it′s less than Volts0+1 DAC count.This *
;*routine is used to check whether a battery is connected.*
;***************************************************************************
Check0V
 LD A,FreshBV  ;test latest average voltage
 CPI A,Volts0+1 ;check if higher than zero
 RET
;***************************************************************************
;*     Check17v     *
;*This routine checks the latest running average of the battery voltage *
;*and sets the Carry bit if it′s less than Max Volts.This routine is *
;*used to check whether a battery is connected.    *
;***************************************************************************
Check17v
 LD A,FreshBV ;test latest average voltage
;LD A,BADhi ;test average voltage
 CPI A,Max Volts ;check for max volt reading
 RET
;***************************************************************************
;*    CheckBattery     *
;*CheckBatt compares the latest 32 sample(~1/4 second)average battery *
;*voltage,FreshBV,to the maximum possible battery voltage reading,17V.*
;*If FreshBV is 17V,then the battery was disconnected.CheckBatt also *
;*checks whether the voltage is less than 1.0V.If so,Flags2 is set for *
;*no battery detected.      *
;***************************************************************************
CheckBatt
 SET Batt,Flags2  ;set flag for connected battery
 JRS Settle,Flags3,ChkBattX ;dont check during settle time
;JRS Rmpng,Flags3,ChkBattX ;don′t check during Rapid->Fast trsition
 LD A,FreshBV  ;Get latest 1/4 second average voltage
 CPI A,Volts09-2  ;check for 9.0V minus 2 counts~8.867V
 JRNC ChkFan  ;leave fan alone if>9.0v
 CALL FanOff  ;...otherwise,turn fan off
ChkFan
;LD A,CurVolt  ;Get latest battery voltage
 CPI A,Volts01  ;Is it at least 1V?
 JRNC ChkBatt0  ;If so,battery might be connected
 JP NoBatt  ;If not,battery is not conected
ChkBatt0
 CPI A,MaxVolts  ;..otherwise,check for max volt reading
 JRZ ChkBattl  ;if=MaxVolts,might not be connected
 JP ChkBattX  ;...otherwise,still connected,just exit
ChkBatt1
 JRR SOC,Flags4,ChkBatt2 ;skip ahead if charge started 0-5 sec ago
 LDI CurentSS,ABORT  ;set to start Abort mode
 JP ExitMain
ChkBatt2
 LD A,BADhi  ;if truly MaxVolts,BADhi should be>16V
 CPI A,Volts16  ;if BADhi<16V,then disconnected
 JRC NoBatt  ;...so set for no battery
 JP ChkBattx  ;...otherwise,just exit
NoBatt
 RES Batt,Flags2  ;otherwise,set for not connected
 CALL ShowRed  ;turn on Alert(Red)LED
 LDI Pecent,0  ;set percent to 0
 LDI DspPcnt,0  ;set display % to 0
 CLR BADhi  ;clear previous voltage reading
 CLR FreshBV  ;clear previous voltage reading
ChkBattX
 RET
;*******************************************************************************
;*    Check Progress     *
;*This routine is used to ensure that the charger will abort if the *
;*battery voltage does not increase throughout the chugs.It checks the *
;*voltage every CPint minutes for a measurable increase since the  *
;*previous check.If there isn′t,the charge is aborted.  *
;*        *
;*******************************************************************************
ChkProg
 JRR MIN,TicFlag1,ChkProgX ;exit ifnot time to check for progress
ChkProg0
 JRR SOC,Flags4,ChkProg1 ;skip ahead if not Start Of Charge
 RES SOC,Flags4  ;...otherwise,clear SOC flag
 CALL IniTime1  ;initialize Timer1
 LDI MINs1,5  ;...set Timer1 for 5 minutes
 CLR LastBatt  ;clear LastBatt(ensure pass 1st test)
 JP ChkProgX  ;...and exit
ChkProg1
 LD A,BADhi  ;get latest battery reading
;SUBI A,2   ;subtract two counts **temp**
 SUBI A,1   ;subtract one count
 CPA,LastBatt   ;check for increase
 JRC ChkProgA  ;set to abort if no increase
 LD A,BADhi  ;set A back to BADhi
 LD LastBatt,A  ;update LastBatt
 CALL IniTime1  ;initialize Timer1
 .IFC NE FastCP  ;assemble next line only if not debugging
 LDI MINs1,CPint  ;set Timer1 for 60 minutes
 .ELSE   ;assemble next line only if debugging
 LDI MINs1,3  ;set Timer1 for 3 mins
 .ENDC
 DEC CCDcnt  ;update interval count
 JRNZ ChkProgX  ;just exit if not zero
 SET HR,TicFlag1  ;if zero,set for time expired
ChkProgA
 LDI CurentSS,ABORT  ;set to start Abort mode
ChkProgX
 RET
;***************************************************************************
;*    Battery Progress   *
;*This routine is used to ensure that ChkProg and CheckBatt are called *
;*only when the charge rate is about to ramp up or isn′t set to ramp at *
;*all.That way,the battery voltage used to check charging progress *
;*won′t be affected by the higher current.BattProg works by checking *
;*RmpCnt to make sure it′s less than 5.If the start of charge flag(SOC)*
;*is set,BattProg does not check RmpCnt.   *
;*          *
;***************************************************************************
BattProg
 JRR Rmpng,Flags3,BtPrg0 ;skip ahead ifnot Rapid->Fast transition
 CALL RampOS  ;otherwise,gradually reduce duty cycle
BtPrg0
 CLRA  ;set A to 0 to ensure<(9,12,or 14.2V)
 JRR HiPwr,Flags2,BtPrg1;skip ahead ifnot high power mode
 JP BtPrgX  ;...otherwise,just exit
BtPrg1
 JRS SOC,Flags4,BtPrg2 ;skip ahead if Start Of Charge
 LD A,RmpCnt  ;get Ramp interval counter
;NOTE:RmpCnt will be 0 if not set to ramp at all
 CPI A,5   ;is it almost time to ramp up?
 JRNC BtPrgX  ;if not,then exit
BtPrg2
 CALL ChkProg  ;check for charging progress
 CALL GetBatt  ;get battery voltage adjusted for drop
BtPrgX
 RET
;***************************************************************************
;*    Check Dip    *
;*CheckDip compares the latest 32 sample(~1/4 second)average battery *
;*voltage,FreshBV,to the maintain voltage used by VoltReg,MaintVolt.*
;*If FreshBV is more than 0.5V below the MaintVolt,the CheckDip checks *
;*the duty cycle.If OFFSET is between OffSlow and HiOff,then the *
;*charge current is more than 0 but less than the Slow rate(usually 2A).*
;*In that case,the battery was probably disconnected.CheckDip raises *
;*the charge rate to Slow by setting OFFSET to OffSlow.CheckDip also *
;*re-initializes the VoltReg interval counter,VRcnt,so that VoltReg *
;*won′t adjust OFFSET again for another second.If the battery really *
;*was disconnected,the output will shoot to 17V and CheckBatt will  *
;*indicate no battery.If there is a battery connected,then the output *
;*needed a boost to raise the voltage.      *
;*        *
;*NOTES:            *
;*CheckDip is only called by VoltReg,so the output must be on.*
;*VoltReg is only called when the charger is not in high power mode.*
;*If OFFSET if HiOff-1 or greater,then the output is zero.*
;*       *
;***************************************************************************
CheckDip
 LD A,FreshBV  ;get latest battery voltage
 ADDI A,Volts005  ;add 1/2 volt
 CP A,MaintVolt ;compare with set value+1
 JRC ChkDp1  ;if FreskBV<MaintVolt-0.5V,continue
 JP ChkDipX  ;...otherwise,exit routine
ChkDp1
 LD A,OFFSET  ;get OFFSET
 CPI A,OffSlow  ;check for rate>Slow
 JRNC ChkDp2  ;if rate<Slow,then continue
 JP ChkDipX  ;...otherwise,exit routine
ChkDp2
 CPI A,HiOff-1  ;test if output is off
 JRNC ChkDipX  ;if so,just exit
 LDI OFFSET,OffSlow ;...otherwise,set for Slow rate
 LDI VRcnt,MSINIT  ;re-initialize initerval counter(1 sec)
ChkDipX
 RET
;***************************************************************************
;*       CHECK SWITCHES    *
;*Check if switch is engaged and change modes if appropriate.*
;*        *
;***************************************************************************
CheckSw
 JRR CrankWait,Flags,ChkStart ;check switches ifnot during Crank wait
 JP ChkSwRET   ;don′t check switches if during Crank wait
ChkStart
 JRR Crank,Flags,ChkMeter ;check meter mode if not during Boost
 JP ChkRate  ;skip meter mode switch during Boost
ChkMeter
 JRR MeterSw,DRC,MeterDown ;If switch is being pressed,skip ahead
 RES MeterSw,SwDown  ;set for Meter switch not pressed(up)
 JP ChkRate   ;Meter switch not pressed,so exit CheckSw
MeterDown
 RES Idle,Flags3  ;set for not idle
 JRR MeterSw,SwDown,ChngMeter ;If switch was released,then check it
 JP ChkRate  ;Otherwise,skip ahead
 ChngMeter   ;change Meter Mode
 SET MeterSw,SwDown ;set for mode switch pressed(down)
 JRR MtrScale,Flags,ChkPrcnt ;if not set for Alt,then skip ahead
 RES MtrScale,Flags  ;set for Alt%,so change to Batt%
;CLR DspPcnt  ;prepare to show new %(not adjust old %)
 JP ChkRate
ChkPrcnt
 JRR MtrUnits,Flags,ChkAlt ;if set for volts,then skip ahead
 RES MtrUnits,Flags ;set for Batt%,so change to volts
 JP ChkRate
ChkAlt
 SET MtrUnits,Flags  ;set for volts,so change to %
;.IFC NE ShoOff ;assemble next line only if not debugging
;JRS ChMode,Flags2,ChkRate ;don′t set for Alt if charging
;.ENDC
 .IFC EQ ShoOff ;assemble next line only if debugging
 SET MtrScale,Flags  ;set for batt,so change to alt
 RES Wait0P,Flags2  ;set to stop waiting for battery %
 .ENDC
;CLRDspPcnt  ;prepare to show new %(not adjust old %)
ChkRate
 CALL ShoMtrMode  ;Meter units are set before rate
 .IFC EQ DEBUG ;assemble next line only if debugging
 JRR SwOff,SwDown,SkpSw ;skip Rate and Type swith if SwOffis set
 JP ChkSwRET   ;Otherwise,just exit
SkpSw
 .ENDC
 JRR RateSw,DRC,RateDown ;If switch is being pressed,skip ahead
 RES RateSw,SwDown  ;set for Rate switch not pressed(up)
 JP ChkType   ;Rate switch not pressed,so check Type
RateDown
 RES Idle,Flags3  ;set for not idle
 JRR RateSw,SwDown,ChngRate ;If switch was released,then check it
 JP ChkType  ;Otherwise,skip ahead to Type Switch
 ChngRate  ;change Charge Rate
 SET RateSw,SwDown  ;set for mode switch pressed(down)
 JRS ChMode,Flags2,ChkCM ;skip ahead if already Charger mode
 SET Crank,Flags  ;...otherwise temporarily set Crank flag
 RES Disable,DRBbuf  ;enable output after Rate is pressed
 JRR MtrScale,Flags,ChkCM ;skip ahead if not set for Alt%
;CLR DspPcnt  ;...otherwise,don′t use Alt% for charge
 RES MtrScale,Flags  ;set for Batt%(not Alt%)when not tester
ChkCM
 SET ChMode,Flags2  ;set for Charger(not tester)Mode
 JRR Crank,Flags,ChkSlow ;if not set for Crank,check for Slow
 RES Crank,Flags  ;clear Crank bit of Flags
 RES Rate,Flags  ;was Crank,so set for Slow
 JP ModeChange  ;go to end of CheckSw
ChkSlow  ;if set for Slow,then set to Fast
 JRS Rate,Flags,ChkES ;If not Slow,then must be Fast
 SET Rate,Flags  ;set Charge rate for Fast
 JP ModeChange  ;go to end of CheckSw
ChkES  ;was set to Fast,so set for Crank
 RES Rate,Flags  ;set Flags for Slow
 SET Crank,Flags  ;set Charge rate for crank(Boost)
;SET ChMode,Flags2  ;Set Charger to stop tester mode
;RES MtrScale,Flags  ;set for Batt%(not Alt%)when not tester
 CALL SetReg  ;set battery type for Regular
;RES Disable,DRBbuf  ;enable output
;RES LoPwr,Flags2  ;turn off output
 CALL TurnOff  ;low & high power and fan off,min duty
 CALL ShowCrank  ;turn ON Crank LED
 LDI CurentSS,CrankSS ;set Charge state to Crank
 CALL IniTime2  ;reset timer 2
 LDI SECs2,003h  ;set Timer2 for 3 seconds
 JP ChkSwRET
 ChkType   ;if Gel/AGM,then set for Regular
 JRR TypeSw,DRC,TypeDown ;If Switch is being pressed,skip ahead
 RES TypeSw,SwDown  ;set for Type switch not pressed(up)
 JP ChkSwRET   ;Type switch not pressed,so exit CheckSw
 TypeDown
 RES Idle,Flags3  ;set for not idle
 JRR TypeSw,SwDown,ChngType ;If Switch was released,then check it
 JP ChkSwRET  ;Otherwise,just exit
 ChngType  ;change Battery Type
 SET TypeSw,SwDown  ;set for mode switch pressed(down)
;SET ChMode,Flags2  ;set for Charger Mode
;RES MtrScale,Flags  ;set for Batt%(not Alt%)when not tester
;RES Disable,DRBbuf  ;enable output after Type is pressed
 JRR BatTypeB,Flags,ChkBT2  ;If not set for Gel/AGM,check for Regular
 CALL SetReg  ;set battery type for Regular
 JP TypeChange  ;go to end of CheckSw
 ChkBT2   ;if Regular,then set for Deep Cycle
 JRS BatTypeA,Flags,ChkBT3  ;If not set for Regular,must be Deep Cycle
 SET BatTypeA,Flags  ;set battery type for Deep Cycle
 RES BatTypeB,Flags  ;set charge mode for automatic
 JP TypeChange  ;go to end of CheckSw
 ChkBT3   ;must be Deep Cycle,so set for Gel/AGM
 SET BatTypeB,Flags  ;set charge mode for Gel/AGM
 RES BatTypeA,Flags  ;set battery type for Regular
TypeChange
 RES Crank,Flags   ;set charge rate for non-Boost
 CALL ShowType   ;turn on Battery Type LED
ModeChange
 RES Crank,Flags  ;clear Crank bit of Flags
 LDI CurentSS,000h  ;restart charging
ChkSwRET
 RET
;***************************************************************************
;*      FAN ON     *
;*This routine turns the cooling fan ON.FanON is called during one of *
;*the following conditions:       *
;*1.Start of charge(end of State 2)     *
;*2.Start of boost(State 16)      *
;*3.If OFFSET<HiOff-3 in Maintain(State 14)    *
;*4.Manual Mode(State 15)      *
;*5.States 4,5,11,12,and 13    *
;*         *
;*The fan won′t be turned on if FreshBV<9V    *
;*        *
;***************************************************************************
FanON
 LD ATemp,A  ;save Aocumulator
 LD A,FreshBV  ;Get latest 1/4 second average voltage
 CPI A,Volts09  ;check for 9.0V
 JRC FanONx  ;leave fan alone if<9.0v
 LDI A,00010000b ;update Accumulator from buffer
 LD DRC,A  ;update port from Accumulator
FanONx
 LD A,ATemp  ;restore Accumulator
 RET
;***************************************************************************
;*     FAN Off     *
;*This routine turns the cooling fan off.FanOff is called during one of*
;*the following conditions:       *
;*1.Before start of charge(State 0)     *
;*2.Start of Abort(State 8)       *
;*3.Before start of Maintain(State 14)     *
;*4.If OFFSET=HiOff in Maintain(State 14)     *
;*5.If battery voltage drops below 8.867V     *
;*         *
;***************************************************************************
FanOff
;LD ATemp,A  ;save Accumulator
;LDI A,00000000b  ;update Accumulator from buffer
;LD DRC,A  ;update port from Accumulator
;LD A,ATemp  ;restore Accumulator
 CLR DRC
 RET
;***************************************************************************
;*      ShutOff      *
;*This routine sets the charger for no output by turning off the output *
;*FETs,turning off the fan,setting the PWM for minimum duty cycle *
;*(HiOFF),and setting it for non-boost mode.    *
;*         *
;*TurnOff      *
;*This routine sets the charger for no output by turning off the output *
;*FETs,turning off the fan,and setting the PWM for minimum duty *
;*cycle(HiOFF).TurnOff is actually part of ShutOff.   *
;*        *
;***************************************************************************
ShutOff
 RES Crank,Flags  ;set charge rate for non-Boost
 CLR RmpCnt  ;clear ramp interval counter
TurnOff
 CALL FanOff  ;turn cooling fan off
 RES LoPwr,Flags2  ;turn output off
 RES HiPwr,Flags2  ;turn off high power mode
 LDI OFFSET,HiOff ;set for minimum duty cycle
 RET
;***************************************************************************
;*      TurnON      *
;*This routine sets the charger to run with the Charging LED,fan,and *
;*output on.        *
;*            *
;*    SetON       *
;*This routine sets the charger to run with the fan and output on *
;*SetON is actually part ofTurnON    *
;*          *
;***************************************************************************
TurnON
 CALL ShowChgng  ;tarn Charging LED on
SetON
 CALL FanON  ;turn cooling fan on
 SET LoPwr,Flags2  ;tell PwrCon charger is on
RET
;***************************************************************************
;*Update the clocks and set overflow flags as necessary.*
;*TicFlag1(s)bit 0=hours went to zero   *
;*TicFlag1(s)bit 1=minutes went to zero   *
;*TicFlag1(s)bit 2=seconds went to zero   *
;*TicFlag1(s)bit 3=miliseconds went to zero   *
;***************************************************************************
CLOCKS
 DEC MSECs1  ;decrement millisecond counter
 JRZ DO_MSECs
 JP CLOCKS1
DO_MSECs
 LDI A,MSINIT  ;restart millisecond counter
 LD MSECs1,A  ;
 SET MSEC,TicFlag1  ;set millisec flag
 DEC SECs1  ;decrement second counter
 JRZ DO_MINs
 JP CLOCKS1
DO_MINs
 SET SEC,TicFlag1  ;set second expired flag
 LDI SECs1,SecInit  ;restart second counter
 DEC MINs1  ;decrement minute counter
 JRZ DO_HRs  ;check for overflow
 JP CLOCKS1
DO_HRs
 SET MIN,TicFlag1  ;set minute expired flag
 LDI MINs1,MININIT  ;restart minute counter
 DEC HRs1   ;decrement hour counter
 JRNZ CLOCKS1   ;check for overflow
 SET HR,TicFlag1  ;set hour expired flag
CLOCKS1
 DEC MSECs2  ;decrement millisecond counter
 JRZ DOMSECs2
 JP CLOCEXIT
DOMSECs2
 LDI A,MSINIT  ;restart millisecond counter;
 LD MSECs2,A  ;
 SET MSEC,TicFlag2  ;set millisec flag
 DEC SECs2   ;decrement second counter
 JRZ DO_MINs2
 JP CLOCEXIT
DO_MINs2
 SET SEC,TicFlag2  ;set second expired flag
 LDI SECs2,SecInit  ;restart second counter
 DEC MINs2  ;decrement minute counter
 JRZ DO_HRs2  ;check for overflow
 JP CLOCEXIT
DO_HRs2
 SET MIN,TicFlag2  ;set minute expired flag
 LDI MINs2,MININIT  ;restart minute counter
 DEC HRs2    ;decrement hour counter
 JRNZ CLOCEXIT  ;check for overflow
 SET HR,TicFlag2  ;set hour expired flag
CLOCEXIT
 RET
;***************************************************************************
;*    INITIALIZE TIMER1     *
;*   Subroutine to initialize timer1    *
;***************************************************************************
IniTime1
 LDI MSECs1,MSINIT
 LDI SECs1,SecInit
 LDI MINs1,MININIT
 CLR HRs1
 CLR TicFlag1
RET
;***************************************************************************
;*    INITIALIZE TIMER2    *
;*   Subroutine to initialize Timer2   *
;***************************************************************************
IniTime2
 LDI MSECs2,MSINIT
 LDI SECs2,SecInit
 LDI MINs2,MININIT
 CLR HRs2
 CLR TicFlag2
RET
;****************************************************************************
;*     DIVIDE BY 2    *
;*Subroutine to divide the number in A by 2.The remainder,if any *
;*will be available in the carry bit upon return.    *
;***************************************************************************
Divide2
 SLA A  ;divide by two by shifting left 8 times
 RLC A  ;thtrough CARRY bit
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 RET
;***************************************************************************
;*     DIVIDE BY 4   *
;*Subroutine to divide the number in A by 4.    *
;***************************************************************************
Divide4
 SLA A  ;divide by two by shifting left 7 times
 RLC A  ;through CARRY bit
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 ANDI A,01111111b ;drop MSB
 RET
;***************************************************************************
;*     A Times 5    *
;*Subroutine to multiply the accumulator (A)by 5.    *
;*Atimes5 multplies A by 4 by shifting left twice then adding the *
;*original value of A:(A*4)+A=A*5     *
;***************************************************************************
ATimes5
 LD ATemp,A  ;ATemp=A
 ADD A,A  ;A=A+A=A*2
 ADD A,A  ;A=A+A=ATemp*4
 ADD A,ATemp  ;A=A+ATemp+ATemp*5
 RET
;***************************************************************************
;*    VOLTAGE REGULATION   *
;*This subroutine will adjust the value of OFFSET once per second to *
;*control the current and maintain the voltage determined by MaintVolt.*
;*         *
;***************************************************************************
VoltReg
 .IFC EQ ShoReg ;assemble next line only if debugging
 LD A,OFFSET  ;get latest OFFSET
 LD TEMP1,A  ;store latest OFFSET in TEMP1
 .ENDC
 CALL CheckDip  ;check for dip in batt voltage
 DEC VRcnt  ;decrement interval counter
 JRZ VReg_0  ;Yes:then time to adjust
 JP VRegEXIT  ;No:then not time to adjust
VReg_0   ;adjust offset
 LDI VRcnt,MSINIT ;re-initialize initerval counter(1 sec)
 CALL GetDrop  ;get cable drop
 LD A,FreshBV  ;get battery voltage
 SUB A,Vdrop  ;adjust A for cable drop
 DEC A  ;adjust A for comparison
 CP A,MaintVolt ;compare with set value+1
 JRC VReg_1   ;not greater than,test if less than
 LD A,OFFSET  ;greater than,get phase delay value
 INC A  ;
 CPI A,HiOff+1  ;test if at high limit
 JRNC VReg_3  ;at the limit,don′t change OFFSET
VReg_4
 LD OFFSET,A  ;update OFFSET
VReg_3
 JP VRegEXIT  ;done for this pass
VReg_1
 INC A
 CP A,MaintVolt ;compare with set value
 JRNC VRegEXIT  ;not less than,just exit
 LD A,OFFSET  ;less than,get phase delay value
 DEC A  ;
 CPI A,MinOff  ;test if at low limit
 JRNC VReg_4  ;not at the limit,update OFFSET
 VRegEXIT  ;the next section lights LED′s for debugging
 .IFC EQ ShoReg ;assemble next lines only if debugging
 LD A,OFFSET  ;get new offset
 CP A,TEMP1  ;compare it to previous value
 JRZ VRegYel  ;turn on yellow LED if no change
 JRC VRegRed  ;turn on red LED if decreased
 CALL ShowGreen  ;turn on Green LED otherwise
 JP VRegDone  ;...and exit routine
VRegRed
 CALL ShowRed  ;turn on Red LED
 JP VRegDone  ;...and exit routine
VRegYe1
 LD A,CurentSS ;check current state
 CPI A,9  ;in desulphation mode?
 JRZ VRegDone  ;...if so,exit routine
 CALL ShowChgng  ;...otherwise,turn on Charging LED
VRegDone
 .ENDC
 RET
;***************************************************************************
;*   TIMER INTERRUPT HANDLER   *
;*This routine turns the FETs on if the power flags are non-zero and *
;*inhibits the timer.      *
;***************************************************************************
PwrCon
 LD ATemp,A  ;save A register
 JRS LoPwr,Flags2,PCon ;skip ahead if charger is on
PCoff
 RES PWMlo,DRBbuf ;...otherwise,shut off output
 SET PWMhi,DRBbuf ;...shut off high power
 JP PwrExit  ;not charging,leave FETs off
PCon
 LD A,OFFSET  ;otherwise,check OFFSET
 JRS HiPwr,Flags2,PCHP ;skip ahead if in high power mode
 JRS NoOff,Flags2,PCon0 ;also skip ahead if full low power
 CPI A,HiOff  ;has OFFSET reached the max?
 JRC PCon0  ;if not,turn FETs on
 JP PCoff  ;...otherwise,shut off output
PCHP
 JRS NoOff,Flags2,PwrC2 ;skip ahead if full high power
 CPI A,HiOff  ;has OFFSET reached the max?
 JRC PwrC2  ;if not,turn on high power
 SET PWMhi,DRBbuf ;...otherwise,shut off high power
 JP PCon0  ;...but turn on low power
PwrC2
 RES PWMhi,DRBbuf  ;0 at PWMhi sets PWM to max power
PCon0  ;set for full low power
 SET PWMlo,DRBbuf ;1 at PWMlo turns output FETs on
PwrExit
 LD A,DRBbuf  ;update port from buffer
 LD DRB,A  ;send to hardware
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 CALL RstWDR  ;reset watch dog timer
 LDI A,FULLTIME ;TCR is reloaded here for 1 full cycle
 LD TCR,A  ;set timer(on time)for FULLTIME
 LDI TSCR,0101110lb ;reload prescaler and start timer
 SET NMInt,Flags2  ;tell ExitMain this was timer interupt
PCexit
 LD A,ATemp  ;restore A register
RETI
;***************************************************************************
;*    A/D INTERRUPT HANDLER   *
;*This is the A to D interrupt service routine.The only thing it does is *
;*clear the interrupt bit and wakes the processor up from its wait mode.*
;***************************************************************************
ADINT
 RES 7,ADCR
 LD A,ADR
 RETI
;***************************************************************************
;*             NON-MASKABLE INTERRUPT HANDLER   *
;*This is the NMI interrupt routine.The NMI is generated on the falling *
;*edge of the full wave rectified AC line voltage.An interrupt is *
;*generated 120 times per second,once every 8.333ms.After each NMI,*
;*this routine performs the following steps.   *
;*1.Reset the watchdog timer and save the registers.    *
;*2.Turn off the FETs(unless OFFSET=0 and LoPwr<>0).  *
;*3.Set the interrupt timer according to OFFSET.   *
;*4.Reset NMInt so ExitMain knows it′s an NMI(not timer int). *
;*5.Update the clocks.    *
;*6.Restore the registers.   *
;*If turned off,the FETs will remain off for a period determined by *
;*OFFSET.The Timer will then trigger an interrupt which tells PwrCon *
;*to turn the FETs back on if necessary.   *
;*           *
;***************************************************************************
IT_TIMER
 CALL RstWDR  ;reset watch dog timer
 LD ATemp,A  ;save A register
 LD A,X  ;get X register
 LD XTEMP,A  ;save X register
 JRS LoPwr,Flags2,IT_LP ;skip ahead if low power is on
IT_OFF
 RES PWMlo,DRBbuf ;...otherwise,shut off output
 SET PWMhi,DRBbuf ;...shut off high power
 JP IT_NoTmr  ;...and jump to end of routine
IT_LP
 JRS HiPwr,Flags2,IT_HP ;skip ahead if High power mode
 SET PWMhi,DRBbuf ;...otherwise,shut off PWMhi
 JRS NoOff,Flags2,IT_FLP ;skip ahead if no off time
 LD A,OFFSET  ;...otherwise,get latest offset
 CPI A,MinOff+1  ;is it at min(nearly full on)?
;CPI A,MinOff  ;**temp**
 JRNC IT_MIN  ;if not,continue and shut off
 JP IT_FLP  ;otherwise,leave ON and skip ahead
IT_MIN
 RES PWMlo,DRBbuf ;...otherwise,shut off output
 JP SetOff  ;...and jump to end of routine
IT_HP
 JRS NoOff,Flags2,IT_FHP ;skip ahead if no off time
 SET PWMhi,DRBbuf ;...otherwise,shut off PWMhi
SetOff
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC IT_ChkHP  ;if so,check for High Power mode
 JP IT_OS  ;...otherwise,skip ahead & set offset
IT_ChkHP
 JRS HiPwr,Flags2,IT_FLP ;if High Power & HiOff,set for full LP
 JP IT_OFF  ;...otherwise,shut off output
 IT_FHP  ;Full High Power(Boost)
 RES PWMhi,DRBbuf  ;turn on high power PWM
 SET PWMlo,DRBbuf  ;turn output FETs on
 JP IT_NoTmr  ;skip ahead and shut off TIMER
 IT_FLP  ;Full Low Power(Fast)
 SET PWMlo,DRBbuf ;turn output FETs on
 SET PWMhi,DRBbuf ;...shut off high power
IT_NoTmr
 LDI TSCR,00010101b ;reset TSCR and inhibit TIMER interupt
 JP IT_TMR
IT_OS
 LD TCR,A  ;load the counter with current offset
 LDI TSCR,01011101b ;reload prescaler(32)and start timer
IT_TMR
 LD A,DRBbuf  ;update port from buffer
 LD DRB,A  ;send to hardware
 RES NMInt,Flags2  ;tell ExitMain this was NMI interupt
 CALL CLOCKS  ;update clocks
 LD A,XTEMP  ;restore registers
 LD X,A
 LD A,ATemp
 RETI
;***************************************************************************
;*ROM DATA WINDOW for THIRD VOLTS LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the third(least significant)digit of the voltage display.  *
;****************************************************************************
.block 16-$%16
Digits0Vx
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;display_0 for 00h
.byte 01111110b ;display_1 for 01h
.byte 01111110b ;display_1 for 02h
.byte 00110001b ;display_2 for 03h
.byte 00111000b ;display_3 for 04h
.byte 00111000b ;display_3 for 05h
.byte 01011100b ;display_4 for 06h
.byte 10011000b ;display_5 for 07h
.byte 10011000b ;display_5 for 08h
.byte 10010000b ;display_6 for 09h
.byte 00111110b ;display_7 for 0Ah
.byte 00111110b ;display_7 for 0Bh
.byte 00010000b ;display_8 for 0Ch
.byte 00011000b ;display_9 for 0Dh
.byte 00011000b ;display_9 for 0Eh
;***************************************************************************
;*ROM DATA WINDOW for THIRD LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the third(least significant)digit on the LED.   *
;***************************************************************************
.block 16-$%16
Digits00x
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;bit pattern to display_0
.byte 01111110b ;bit pattern to display_1
.byte 00110001b ;bit pattern to display_2
.byte 00111000b ;bit pattern to display_3
.byte 01011100b ;bit pattern to display_4
.byte 10011000b ;bit pattern to display_5
.byte 10010000b ;bit pattern to display_6
.byte 00111110b ;bit pattern to display_7
.byte 00010000b ;bit pattern to display_8
.byte 00011000b ;bit pattern to display_9
;***************************************************************************
;*ROM DATAWINDOW for SECOND LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the second(middle significant)digit on the LED.  *
;***************************************************************************
.block 16-$%16
Digits0x0
;patterns for DigiDat2-Digit 2(middle digit)and MS 1
.byte 00000101b ;bit pattern to display_0_
.byte 11001111b ;bit pattern to display_1_
.byte 00100011b ;bit pattern to display_2_
.byte 10000011b ;bit pattern to display_3_
.byte 11001001b ;bit pattern to display_4_
.byte 10010001b ;bit pattern to display_5_
.byte 00010001b ;bit pattern to display_6_
.byte 11000111b ;bit pattern to display_7_
.byte 00000001b ;bit pattern to display_8_
.byte 10000001b ;bit pattern to display_9_
;***************************************************************************
;*ROM DATA WINDOW for Output Cable Voltage Drop *
;*The following values are the OFFSET values at which Vdrop is adjusted.*
;*The value of OFFSET is a rough indication of the output current,which *
;*is directly related to the voltage drop in the output cable.*
;***************************************************************************
.block 16-$%16
DropOffs
;OFFSET Vdrop Power Current
.byte 0FFh ;00 Low>0.0A
.byte 005h ;01 Low>12A(Max low power)
.byte 005h ;02 Low>12A
.byte 005h ;03 Low>12A
.byte 005h ;04 Low>12A
.byte 005h ;05 Low>12A
.byte 0FFh ;06 High>12A(Min high power)
.byte 0A6h ;07 High>15A
.byte 0A2h ;08 High>17A
.byte 099h ;09 High>22A
.byte 095h ;0A High>25A
.byte 08Fh ;0B High>27A
.byte 08Bh ;0C High>29A
.byte 087h ;0D High>30A
.byte 082h ;0E High>32A
;.byte 07Fh ;0F High>33A(Max high power)
;.byte 070h ;0E High>30.3A
;.byte 069h ;0F High>32.4A
;***************************************************************************
;*ROM DATA WINDOW for Alternator Charge in Percent  *
;*The following values are the Percent values for the alternator voltages *
;*listed below.These numbers are only used when the charger is in *
;*Tester mode.Voltages lower than the first entry are displayed as 0% *
;*charged.Voltages above the last entry are displayed as 199% charged.*
;***************************************************************************
.block 32-$%32
AltLvls
; % Volts Hex
.byte 0 ;13.53 CB red
.byte 12 ;13.60 CC |
.byte 25 ;13.67 CD |
.byte 38 ;13.73 CE red
.byte 50 ;13.80 CF yellow
.byte 62 ;13.87 D0 |
.byte 75 ;13.93 D1 yellow
.byte 85 ;14.00 D2 green
.byte 92 ;14.07 D3 |
.byte 97 ;14.13 D4 |
.byte 100 ;14.20 D5 |
.byte 100 ;14.27 D6 |
.byte 100 ;14.33 D7 |
.byte 100 ;14.40 D8 |
.byte 100 ;14.47 D9 |
.byte 100 ;14.53 DA |
.byte 100 ;14.60 DB |
.byte 103 ;14.67 DC |
.byte 110 ;14.73 DD |
.byte 120 ;14.80 DE green
.byte 130 ;14.87 DF yellow
.byte 140 ;14.93 E0 |
.byte 150 ;15.00 E1 yellow
.byte 160 ;15.07 E2 red
.byte 170 ;15.13 E3 |
.byte 180 ;15.20 E4 |
.byte 190 ;15.27 E5 |
.byte 196 ;15.33 E6 red
.byte 199 ;15.40 E7 red
;***************************************************************************
;*               Interrupt vectors         *
;***************************************************************************
 .org 0FF0h
ADC
 JP ADINT
TIMER
 JP PwrCon
INT2
 NOP
 RETI
INT1
 NOP
 RETt
 .org 0FFCh
NMI
 JP IT_TIMER
RST
 JP RESET
-----------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------1000-P8.asm
;Checksum
;Raw Code:76C48
;With Info:748A5
;***************************************************************************
;*  COPYRIGHT 2003 SCHUMACHER ELECTRIC  *
;*   ALL RIGHTS RESERVED   *
;*   WRITTEN BY    *
;*  THOMAS F.JOHNSON   *
;*     *
;* Schumacher High Frequency Auto Charger/Starter *
;* This code is for the SGS-THOMPSON micro-controler *
;* Part number ST62T15/ST62E15/ST62T25/ST62E25 *
;*        *
;*;************************************************************************
 .title″10000A Ver.0.66″
 .LINESIZE 131
 .vers″ST6225″
 .romsize 4
 .W_ON
DEBUG .SET 1;1->normal,0->Ignore Type and Rate switches after SS5
ShoOff .SET 1;1->normal,0->Show OFFSET Alt% mode during charging
ShoReg .SET 1;1->normal,0->Flash LED′s to indicate up/down change
FastCP .SET 1;1->normal,0->3 min ChkProg interval instead of 60 min
;***************************************************************************
;*  Define the port hardware locations  *
;***************************************************************************
;*  At times,the .def statement is followed by a value and ″!m″.The !m *
;* is used by the simulator/emulator for debugging.This symbol tells the *
;* equipment what registers the user wants to monitor during debuging.  *
;***************************************************************************
X .def 80h!m       ;Index register
Y .def 81h        ;Index register
V .def 82h        ;Short direct register
W .def 83h         ;Short direct register
A .def 0ffh!m      ;Accumulaor
DRA .def 0c0h!m      ;Port a data register
DRB .def 0c1h!m      ;Port b data register
DRC .def 0c2h       ;Port c data register
DDRA .def 0c4h        ;Port a direction register
DDRB .def 0c5h        ;Port b direction register
DDRC .def 0c6h        ;Port c direction register
ORA .def 0cch       ;Port a option register
ORB .def 0cdh       ;Port b option register
ORC .def 0ceh       ;Port c option register
ADR .def 0d0h!m      ;A/D data register
ADCR .def 0d1h        ;A/D control register
PSC .def 0d2h       ;Timer prescaler register
TCR .def 0d3h!m      ;Timer counter register
TSCR .def 0d4h        ;Timer status control register
WDR .def 0d8h         ;Watchdog register
IOR .def 0c8h!m      ;Interrupt option register
DRWR .def 0c9h          ;Data rom window register
;***************************************************************************
;*     These are the ram equates used by the battery charger.    *
;***************************************************************************
DRAbuf .def 084h ;shadow ram for port A data register
DRBbuf .def 085h ;shadow ram for port B data register
DRCbuf .def 086h ;shadow ram for port C data register
ATemp .def 087h ;Accumulator temporary storage
XTEMP .def 088h ;X register temporary storage
MSECs1 .def 089h ;storage for 8.333 ms tics -count of 120=1 sec
SECs1 .def 08Ah ;storage for timer1 seconds
MINs1 .def 08Bh ;storage for timer1 minutes
HRs1 .def08Ch ;storage for timer1 hours
TicFlag1 .def 08Dh ;overflow flags for SECs1,MINs1,and hours
MSECs2 .def 08Eh ;millisecond one counter
SECs2 .def 08Fh ;storage for timer2 seconds
MINs2 .def 090h ;storage for timer2 minutes
HRs2 .def 091h ;storage for timer2 hours
TicFlag2 .def 092h ;overflow flags for secs1,MINs2,and hours1
Tries .def 093h ;used by battery detect routines
TEMP .def 094h ;scratch pad area
TEMP1 .def 095h ;scratch pad area
Temp2 .def 096h ;count used for FreshBV
CurVolt .def 097h ;current battery voltage
MaintVolt .def 098h ;storage for MAINTAIN voltage level
OldVolt .def 099h ;previous battery voltage.used for dv/dt
CCDcnt .def 09Ah ;display countdown during crank cool down
OldOff .def 09Bh ;old value of OFFSET used in dI/dt
BADlo .def 09Ch ;low bits battery voltage average
BADhi .def 09Dh ;hi bits battery voltage average
Vmax .def 09Eh ;maximum battery voltage(per Battery Type)
Vref .def 09Fh ;refvoltage for desulfation
OFFSET.def 0A0h ;storage for phase delay value
FreshBV .def 0A1h ;avg batt volt used for di/dt ref
FBVTotLo .def 0A2h ;low byte of total used for FreshBV
FBVTotHi .def 0A3h ;high byte of total used for FreshBV
CurentSS .def 0A4h ;stores current charger state
Flags .def 0A5h ;charger configuration states
  ;bit 0(BatTypeA):(0 for Reg,1 for D/C)
  ;bit 1(BatTypeB):(0 for Norm,1 for AGM/GEL)
  ;bit 2(Rate):(0 for Slow,1 for Fast)
  ;bit 3(Crank):1 if in Boost mode
  ;bit 4(CrankWait):1 during E/S cool down
  ;bit 5(Started):1 if charging started
  ;bit 6(MtrUnits):(0 for Volts,1 for %)
  ;bit7(MtrScale):(0 for Batt,1 for Alt)
Flags2 .def 0A6h ;stores the following Flags
  ;bit 0(Batt):1 if battery connected
  ;bit 1 (Rapid):1 if set for Rapid charge rate
  ;bit 2(Bat6V):1 if set for 6V battery
  ;bit 3(Relay):1 if output relay is closed
  ;bit 4(NMInt):1 if NMI interrupt,0 if Timer
  ;bit 5(ChMode):1 if in Charger Mode
  ;bit 6(Wait0P):1 if waiting for % to change from 0
  ;bit 7(Alert):1 indicates Alert condition
Flags3.def 0A7h ;stores the following Flags
  ;bit 0(Rmpng):1 during Rapid->Fast transition
  ;bit 1(Settle):1 during voltage settle time
  ;bit 2(RmpInt):1 during 1 st half of each Ramp interval
  ;bit 3(Idle):1until a button is pressed
  ;bit 4(RampUp):0->ramping down,1->ramping up
  ;bit 5(NxtCnt):1->1 st second of count
  ;bit 6(Manual):1 if in Manual Mode
  ;bit 7(BurnIn):1 if in Bum-in Mode
SwDown .def 0A8h ;Indicates state of switches(1->pressed)
  ;bit 3(SOC):1 if at start of charge(1 st 5s)
  ;bit 4(SwOff):1 when igoring Type & Rate switch(debug)
  ;bit 5=Type switch
  ;bit 6=Rate switch
  ;bit 7=Meter switch
DigiDat2 .def 0A9h ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 3 segments B & C
  ;bit 1=digit 2 segment F
  ;bit 2=digit 2 segment G
  ;bit 3=digit 2 segment A
  ;bit 4=digit 2 segment B
  ;bit 5=digit 2 segment C
  ;bit 6=digit 2 segment D
  ;bit 7=digit 2 segment E
DigiDat1 .def 0AAh ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 1 segment C
  ;bit 1=digit 1 segment G
  ;bit 2=digit 1 segment D
  ;bit 3=digit 1 segment E
  ;bit 4=digit 2 decimal point
  ;bit 5=digit 1 segment F
  ;bit 6=digit 1 segment A
  ;bit 7=digit 1 segment B
SwData .def0ABh ;data for the 3 Rate and 3 Type LEDs(0->ON,1->off)
  ;bit 0=6V battery type LED
  ;bit 1=Reg battery type LED
  ;bit 2=D/C battery type LED
  ;bit 3=AGM battery type LED
  ;bit 4=40A charge rate LED
  ;bit 5=15A charge rate LED
  ;bit 6=100A charge rate LED
  ;bit 7=2A charge rate LED
BitCnt .def 0ACh ;Index of bit sent to display
BytCnt .def 0ADh ;Index of word sent to display
DataBuf .def 0AEh ;Temp storage for Data bits
VltCnt .def 0AFh ;Counter for voltage display interval
LastBatt .def 0B0h ;stores battery reading used to monitor progress
RmpCnt .def 0B1h ;counts ramp intervals until next ramp
LEDnum .def 0B2h ;stores number to be shown on digital LED
Percent .def 0B3h ;stores percent to be shown on digital LED
Index .def 0B4h ;used for look up table access
Vdrop .def 0B5h ;estimate of voltage drop in output cable
VRcnt .def 0B6h ;Counter for voltage regulation interval
PcntL .def 0B7h ;NMI counter for percent display update
PcntH .def 0B8h ;Interval counter for percent display update
DspPcnt .def 0B9h ;storage for last percent displayed
Flags4 .def 0BAh ;stores the following Flags
  ;bit 0(IdleSet):1 if 10 minute Idle timer was started
  ;bit 1(MinOut):1 when min rate is needed for VoltReg
  ;bit 2(RlySw):1 too soon to switch relay
  ;bit 3(RlyCls):1 if relay was closed
  ;bit 4(VRlmt):1 if VoltReg limit reached
  ;bit 5(HiPwr):1 if charge rate>Fast
  ;bit 6(Hi6V):1 if battery>8.5V
  ;bit 7(IPSlo):1 if intemal power supply<18V
CurIPS .def 0BBh ;storage for current internal power supply voltage
IPSref .def 0BCh ;storage for old internal power supply voltage
ORBbuf .def 0BDh ;shadow RAM for ORB register
;free .def 0BEh ;free
;free .def 0BFh ;free
;0BFh=last RAM location
;***************************************************************************
;* These are the constants used by the battery charger.  *
;***************************************************************************
Volts001 .equ 001h ;0.067 VOLTS
Volts002 .equ 003h ;0.2 VOLTS
Volts004 .equ 006h ;0.4 VOLTS
Volts005 .equ 008h ;0.5 VOLTS
Volts006 .equ 009h ;0.6 VOLTS
Volts0 .equ 00Ah ;0.7 VOLTS
Volts008 .equ 00Ch ;0.8 VOLTS
Volts01 .equ 00Fh ;1.0 VOLTS
Volts013 .equ 013h ;1.3 VOLTS
Volts016 .equ 017h ;miminum voltage for engine start,1.5V
Volts02 .equ 01Eh ;2.0 VOLTS
Volts05 .equ 04Bh ;5.0 VOLTS
Volts06 .equ 05Ah ;6.0 VOLTS
Volts066 .equ 061h ;6.6 VOLTS
Volts075 .equ 071h ;7.5 VOLTS
Volts09 .equ 087h ;very discharged battery voltage
Volts10 .equ 096h ;10.0 VOLTS
BattMin .equ 0AFh ;lowest value in Battery % LUT
Volts12 .equ 0B4h ;low battery voltage
Volts121 .equ 0B6h
Volts122 .equ 0B7h
Volts124 .equ 0BAh
Volts125. equ 0BCh
Volts126 .equ 0BDh
BattMax .equ 0BDh ;highest value in Battery % LUT
Volts127 .equ 0BEh
Volts128 .equ 0C0h
Volts129 .equ 0C1h ;good battery test voltage
Volts13 .equ 0C3h
Volts132 .equ 0C6h
Volts133 .equ 0C8h
Volts135 .equ 0CAh
AltMin .equ 0CBh ;lowest value in Alternator % LUT
Volts137 .equ 0CDh
Volts138 .equ 0CFh
Volts139 .equ 0D1h
Volts14 .equ 0D2h
Volts142 .equ 0D5h ;start monitoring dv/dt voltage
Volts1435 .equ 0D7h
Volts144 .equ 0D8h
Volts146 .equ 0DAh ;maximum allowed voltage for reg/gel mode
Volts147 .equ 0DCh ;start trickle timer voltage
Volts149 .equ 0E0h ;14.87V
Volts15 .equ 0E1h ;maximum allowed voltage for RV/DC Marine
Volts15a .equ 0E2h ;15.07V
Volts153 .equ 0E6h;
AltMax .equ 0E7h ;highest value in Alternator % LUT
Volts155 .equ 0E9h ;maximum allowed voltage for Auto/Marine Starting
Volts16 .equ 0F0h ;maximum allowed voltage
Volts165 .equ 0F7h ;maximum allowed voltage for deep cycle 2
MaxVolts .equ 0FFh ;maximum voltage reading -17.0V
MaxDrop .equ 00Ah ;maximum output cable voltage drop
MinIPS .equ 097h ;minimum internal power supply voltage
RCinit .equ 064h ;1003/8-second intervals yields 37.5 seconds
RCinitX2 .equ 0C8h ;200 3/8-second intervals yields 75 seconds
RIinit .equ 02Dh ;45 NMI interrupts yields 0.375 seconds
;RIinit .equ 0FFh ;240 NMI interrupts yields 2.0 seconds **DEBUG**
MSINIT .equ 078h ;millisecond initialization value(120)
MS500 .equ 03Ch ;millisecond counter value for 500mS(60)
MS200 .equ 018h ;millisecond counter value for 200mS(24)
MS100 .equ 00Ch ;millisecond counter value for 100mS(12)
;MSINIT .equ 07Fh ;millisecond initialization value(127)
;MS500 .equ 03Fh ;millisecond counter value for 500mS(60)
SecIuit .equ 03Ch ;second initialization value(60)
MININIT .equ 03Ch ;minute initialization value(60)
MaxHrs .equ 25 ;maximum allowed charge time,24 hours+1
CPint .equ 60 ;minutes per charge progress interval
HR .equ 000h ;hours bit of TicFlag1 and TicFlag2
MIN .equ 001h ;minutes bit of TicFlag1 and TicFlag2
SEC .equ 002h ;seconds bit of TicFlag1 and TicFlag2
MSEC .equ 003h ;milliseconds bit of TicFlag1 and TicFlag2
VLO .equ 0C0h ;low line limit-100 VAC
VHI .equ 0EEh ;high line voltage limit-130 VAC
PCint .equ 00Ah ;number of 1-second intervals between % updates
RlyInt .equ 005h ;relay switching interval(minimum)
FULLTIME .equ 0B4h ;half second when AC power is OFF
MinOff .equ 005h ;Min offset->max duty cycle
SlowAmps .equ 2 ;Nominal amps out at Slow rate
FastAmps .equ 15 ;Nominal amps out at Fast rate
RapAmps .equ 40 ;Nominal amps out at Rapid rate
CmkAmps .equ 100 ;Nominal amps out at Crank rate
CodeRev .equ 0 ;software revision level
OffSlow .equ 0A3h ;Nominal offset for slow charge(2A)163
OffSafe .equ 09Ah ;Nominal offset for safe charge(~5A)154
OffSafer .equ 08Fh ;Nominal offset for safer charger(-10A)143
OffFast .equ 086h ;Nominal offset for fast charge(15A)134
OffRap .equ 05Dh ;Nominal offset for rapid charge(40A)93
Off6Slo .equ 0A0h ;Nominal offset for 6V slow charge(2A)
Off6Fst .equ 086h ;Nominal offset for 6V fast charge(15A)
Off6Rap .equ 065h ;Nominal offset for 6V rapid charge(40A)
OffCrank .equ 07Eh ;OFFSET for Crank standby
HiOff .equ 0A7h ;high limit for OFFSET variable
ABORT .equ 008h ;abort state
LEDslow .equ 007h ;Slow LED -bit of SwData
LEDboost .equ 006h ;Crank LED -bit of SwData
LEDfast .equ 005h ;Fast LED -bit of SwData
LEDrap .equ 004h ;Rapid LED-bit of SwData
LEDgel .equ 003h ;AGM/Gel LED-bit of SwData
LEDdeep .equ 002h ;Dp Cycl LED-bit of SwData
LEDreg .equ 001h ;Regular LED-bit of SwData
LED6V .equ 000h ;6V Reg LED-bit of SwData
LEDdone .equ 000h ;Charged LED-PORT A
LEDchgng .equ 001h ;Charging LED-PORT A
LEDalert .equ 002h ;Fault LED-PORT A
LEDprcnt .equ 003h ;Percent LED-PORT A
LEDvolt .equ 004h ;Voltage LED-PORT A
LEDalt .equ 005h ;Altrntr LED-PORT A
SerData .equ 006h ;Serial Data-PORT A
ClrData .equ 007h ;Data Clear-PORT A
ShftClk .equ 000h ;Shift Clock-PORT B
LtchClk .equ 001h ;Latch Clock-PORT B
RlyCtl .equ 002h ;Relay cntrl-PORT B
Disable .equ 003h ;Disable ctrl-PORT B
BattA2D .equ 005h ;Battery A/D-PORT B
IPSA2D .equ 006h ;Int.PS A/D-PORT B
PWMhi .equ 007h ;Hi PWM ctrl-PORT B
FanCtl .equ 004h ;Fan control-PORT C
TypeSw .equ 005h ;Type switch-PORT C
RateSw .equ 006h ;Rate switch-PORT C
MeterSw .equ 007h ;Meter switch -PORT C
SOC .equ 003h ;bit in SwDown:1 during Start Of Charge(1 st 5 sec)
SwOff .equ 004h ;bit in SwDown:1 for disabled Type & Rate switches
BatTypeA .equ 000h ;bit in Flags for battery type:0=Reg,1=D/C
BatTypeB .equ 001h ;bit in Flags for battery type:1=AGM/Gel Cell
Rate .equ 002h ;bit in Flags for charge rate:0=Slow,1=Fast
Crank .equ 003h ;bit in Flags that indicates engine start
CrankWait .equ 004h ;bit in Flags that indicates cool down between cranks
Started .equ 005h ;bit in Flags that indicates charge started
MtrUnits .equ 006h ;bit in Flags for meter units:0=volts,1=%
MtrScale .equ 007h ;bit in Flags for meter scale:0=batt,1=altrntr
Batt .equ 000h ;bit in Flags2:1 if battery is connected
Rapid .equ 001h ;bit in Flags2:1 if charge rate is Rapid
Bat6V .equ 002h ;bit in Flags2:1 if battery type is 6V
Relay .equ 003h ;bit in Flags2:1 if output relay is closed
NMInt .equ 004h ;bit in Flags2:1 if NMI interrupt,0 if Timer
ChMode .equ 005h ;bit in Flags2:1 if in Charger mode(not Tester)
Wait0P .equ 006h ;bit in Flags2:1 if battery>10V
Alert .equ 007h ;bit in Flags2:1 indicates trouble
Rmpng .equ 000h ;bit in Flags3:1 during Rapid->Fast transition
Settle .equ 001h ;bit in Flags3:1 during voltage settle time
RmpInt .equ 002h ;bit in Flags3:1 during 1 st half each Ramp interval
Idle .equ 003h ;bit in Flags3:1 until a button is pressed
RampUp .equ 004h ;bit in Flags3:0->ramping down,1->ramping up
NxtCnt .equ 005h ;bit in Flags3:0 during last half of CCDcnt interval
Manual .equ 006h ;bit in Flags3:1 during Manual modes
BurnIn .equ 007h ;bit in Flags3:1 during Burn-In mode
IdleSet .equ 000h ;bit in Flags4:1 if 10 minute Idle timer was started
MinOut .equ 001h ;bit in Flags4:1 when min rate is needed for VoltReg
RlySw .equ 002h ;bit in Flags4:1 when too soon to switch relay
RlyCls .equ 003h ;bit in Flags4:1 when relay was closed
VRlmt .equ 004h ;bit in Flags4:1 if VoltReg limit reached
HiPwr .equ 005h ;bit in Flags4:1 if charge rate>Fast
Hi6V .equ 006h ;bit in Flags4:1 ifbattery>8.5V
IPSlo .equ 007h ;bit in Flags4:1 if internal power supply<18V
CrankOff .equ 120;crank off time in seconds(120)
CrankON .equ 005h ;crank on time in seconds(5)
CCDint .equ 001h ;crank cool down display counter interval(seconds)
CrankSS .equ 010h ;crank SS is state 16=10 hex
Decimal .equ 004h ;bit in DigiDatl for decimal point
Digit1.equ 000h ;bit in DigiDat2 for most significant 1
SwsOff .equ 11111111b ;bit pattern for all switches off
DigiOffa .equ 11111111b ;bit pattern for all segements off
DigiOffb .equ 11111111b ;bit pattern for all segements off
DigiONa .equ 00000000b ;bit pattern for all segements ON
DigiONb .equ 00000000b ;bit pattern for all segements ON
Dashes1 .equ 11111101b ;bit pattern to display_-
Dashes2 .equ 11111011b ;bit pattern to display_-_
DigiRev1 .equ 00010000b ;bit pattern to display_8_
DigiRev2 .equ 01100001b ;bit pattern to display_P_
;***************************************************************************
;*                    COLD START                     *
;***************************************************************************
;.org 0880h ;for ST6210/15
 .org 0100h ;for ST6220/25
RESET
 CALL RstWDR ;reset watch dog timer
;***************************************************************************
;*              Clear The Ram Area              *
;***************************************************************************
RAMCLR
 LDI X,084h ;point X to 1st RAM Location
RAMCLR1
 CLR A  ;clear A
 LD(X),A  ;store A at location pointed to by X
 INC X  ;increment X
 LD A,X  ;get pointer in A
 CPI A,0C0h  ;test for end of RAM
 JRNZ RAMCLR1  ;do again if not finished
;***************************************************************************
;*         Now Set Up The Hardware I/O Ports        *
;***************************************************************************
PORTA
 ;Bit 0=LED-Done(Output,0=ON)
 ;Bit 1=LED-Charging(Output,0=ON)
 ;Bit 2=LED-Alert(Output,0=ON)
 ;Bit 3=LED-Battery%(Output,0=ON)
 ;Bit 4=LED-Volts DC(Output,0=ON)
 ;Bit 5=LED-Altrntr%(Output,0=ON)
 ;Bit 6=Serial Data(Output,0=ON)
 ;Bit 7=Display Clear(Output,0=clear)
;      Bit#76543210
LDI DDRA,11111111b ;Set all bits as outputs
LDI ORA,11000000b ;open-drain outputs 0-5;6-7 push-pull
LDI DRA,11111111b ;Set initial values to 1(off)
LDI DRAbuf,11111111b ;store settings in shadow RAM
PORTB
 ;Bit 0=Shift clock(Output,0->1=Shift)
 ;Bit 1=Latch clock(Output,0->1=Latch)
 ;Bit 2=Relay control(Output,0=open,1=closed)
 ;Bit 3=Disable out(Output,1=disabled)
 ;Bit 4=SCR control(Output,0=Off,1=ON)
 ;Bit 5=Batt Voltage(Input,Analog)
 ;Bit 6=Int Voltage(Input,Analog)
 ;Bit 7=0A-100A PWM(Output,0=0A,1=100A)
;       Bit#76543210
 LDI DDRB,10011111b ;bits 5&6 are inputs,others are outputs
 LDI ORB,00111111b ;Setpush-pull outputs*,analog input
   ;*bit 7 is open drain output
LDI ORBbuf,00111111b ;store settings in shadow RAM
LDIDRB,11101011b ;Set push-pull output,inputs=0
LDI DRBbuf,11101011b ;store settings in shadow RAM
PORTC
 ;Bit 4=Fan Control(Ouput,0=off,1=ON)
 ;Bit 5=Type switch(Input,0=IN/change)
 ;Bit 6=Rate switch(Input,0=IN/change)
 ;Bit 7=Meter switch(Input,0=IN/change)
;      Bit# 76543210
 LDI DDRC,00011111b ;bit 4 is output,others are inputs
 LDI ORC,00011111b ;non-interrupt inputs,push-pull output
 LDI DRC,00001111b ;Set internal pull-ups for bits 5-7
 LDI DRCbuf,00001111b ;store settings in shadow RAM
 TSCRINIT
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 SET 4,IOR      ;enable interupts
 RETI
 CALL InitState ;initialize to slow(2A)auto mode
;The next three lines are to set the maximum idle tester time
CALL IniTime1  ;initialize timer 1
LDI MINs1,0Ah  ;set timer 1 for 10 minutes
SET Idle,Flags3  ;indicates no buttons pressed yet
;The next three lines set the unit for Tester(not Charger)mode
 RES ChMode,Flags2  ;set for Tester Mode
 CALL ShowData  ;initialize display
INIT_01
;JP MAIN  ;debug
;***************************************************************************
;*    Test Routines   *
;*This routine checks the switches at power up to determine whether to *
;*enter one of the test modes.The possible test modes and the switch *
;*combinations that trigger them are as follows.  *
;*       *
;*Meter Rate Type Test Mode          *
;*Y x N Power On Self Test (POST):LED′s light in sequence *
;*N Y N Manual Slow Charge(1 hour max for all manual mode) *
;*N N  Y Manual Medium Charge(Fast for boost models)  *
;*N Y  Y Manual Fast Charge(Fast-Rapid for boost models) *
;*Y x Y Burn-In Mode:Fast/Rapid Charge for 199 minutes  *
;*       *
;*Y->pressed,N->not pressed,x->either(not checked)*
;*       *
;***************************************************************************
TEST
 JRS MeterSw,DRC,NoPOST ;Skip ahead if display mode button not pressed
 JRS TypeSw,DRC,POST ;Skip to POST if Type button not pressed
 JP TestBI  ;...otherwise,skip ahead to Burn-In setup
NoPOST
 CALL FifthSecond ;wait one fifth second
 JRR RateSw,DRC,TEST1;Check Type switch ifRate switch is pressed
 JRS TypeSw,DRC,NoTest ;go to MAIN if no switch is pressed
  ;Set for Manual Fast Charge
SET Rate,Flags  ;turn on Fast LED,turn off Slow LED
 RES Rapid,Flags2 ;turn off Rapid LED
 CALL SetFast  ;set to ramp from OffSafe to OffFast
 JP TestMM1  ;set forManual charge
NoTest
 JP MAIN  ;skip test and go to MAIN
TEST1  ;Set for manual Slow Charge
 JRR TypeSw,DRC,TEST2 ;if Type switch is pressed,set for Fast Test
 LDI OFFSET,OffSlow ;set Offset for 2A
 CALL SetSlow  ;set for Slow Rate
 JP TestMM1  ;set for Manual charge
 TestBI  ;Set for 60 minute Burn-In
 SET BurnIn,Flags3  ;Set for Burn-In mode
 CALL SetFast  ;set to ramp from OffSafe to OffFast
 CALL SetRmpUp  ;prepare to ramp from Fast to Rapid
 TEST2  ;set for Manual Rapid Charge
 SET Rapid,Flags2  ;turn on Rapid LED
 SET Rate,Flags  ;set for non-Slow rate
 CALL SetSafe  ;set OFFSET for OffSafe(~5A)when relay closes
 JRS BurnIn,Flags3,TestRap ;don′t set for ramp down if Burn-In
 LDI VRcnt,OffSafe-OffRap ;ramp from OffS afe to OffRap
 LDI RmpCnt,RCinit  ;100 0.75-second intervals yields 75 secs
 RES RampUp,Flags3 ;set for ramp down
 CALL SetRamp ;set ramping parameters
TestRap
 JP TestMM1  ;set for Manual charge
POST
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ModeOff  ;turn off all display mode LED′s
 CALL DigitsOft  ;turn off 3-digit LED
 RES RlyCls,Flags4  ;make sure output relay will be open
 CALL Set12V  ;set for Regular,12V battery
 CALL HoldType  ;show Type and wait a fifth second
 SET BatTypeA,Flags  ;turn on Deep Cycle & turn off Regular LED
 CALL HoldType  ;show Type and wait a fifth second
 SET BatTypeB,Flags  ;turn on Gel/AGM LED
 RES BatTypeA,Flags  ;turn offDeep Cycle LED
 CALL HoldType  ;show Type and wait a fifth second
 RES BatTypeB,Flags  ;turn off Gel/AGM LED
 SET Bat6V,Flags2  ;turn ON 6V LED
 CALL HoldType  ;show Type and wait a fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 RES Bat6V,Flags2  ;set for 12V battery(not 6V)
 SET ChMode,Flags2  ;must set flag to show rate LED′s
 RES Crank,Flags  ;turn off Crank LED
 CALL SetSlow  ;set for Slow Rate
 LDI LEDnum,SlowAmps ;set digital LED to show Slow rate
 CALL HoldRate  ;show Rate and wait a fifth second
 SET Rate,Flags  ;turn on Fast LED
 LDI LEDnum,FastAmps ;set digital LED to show Fast rate
 CALL HoldRate  ;show Rate and wait a fifth second
 SET Rapid,Flags2 ;turn on Rapid LED
 LDI LEDnum,RapAmps ;set digital LED to show Rapid rate
 CALL HoldRate  ;show Rate and wait a fifth second
 RES ChMode,Flags2 ;clear flag to disable output
 LDI LEDnum,CrnkAmps ;set digital LED to show Crank rate
 CALL ShowNum  ;get data to show the LED number
 CALL ShowCrank  ;turn on Crank(Boost)LED
 CALL FifthSecond  ;wait one fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowData  ;update display
 SET MtrUnits,Flags  ;set for % LEDs ON,volts LED off
 RES MtrScale,Flags  ;set for Alternator % LED off
 LDI DigiDat1,DigiRev1 ;set digital LED to show Code Revision
 LDI DigiDat2,DigiRev2 ;set digital LED to show Code Revision
 CALL ShowData  ;update display
 CALL HoldMtrMd  ;show display mode and wait one fifth second
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
 CALL HoldMtrMd  ;show display mode and wait one fifth second
 SET MtrUnits,Flags  ;set for % LEDs ON,volts LED off
 SET MtrScale,Flags  ;set for Alternator % LED ON
 CALL HoldMtrMd  ;show display mode and wait one fifth second
 CALL ModeOff  ;turn off all display mode LED′s
 CALL AlertON  ;turn on Alert(Red)LED
 CALL FifthSecond  ;wait one fifth second
 CALL ShowChgng  ;light Charging LED
 CALL FifthSecond  ;wait one fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL FifthSecond  ;wait one fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 LDI LEDnum,5  ;initialize to 5 to show 4 1st
POST2
 DEC LEDnum  ;the next number will be 1 less
 CALL HoldNum  ;show LEDnum,wait 200mS,and load into A
;CALL NumData  ;get data for,and show LED number
;CALL FifthSecond ;wait one fifth second
;LD A,LEDnum  ;check for last number
 JRNZ POST2  ;loop back and repeat if not there
;JR ZPOST3  ;skip ahead if there
;JP POST2  ;...otherwise,loop back & repeat
POST3
 ADDI A,20  ;adding 20 changes 2nd digit
 LD LEDnum,A  ;prepare to show new number
 CALL HoldNum  ;show LEDnum,wait 200mS,and load into A
;CALL NumData  ;get data for,and show LED number
;CALL FifthSecond ;wait one fifth second
;LD A,LEDnum  ;check latest number
 CPI A,100  ;compare to last number
 JRNZ POST3   ;loop back and repeat if not there
;JRZ POST4  ;skip ahead if there
;JP POST3  ;...otherwise,loop back & repeat
;POST4
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL InitState  ;reset to Slow,TypeA charge mode
 RES ChMode,Flags2 ;set for Tester mode
 JP TEST   ;repeat POST if necessary
 TestMM1   ;Set for manual charge
 SET Manual,Flags3  ;set for Manual mode
 SET ChMode,Flags2  ;set for Charger Mode(output enabled)
 RES Disable,DRBbuf ;enable output
 LDI CurentSS,15 ;State 15 is Manual charge
 SET Started,Flags ;set Flags for charge started
 SET RlyCls,Flags4  ;close output relay
 JRR Rate,Flags,TstSlow ;skip ahead if set for Slow rate
 CALL FifthSecond ;wait one fifth second
 CALL FstRmp  ;ramp from OffSafe to OffFast or OffRap
TstSlow
 CALL IniTime1  ;initialize Timer1
 LDI HRs1,1   ;set Timer1 for 1 hour
;LDI MINs1,5  ;set Timer1 for 5minutes **DEBUG**
 .IFC NE ShoOff ;assemble next line only if not debugging
 JRR BurnIn,Flags3,MAIN ;skip next 2 lines if not Burn-in
 .ENDC
TestMM2
 CALL IniTime2  ;reset Timer2
 .IFC NE ShoOff ;assemble next line only if not debugging
 LDI MINs2,1  ;set timer for counter interval(1 minute)
 .ENDC
 LDI CCDcnt,60  ;set Burn-in minute counter to 60
;***************************************************************************
;*                MAIN                     *
;***************************************************************************
;***************************************************************************
;*Because the A/D voltage is being averaged,it would take considerable  *
;*time to notice that a battery has become disconnected.To overcome this *
;*DELAY the program will monitor the instantaneous voltage each time thru *
;*the loop to detect this condition.This check will be made only ifthe *
;*unit is in a charging mode.                            *
;***************************************************************************
MAIN
 CALL RstWDR  ;reset watch dog timer
 LD A,CurentSS  ;get current state
 CPI A,ABORT  ;check for abort
 JRNZ MainMore  ;continue Main ifnot Abort
 JP MAIN3  ;don′t continue Main if Abort
MainMore
 JRR Manual,Flags3,MainMan ;continue Main if not Manual Mode
 JP SS15  ;otherwise,goto Manual charge
MainMan
 JRS CrankWait,Flags,MAIN1;don′t check switches during Crank wait
 CALL CheckSw  ;check if switch is being pressed
MAIN4
 JRS IPSlo,Flags4,MainIPS ;don′t check for Crank if checking IPS
 JRS Crank,Flags,MAIN0 ;skip ahead if during Crank
MainIPS
 JRS Crank,Flags,MainIPS2 ;don′t update % if Crank & checking IPS
 CALL GetPercent ;update the percentage reading
 CALL UpdateBP  ;update % to display
MainIPS2
 CALL GetMeter  ;update display
 JRR Idle,Flags3,MAIN0  ;skip ahead ifnot idle
 JRR Batt,Flags2,MAIN0  ;don′t check idle time limit if no battery
 JRS IdleSet,Flags4,MAIN5 ;don′t set idle timer if already set
 CALL IniTime1  ;...otherwise initialize timer 1
 LDI MINs1,0Ah  ;set timer 1 for 10 minutes
 SET IdleSet,Flags4  ;Idle timer started,set flag
MAIN5
 JRR MIN,TicFlag1,MAIN0 ;...otherwise,check idle time limit
 RES Disable,DRBbuf ;...enable output after idle time limit
 JP MAIN2  ;...and re-initialize if reached
 MAIN0  ;not Crank,check for 0 or 1
 JRS RlyCls,Flags4,MAIN1 ;charger is ON,goto 0V check
 JRS LEDchgng,DRAbuf,MAIN3 ;charger not almost on,skip 0V check
;JRR LEDchgng,DRAbuf,MAIN1 ;charger is almost on,goto 0V check
;JP MAIN3  ;charger is OFF,goto Main3
MAIN1  ;Check for disconnected battery
 CALL CheckBatt  ;check for disconnected battery
 JRS Batt,Flags2,MAIN3  ;skip ahead if connected
 MAIN2  ;0V detected,prepare to start over from state 0
 LDI DspPcnt,0  ;initialize display Percent to 0
 CALL InitState  ;initialize to Slow Regular Charge mode
MAIN3
;***************************************************************************
;*            SEQUENCE STATE JUMP TABLE                             *
;*Determine what routine to execute on this pass through the the loop.Only*
;*one routine is executed each time through the loop.             *
;***************************************************************************
NSS0
 LD A,CurentSS
 JRNZ NSS1
 JP SS0 ;* SS0-BATTERY DETECT *
NSS1
 CPI A,001h
 JRNZ NSS2
 JP SS1 ;* SS1-BATTERYDETECT DELAY *
NSS2
 CPI A,002h
 JRNZ NSS3
 JP SS2 ;* SS2-AUTOMATIC CHARGE START *
NSS3
 CPI A,003h
 JRNZ NSS4
 JP SS3 ;* SS3-BELOW 9 Volts *
NSS4
 CPI A,004h
 JRNZ NSS5
 JP SS4 ;* SS4-BELOW 12 Volts *
NSS5
 CPI A,005h
 JRNZ NSS7
 JP SS5 ;*SS5-NORMAL CHARGE *
;NSS6
;CPI A,006h
;JRNZ NSS7
;JP SS6 ;*SS6-dv/dt MONITOR * NOT USED
NSS7
 CPI A,007h
 JRNZ NSS8
 JP SS7 ;*SS7-wait for good IPS
NSS8
 CPI A,008h
 JRNZ NSS9
 JP SS8 ;* SS8-ABORT CHARGE *
NSS9
 CPI A,009h
 JRNZ NSS11
 JP SS9 ;* SS9-DESULFATION *
;NSS10
;CPI A,00Ah
;JRNZ NSS11
;JP SS10 ;* SS10-RESTORE CHARGE *
NSS 11
 CPI A,00Bh
 JRNZ NSS12
 JP SS11 ;* SS11-dV/dt MONITOR *
NSS12
 CPI A,00Ch
 JRNZ NSS13
 JP SS12 ;*SS12-dI/dt MONITOR *
NSS13
 CPI A,00Dh
 JRNZ NSS14
 JP SS13 ;* SS13-ENDCHARGE *
NSS14
 CPI A,00Eh
 JRNZ NSS15
 JP SS14 ;*SS14-MAINTAIN *
NSS15
 CPI A,00Fh
 JRNZ NSS16
 JP SS15 ;* SS15-Manual *
NSS16
 CPI A,010h
 JRNZ NSS 17
 JP SS16 ;* SS16-CRANK *
NSS17
 CPI A,011h
 JRNZ NSS18
 JP SS17 ;* SS17-CRANK *
NSS18
 CPI A,012h
 JRNZ NSS19
 JP SS18 ;* SS18-CRANK *
NSS19
 CPI A,013h
 JRNZ NSS20
 JP SS19 ;* SS19-CRANK *
NSS20
 CPI A,014h
 JRNZ NSS21
 JP SS20 ;* SS20-CRANK *
NSS21
 LDI WDR,001h      ;invalid sequence state,reset
;***************************************************************************
;*                 END OF MAIN          *
;*Wait for NMI,which indicates end of FET on period,before measuring *
;*battery voltage.                            *
;***************************************************************************
ExitMain
XMain
 WAIT  ;wait for interupt
 JRS NMInt,Flags2,XMain ;timer interupt???
;***************************************************************************
;*                READ BATTERY VOLTAGE                          *
;*This routine is executed at or near zero cross.The current voltage *
;*is stored in CurVolt and the reading is added to BADhi(two locations).*
;*BADhi will contain a running average of the last 256 readings.       *
;***************************************************************************
BADREAD
 LD A,BADlo  ;get average reading
 SUB A,BADhi  ;subtract one reading from the running total
 JRNC BADREAD1  ;no carry,go on
 DEC BADhi  ;adjust high order bits
BADREAD1
 LD BADlo,A  ;store new value
 LDI ADCR,0B0h  ;start A/D conversion
 LDI ADCR,0B0h  ;do again to insure a valid start
 WAIT  ;let the interupt notify us when data is ready
 LD CurVolt,A  ;save current reading
 ADD A,BADlo  ;add into running average
 JRNC BADREAD2  ;no carry,go on
 INC BADhi ;increment high bits
BADREAD2
 LD BADlo,A  ;store new low bits
;LDI ORB,01Fh
;LDI ORB,09Fh
;***************************************************************************
;*               di/dt AVERAGE CALCULATION                        *
;*For use by the di/dt,about four times every second the average of the *
;*previous 32 curvolt readings is stored in FreshBV for comparison to a *
;*reading taken once every second.     *
;***************************************************************************
DIDTAVG
 LD A,Temp2  ;if Temp2=0 then first reading
 JRNZ DIDTAVG1  ;skip init if not 1 st reading
 LDI Temp2,020h  ;initialize Temp 2 to 32
DIDTAVG1
 LD A,FBVTotLo ;
 ADD A,CurVolt ;add current voltage to total
 JRNC DIDTAVG2 ;don′t inc high byts ifno carry
 INC FBVTotHi ;inc high byte
DIDTAVG2
 LD FBVTotLo,A ;update total
 DEC Temp2 ;update Temp2
 JRZ DIDTAVG3 ;compute avg
 JP DIDTAVGX ;exit to Main
DIDTAVG3
 LDI Temp2,003h ;prepare to shift 3 times
DIDTAVG6
 LD A,FBVTotHi ;load high byte of total into accumulator
 SLA A ;shift accumulator left
 LD FBVTotHi,A ;update high byte of total
 LD A,FBVTotLo ;load low byte of total into accumulator
 SLA A  ;shift accumulator
 LD FBVTotLo,A ;update low byte of total
 JRNC DIDTAVG4 ;msb was zero,skip next line
 INC FBVTotHi ;
DIDTAVG4
 DEC Temp2 ;dec loop counter
 JRZ DIDTAVG5 ;if zero,finish average
 JP DIDTAVG6 ;not zero,shift again
DIDTAVG5
 LD A,FBVTotHi ;store average in FreshBV
 LD FreshBV,A
 CLR FBVTotHi
 CLR FBVTotLo
 JRS 7,FreshBV,DA7 ;skip ahead if>8.5V
 RES Hi6V,Flags4 ;clear Hi6V flag
 JP DIDTAVGX ;and skip to end of routine
DA7
 SET Hi6V,Flags4 ;set Hi6V flag
 DIDTAVGX
 JP MAIN
;***************************************************************************
;*This is where the sequence states are defined.The number of a given   *
;*sequence state has no relevance to the order in which it is actually *
;*executed.Any given state can give control to any other state.     *
;***************************************************************************
;***************************************************************************
;*                   BATTERY DETECT                          *
;*This is the charger idle state.The program remains here until a battery *
;*is detected.Dectection is determined by finding a positive voltage  *
;*greater than one volt.                              *
;***************************************************************************
SS0
 RES Crank,Flags  ;clear Crank bit of Flags
 CALL ShowRate  ;turn on charge rate LED(Slow or Fast)
 CALL ShowType  ;turn on battery type LED(Reg,D/C or Gel)
 CALL ShutOff  ;open relay and set to HiOFF
 LDI OFFSET,OffSafe  ;set OFFSET to OffSafe
 RES SOC,SwDown  ;clear Start Of Charge flag
 JRS ChMode,Flags2,Ready  ;continue routine ifin Charger Mode
 CALL CheckBatt  ;...otherwise,check whether to show 0′s
 JP SS0EXIT  ;...and exit
Ready
 JRR Started,Flags,SS00 ;skip if output hasn′t been on
 RES Started,Flags  ;set Flags for charge not started
SS00
 LD A,FreshBV  ;check latest average voltage
 JRNZ SS0_1  ;Is it 0(exactly)?
 CALL ShowRed  ;turn on Red LED until battery is detected
 JP SS0EXIT  ;...Yes:must be rev.batt,so stop
SS0_1
 CALL IniTime1  ;set up timer
 LDI SECs1,002h  ;adjust for 2 seconds
 LDI Tries,005h  ;5 Tries for debounce
 SET 0,CurentSS  ;go on to BATTERY DETECT DELAY
SS0EXIT
 JP ExitMain
;***************************************************************************
;*BATTERY DETECT DELAY  *
;*This state checks that a voltage is present for three seconds.If the *
;*voltage drops below 1 Vdc,the timer is restarted and the ″try″counter *
;*is decremented.If after 5 Tries the voltage has not been above 1 Vdc*
;*for 3 seconds,go back to battery detect.This delay has the effect of *
;*debouncing the leads being connected to the battery.   *
;***************************************************************************
SS1
 CALL CheokBatt  ;check for connected battery
 JRR Batt,Flags2,SS1_2 ;subtract a try if not connected
;JRS Batt,Flags2,SS1_1 ;yes,check if it has been two seconds
;JP SS1_2  ;no,subtract a try
;SS1_1
 CALL ShowChgng  ;turn Charging LED on
 JRR 2,TicFlag1,SS1 EXIT ;go on if time is up,otherwise exit
 LDI OldVolt,000h ;clear OldVolt before entering SS2
 LDI TEMP1,000h ;clear Temp1 before entering SS2
;LDI IPSref,000h ;clear IPSref before entering SS2
 INC CurentSS  ;go on to start charge
 JP SS1_3  ;set timer for 2 seconds
 SS1_2  ;NOTE:Tries set to 5 in SS0
 DEC Tries  ;subtract a try
 JRNZ SS1_3  ;try again if not too many Tries
 DEC CurentSS  ;...otherwise,go back to idle(state 0)
 JP SS1EXIT  ;...and exit routine
SS1_3
 CALL IniTirne1  ;reset timer and try again
 LDI SECs1,002h ;adjust for 2 seconds
SS1EXIT
 JP ExitMain
;***************************************************************************
;*  AUTOMATIC CHARGE START   *
;*This state gets the battery voltage and decides how to continue the *
;*the charge.The maximum allowed charge time is also started.*
;***************************************************************************
SS2
;NOTES:OldVolt SET TO 0 IN SS1
; IPSref SET TO 0 IN SS1
;TEMP1 SET TO 0 AT RESET
FASTAVG
 DEC TEMP1  ;decrease Temp1 one count(starts at 0)
   ;have we counted down to 0?
 JRZ FASTDONE  ;yes,jump to FASTDONE
 LD A,TEMP  ;load previous TEMP value
 ADD A,CurVolt  ;add CURVOLT,Did we overflow the counter?
 JRNC OVER  ;no,jump to OVER
 INC OldVolt ;yes,bump up the running average
OVER
 LD TEMP,A  ;store the latest value in TEMP
 JP SS2EXIT  ;exit and go update CurVolt
FASTDONE
 LD A,TEMP  ;load previous TEMP value
 ADD A,CurVolt  ;Did we overflow the counter one last time?
 JRNC OVER2  ;no,jump to OVER2
 INC OldVolt  ;yes,bump up the running average one last time
OVER2
 CALL CheckBatt  ;Check to see if battery was removed during FastAvg
 JRS Batt,Flags2,SS2_0b ;Still connected-continue
 LDI CurentSS,0  ;not connected-go back to state 0
 JP SS2EXIT  ;...and exit State 2
SS2_0b
 LD A,OldVolt  ;get OldVolt(initial battery voltage)
 LD BADhi,A  ;initialize BADhi to OldVolt
;LD A,Percent  ;get updated %
 LD A,DspPcnt  ;compare to last % displayed
 JRNZ SS2_GP  ;if % previously shown,skip ahead
 CALL GetPercent  ;update Percent for initial voltage
 LD A,Percent  ;get latest %
 LD DspPcnt,A  ;store latest % in Display Percent
 RES Wait0P,Flags2  ;set flag to indicate not waiting
 JP SS2 BP  ;skip ahead
SS2_GP
 CPI A,100  ;check for 100%
 JRNZ SS2_BP  ;continue State 2 if not 100%
 JP SS5 Maint  ;...otherwise,go to Maintain
SS2_BP
 LDI CCDcnt,MaxHrs ;set interval counter to MaxHrs
 SET SOC,SwDown ;set Start Of Charge flag
 RES HiPwr,Flags4 ;clear high power flag
 JRS Rate,Flags,SS2Fast ;skip ahead if not set for Slow
   ;...otherwise,set for Slow charge rate
 LDI OFFSET,OffSlow ;set Offset for 2A
 JRR Bat6V,Flags2,SS2Slo ;skip ifnot set for 6V mode
 LDI OFFSET,Off6Slo ;...otherwise,adjust OFFSET
SS2Slo
 JP SS2_0a  ;skip ahead and read voltage
 SS2Fast  ;set for Fast charge rate
 CALL SetFast  ;set to ramp from OffSafe to OffFast
 JRR Bat6V,Flags2,SS2Fst ;skip if not set for 6V mode
 LDI VRcnt,OffSafe-Off6Fst ;...otherwise,adjust OFFSET ramp
SS2Fst
 JRR Rapid,Flags2,SS2_0a ;don′t set to ramp up if not Rapid rate
;JRS Rapid,Flags2,SS2Rap ;skip ahead if rate is Rapid
;JP SS2_0a  ;skip ahead and read voltage
;SS2Rap  ;set for Rapid charge rate
 CALL SetRmpUp  ;prepare to ramp from Fast to Rapid
SS2_0a
 CALL ShowChgng  ;turn Charging LED on
 CALL ChrgTmr  ;initialize charging timer(Timer 2)
 SET IPSlo,Flags4  ;initialize flag for checking IPS
 LDI IPSref,000h  ;clear IPSref before entering SS7
 LDI TEMP1,0FFh  ;initialize TEMP1 for State 7
 LDI CurentSS,7  ;prepare to go to the IPS wait state(7)
 JP ExitMain  ;exit and go to IPSwait state
SS2IPS
 CALL AdjVolt  ;adjust voltage for cable drop(& 6V scale)
 CPI A,Volts09  ;very low battery?
 JRNC SS2_2  ;no,try next limit
SS2_1  ;Battery<9V
 LDI A,003h  ;yes,service it,below 9 VOLT SS
 INC MINs2  ;allow 6 mins instead of 5 for state 3
 INC MINs2  ;allow 7 mins instead of 6 for state 3
 JP SS2_5
SS2_2  ;Battery>9V
 CPI A,Volts12  ;low battery state?
 JRNC SS2_4  ;no,goto SS5
SS2_3;9V<Battery<12V
 LDI A,004h  ;yes,service it,below 12 VOLT SS
 JP SS2_5
SS2_4  ;Battery>12V
;JRS Alert,Flags2,SS2EXIT;don′t start charge if Alert set by Double6V
 LDI A,005h  ;normal charge SS
SS2_5
 LD CurentSS,A  ;prepare to go to the correct state(3,4 or 5)
 SET Started,Flags ;set Flags for charge started
 CALL IniTime1  ;initialize timer 1
 LDIMINs1,1  ;set timer 1 for 1 minute
 LDI SECs1,005h  ;set timer 1 for 5 seconds
 SET RlyCls,Flags4  ;close output relay
 JRR Rate,Flags,SS2_6 ;skip ahead if set for Slow rate
 CALL FstRmp  ;ramp from OffSafe to OffFast or Off6Fst
SS2_6
 RES MinOut,Flags4  ;set for>minimum output
 RES VRlmt,Flags4  ;set for not at VoltReg limit
; NOTE:relay already closed,but TurnON saves code space
 CALL TurnON  ;turn Fan and Charging LED on & close relay
 SET Settle,Flags3  ;initial charge voltage settle mode
SS2EXIT
 JP ExitMain
;***************************************************************************
;*             BELOW 9 Volts    *
;*  Battery is extremely discharged and may be bad.Charge for a maximum *
;*of seven minutes.If voltage does not come above 9 Volts in this time *
;*period,abort charge.Otherwise,go to below 12 Volts.    *
;***************************************************************************
SS3
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS3EXIT;exit if voltage settle time not expired
;JRS SEC,TicFlag2,SS3_0;continue if voltage settle time expired
;JP SS3EXIT  ;...otherwise,just exit
;SS3_0
 RES Settle,Flags3  ;clear settle flag
 JRR MIN,TicFlag2,SS3_1 ;check if time has expired
 CALL SetAbort  ;yes,time to abort
 JP SS3EXIT
 SS3_1  ;not 7 mins yet
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts09  ;is battery up to 9V?
 JRC SS3EXIT           ;continue state 3 if<9V
 INC CurentSS  ;...otherwise,go to state 4
SS3EXIT
 JP ExitMain
;***************************************************************************
;*                  BELOW 12 Volts                    *
;*  Battery is very low.Allow a maximum of 4 hours for the voltage to  *
;*rise above 12 volts under charge.If voltage does not come up,go to *
;*abort charge.Otherwise go to normal charge.                   *
;***************************************************************************
SS4
 CALL TurnON  ;turn Fan and Charging LED on & close relay
 CALL ChkRapid  ;update Rarmp timer,if necessary
 JRR SEC,TicFlag2,SS4EXIT;exit if voltage settle time not expired
;JRS SEC,TicFlag2,SS4_0 ;continue if voltage settle time expired
;JP SS4EXIT  ;...otherwise,just exit
;SS4_0
 RES Settle,Flags3 ;...otherwise,clear settle flag
 JRR HR,TicFlag2,SS4_1 ;check if time(4 hours)has expired
 CALL SetAbort  ;yes,time to abort
 JP SS4EXIT  ;exit routine
SS4_1
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts12  ;is battery up to 12V?
 JRC SS4EXIT           ;...if not,just exit
 INC CurentSS  ;...otherwise,go to state 5
SS4EXIT
 JP ExitMain
;***************************************************************************
;*  NORMAL CHARGE    *
;*Program stays here until the voltage reaches 14.2 volts or the maximum *
;*charge time is exceded.If the voltage limit is reached the program *
;*will transfer to:      *
;*A.SSB(dV/dt)if the the battery has been charging more than 5  *
;*  minutes or      *
;*B.SS9(Desulfation)if the OCV was less than 12.2 volts or *
;*C.SS14(Maintain)if the OCV was more than 12.2 volts  *
;*      *
;*If the maximum charge time is exceded the program will abort *
;*         *
;***************************************************************************
SS5
 CALL TurnON   ;turn Fan and Charging LED on & close relay
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS5EXIT;exit if voltage settle time not expired
;JRS SEC,TicFlag2,SS5_0 ;continue if voltage settle time expired
;JP SS5EXIT  ;...otherwise,just exit
;SS5_0
 RES Settle,Flags3 ;...otherwise,clear settle flag
 CALL BattProg ;check battery voltage for charge progress
 JRR HR,TicFlag1,SS5_0a ;skip next line if max time not expired
;NOTE:CurentSS set to ABORT by BattProg.ChkProg
SS5x
 JP SS5EXIT  ;exit(and abort)if max time expired
SS5_0a
 JRS Rate,Flags,SS5_0b ;change delta if slow rate
 CPI A,Volts142+1  ;check if over 14.2 volts yet
 JP SS5_1
SS5_0b
 CPI A,Volts142+3  ;check if over 14.2 volts yet
SS5_1
 JRC SS5x  ;exit if not over 14.2 volts
;JRNC SS5_2  ;yes,check if>5 minutes
;JP SS5EXIT  ;otherwise,just return
;SS5_2
;**BP**
 LD A,CCDcnt  ;get CCDcnt(set by BattPRog w/minutes)
 LD HRs1,A  ;set Timer1 hours to CCDcnt
 RES HiPwr,Flags4  ;set for low power mode
 RES Rmpng,Flags3  ;clear flag before moving on
 RES RmpInt,Flags3  ;clear flag before moving on
;RES Settle,Flags3  ;clear flag before moving on
 JRS MIN,TicFlag2,SS5_3 ;if>5 min,go to dV/dt
 LD A,OldVolt  ;otherwise,check initial voltage
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,Volts122 ;initial voltage<12.2V?
 JRC SS5_5  ;Yes:then desulfate
 JP SS5_Maint  ;No:goto Maintain
SS5_5
 LDI CurentSS,009h  ;battery is sulfated
 LDI MaintVolt,Volts16 ;try to hold battery at 16V
 LDI Vref,Volts15 ;and see if it drops to 15V
 CALL IniTime2  ;
 LDI HRs2,002h  ;in less than 2 hours
 JP SS5EXIT  ;
SS5_3
 LD A,OFFSET  ;get OFFSET
 LD OldOff,A  ;store OFFSET into OldOff
 LDI CurentSS,00Bh  ;goto wait for dv/dt trip voltage
 LDI Percent,77  ;set Percent to 77
 CALL IniTime2
 LDI MINs2,0Dh  ;set to 13 minutes for dV/dt
 LD A,BADhi  ;get latest battery voltage
 SUBI A,4  ;prevent match @ 1st dV/dt check
 LD MaintVolt,A  ;store as maintain voltage for di/dt
 LDI Tries,004h  ;initialize dV/dt for 4 Tries(3 intervals)
 JP SS5EXIT  ;
SS5_Maint  ;goto MAINTAIN,battery is already charged???
 CALL Set100p  ;set Percent to 100
 LDI MaintVolt,Volts 132 ;set maintain voltage to 13.2V
;CALL FanOff ;turn cooling fan off
 JRR BatTypeB,Flags,SS5_7 ;skip ahead if not Gel/AGM
 LDI MaintVolt,Volts 135 ;set maintain voltage to 13.5V for Gel & AGM
SS5_7
 LDI CurentSS,00Eh ;Maintain is state 14(0E hex)
 CALL SetSlow  ;set for Slow Rate
 LDI OFFSET,HiOff-1 ;MAX offset value->min duty cycle
 CALL IniTime1  ;start relay control timer
 LDI SECs1,255  ;set for 255 seconds
 SET RlySw,Flags4 ;set recent change flag
;LDI SECs1,1  ;set for 1 second
;LDI MSECs1,2  ;set for 2 NMI interupts
SS5EXIT
 JP ExitMain
SS6
;***************************************************************************
;*       SS7-WAIT FOR INTERNAL POWER SUPPLY *
;*       *
;*In State 7,the charger leaves the output off and turns the fan on.*
;*If the internal power supply voltage is not high enough after 5*
;*minutes,the charger will proceed to the end of State 2.    *
;*        *
;***************************************************************************
SS7
 CALL FanON  ;turn cooling fan on
 JRR MIN,TicFlag2,SS7_1 ;skip ahead if 5 minute period has not expired
 RES IPSlo,Flags4  ;clear flag
 JRS Crank,Flags,SS7_5 ;set OFFSET to OffSafer if Crank
 JRS Rate,Flags,SS7_4 ;set OFFSET to OffSafer if not Slow
 CALL SetSafe  ;set OFFSET for OffSafe(~5A)when relay closes
SS7_0
;LDI CurentSS,2  ;prepare to return to State 2
  CALL ChrgTmr  ;initialize charging timer(Timer 2)
  JP SS2IPS  ;begin charging
SS7_4
 LDI OFFSET,OffSafer ;set Offset for~10A
 LDI VRcnt,OffSafer-OffFast ;adjust OFFSET ramp
 JP SS7_0
SS7_5
 LDI OFFSET,OffSafer ;set Offset for~10A
 LDI VRcnt,OffSafer-OffCrank ;adjust OFFSET ramp
 JP SS16_3  ;return to state 16
SS7_1
;CALL ShowRed ;**DEBUG**
 JRS Bat6V,Flags2,SS7_6 ;don′t check IPS in 6V mode
 DEC TEMP1  ;update counter
 JRZ SS7_2  ;skip ahead if zero(time to check)
 CALL ReadIPS  ;get IPS voltage
;CALL CheckIPS  ;check for minimum
 LD A,CurIPS  ;store latest reading in A
 CPI A,MinIPS  ;compare with minimum
 JRC SS7_7  ;skip ahead if too low
 INC IPSref  ;...otherwise,increment IPSref
SS7_7
 JP SS7_x  ;exit and wait for next reading
SS7_2
 LD A,IPSref  ;check″average″of readings
 CPI A,250  ;okay of 250/255 were high enough
 JRC SS7_3  ;if nothigh enough,clear and start new avg
SS7_6
 RES IPSlo,Flags4  ;...otherwise,clear flag
 JRR Crank,Flags,SS7_0 ;return to state 2 if not crank
 JP SS16_2  ;...otherwise,return to state 16
SS7_3
 CLR IPSref  ;clear IPSref
 LDI TEMP1,0FFh ;initialize TEMP1 for next″average″
SS7_x
 JP ExitMain
;***************************************************************************
;*         SS8-ABORT CHARGE     *
;*         *
;*Turn off all LED′s. Blink TROUBLE LED at half second interval.If *
;*battery becomes disconnected,re-initialize.    *
;*         *
;***************************************************************************
SS8
 SET Alert,Flags2  ;set Alert flag
 CALL ShutOff  ;open relay,turn off fan,and set to HiOFF
 CALL Blink Alert  ;blink Alert LED
 CALL ModeOff ;Turn off display mode LEDs
 JRS BurnIn,Flags3,SS8X ;don′t check for battery if Burn-In
 JRS SOC,SwDown,SS8X ;don′t check for battery if Start Of Charge
 CALL CheckBatt  ;check for connected battery
 JRS Batt,Flags2,SS8X
;JRR Batt,Flags2,SS8_1 ;if disconnected,end abort routine
;SS8_2
;JP SS8EXIT  ;otherwise,just exit
SS8_1
 RES Alert,Flags2  ;reset Alert flag
SS8rst
 JP MAIN2  ;re-initialize
SS8X
;SS8EXIT
 JP ExitMain
;***************************************************************************
;*             SS9-DESULFATION   *
;*Desulfation Mode is entered if the initial battery voltage is less *
;*than 12.2 volts and the voltage reaches 14.0 volts within five *
;*minutes.        *
;*          *
;*The charger tries to hold the voltage at 16.0 volts.As the battery *
;*starts to conduct,the voltage will fall.If the voltage reaches 14.0*
;*in a reasonable time limit(10 hours),we will transition to the *
;*normal charging sequence(SS5).If the voltage doesn′t fall to 14.0*
;*volts we will transition to the ABORT sequence state(SS8).*
;*******************************************************************************
SS9
 LDI Percent,15  ;set to 15%
 CALL BlnkChrg  ;blink Charging LED
 CALL CheckBatt ;check for connected battery
 JRR Batt,Flags2,SS8rst ;re-initialize if not connected
;JRS Batt,Flags2,SS9_0;continue routine if connected
;JP MAIN2 ;...otherwise,re-initialize
;SS9_0
 CALL VoltReg  ;try to hold batt at 16(or 8)volts
;**BP**
 LD A,OFFSET  ;check output level
 CPI A,OffSlow  ;is output>slow rate?
 JRNC SS9_5  ;...no:use output set by VoltReg
 LDI OFFSET,OffSlow  ;...yes:limit output to Slow rate
SS9_5
 JRR SEC,TicFlag2,SS9X ;wait 1 minute
 JRR HR,TicFlag2,SS9_1;maximum time out?(1 or 2 hours)
 DEC CurentSS  ;ABORT state
SS9exit
 JP SS9X  ;done
SS9_1
 CALL AdjVolt  ;adjust voltage for cable drop(& 6V scale)
 CPA,Vref  ;are we there?
 JRNC SS9exit  ;if not,then exit
;JRC SS9_2  ;yes:reduce Vref
;JP SS9X  ;no:wait another minute
;SS9_2
 DEC Vref  ;1 count is 0.0667 volts
 DEC Vref  ;reduce Vrefby 0.133 volts
 LD A,Vref  ;see if batt is desulfated yet
 CPI A,Volts14  ;is Vref<14.0 Volts?
;JRNC SS9_3
 JRC SS9_4  ;...if so,go to normal charge
 JP SS9_3  ;...otherwise,try another hour
SS9_4
 LDI CurentSS,005h  ;prepare to go to normal charge
;CALL ShowChgng  ;turn Charging LED on(stop blinking)
 LD A,Vmax  ;set MaintVolt to Vmax
 LD MaintVolt,A  ;maintain voltage for state 5
 SET RlyCls,Flags4  ;close output relay
 CALL IniTime2  ;initialize timer 2
 LDI SECs2,002h ;set timer for 2 seconds(voltage settle time)
 JP SS9X  ;
SS9_3
 CALL IniTime2  ;reset timer
 LDI HRs2,001h  ;set max time for 1 hour
SS9X
 JP ExitMain
SS10
;***************************************************************************
;*dV/dt MONITOR     *
;*  This state is looking for one of three conditions:  *
;*1.Maximum time is exceded-set for check battery and turn off charger.*
;*2.No change in dV/dt for 45 minutes-battery is about 80% charged.*
;*3.MAX voltage is reached-GOTO dI/dt.     *
;*      *
;***************************************************************************
SS11
 CALL SetON  ;turn cooling fan on & close output relay
;RES Rmpng,Flags3  ;clear flag before moving on
;RES Settle,Flags3  ;cIear flag before moving on
 JRR HR,TicFlag1,SS11_1 ;If not max time out,goro SS11_1
 CALL SetAbort  ;otherwise,go to abort
 JP SS11X
SS11_1
 CALL ShowChgng  ;light Charging LED
 CALL AdjVolt  ;adjust voltage for cable drop(& 6V scale)
 CP A,Vmax  ;is batt voltage<MAX voltage?
 JRC SS11_2  ;yes:continue loop
 SET RmpInt,Flags3  ;no:set to boost during D/C EndCharge
 JP SS11_6  ;  ...and prepare to GOTO dI/dt
SS11_2
 JRR MIN,TicFlag2,SS11X ;exit if not time for dy/dt test?
 LD A,Percent ;get Percent
 CPI A,84  ;is Percent<84?
 JRNC SS11_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_3
 LD A,BADhi  ;get battery voltage
 DEC A  ;limit for 6V batteries is 1 count
 JRS Bat6V,Flags2,SS11_3a;leave limit at 1 for 6V batteries
DEC A  ;limit for 12V batteries is 2 counts
SS11_3a
 CP A,MaintVolt ;test for upper limit change
 JRC SS11_4  ;delta less than limit,dec Tries
 JP SS11_7  ;otherwise,skip ahead & update MaintVolt
SS11_4
 .IFC EQ ShoReg  ;assemble next line only if debugging
 CALL ShowGreen  ;turn on Green LED
 .ENDC
 DEC Tries  ;decrement counter
 JRZ SS11_6  ;all done,GOTO dI/dt
 LD A,Percent  ;get Percent
 CPI A,87  ;is Percent<88?
 JRNC SS11_5  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_5
 JP SS11_8  ;no,reload timer
SS11_6
 INC CurentSS  ;GOTO dI/dt next
 LDI Percent,88  ;set percent to 88-NOTE must always be even
 JRS RmpInt,Flags3,MntMx ;skip ahead if Vmax reached
 CALL AdjVolt  ;adjust voltage for cable drop(& 6V scale)
 LD MaintVolt,A  ;save BADhi as maintain voltage
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
MntMx
 LD A,Vmax  ;otherwise,set MaintVolt to Vmax
 LD MaintVolt,A  ;MaintVolt used for di/dt
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
SS11_7  ;update MaintVolt
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowRed  ;turn on Red LED
 .ENDC
 LD A,BADhi  ;get current battery voltage
 LD MaintVolt,A  ;update MaintVolt for dV/dt & di/dt
SS11_9
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS11_8
 CALL IniTime2  ;initialize timer
 LDI MINs2,009h ;...for 9 minutes
SS11X
 JP ExitMain
;***************************************************************************
;*    di/dt MONITOR    *
;*In di/dt the on/off relay is opened and closed to hold the voltage *
;*close to the dV/dt value.The interval between opening and closing the *
;*relay will increase.This state is looking for one of two conditions:*
;*1.Maximum time is exceded-set for check battery and turn off charger.*
;*2.No change in on/off relay for 30 minutes-current stabilized at a *
;*low value.Battery is about 97% charged.Goto SS13(EndCharge)for *
;*1 hour.       *
;***************************************************************************
SS12
;CALL SetON  ;turn cooling fan on & close output relay
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS12_14  ;...if so,turn on green LED
 CALL ShowYellow  ;...otherwise,turn on yellow LED
 JP SS12_15  ;...and skip ahead(leave green off)
SS12_14
 CALL ShowDone  ;turn on charge complete LED
SS12_15
 JRR HR,TicFlag1,SS12_1 ;maximum time out?
 JRS Alert,Flags2,SS12_0 ;If 2nd max time out,goto SS12_0
 SET Alert,Flags2  ;If 1st max time,set Alert flag
 CALL IniTime1   ;and reset timer
 LDI HRs1,004h  ;to alow 4 more hours
SS12_10
 LD A,MaintVolt  ;and get Maintain voltage
 SUBI A,007h   ;then subtract~0.5V
 LD MaintVolt,A  ;and update Maintain voltage
 JP SS12EXIT  ;then restart di/dt
SS12_0
 CALL SetAbort  ;go to abort
 RES Alert,Flags2  ;reset Alert flag for Abort timer
 JP SS12EXIT
SS12_1
 JRS MinOut,Flags4,SS12_2 ;don′t wait if at minimum output
 JRR Min,TicFlag2,SS12EXIT ;time for dI/dt test?
 .IFCC EQ ShoReg ;assemble next line only if debugging
 CALL ShowAlt  ;turn on alternator % LED
 .ENDC
 LD A,Percent  ;get Percent
 CPI A,100  ;is Percent<100?
 JRNC SS12_2  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 LD A,Percent  ;get percent
 CPI A,100  ;Is percent =100?
 JRZ SS12_2  ;YES,don′t increase anymore
 INC Percent  ;No,increase by 2
SS12_2
 LD A,OFFSET  ;get current OFFSET
;INCA
 CPI A,HiOff-1 ;has OFFSET reached maximum?
 JRNC SS12_5  ;if so,finish di/dt
 DEC A  ;ensure carry if equal
;DEC A  ;allow difference of 1
 CPA,OldOff  ;test for lower limit change
 JRC SS12_4  ;offset within 1,finish di/dt
 JP SS12_7  ;offset too high,try again
SS12_5
 JP SS12_6
SS12_4
 DEC Tries  ;decrement counter
 JRZ SS12_5  ;if0,then prepare for EndCharge(SS13)
;JRNZ SS12_5  ;Are we done?
;JP SS12_6  ;yes,all done,cleanup and exit
;SS12_5  ;no,continue
 LD A,Percent  ;get Percent
 CPI A,99  ;is Percent<100
 JRNC SS12_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 JP SS12_8  ;reload timer & check again later
SS12_3
 LD A,Tries  ;get the current tries
 CPI A,03  ;Is tries less than 3?
 JR NC SS12_11  ;No,just exit
 CALL Set100p  ;Yes,show 100% and done
SS12_11
 JP SS12_8  ;reload timer & check again later
SS12_6
 INC CurentSS  ;GOTO EndCharge(SS13)
 CALL IniTime2  ;initialize timer
 LDI HRs2,001h  ;charge for 1 more hour(EndCharge)
 LDI MINs2,00Fh  ;charge for only 15 minutes(EndCharge)
 JRR BatTypeA,Flags,SS12_9 ;skip if not Deep Cycle(Voyager)
 JRR RmpInt,Flags3,SS12_9 ;skip if not using higher EndCharge voltage
 INC HRs2  ;otherwise,change HRS2 from 1 to 2
 LD A,MaintVolt  ;also,store MaintVolt in A
 ADDI A,04h  ;increase A by 4 counts~0.267V
 LD MaintVolt,A  ;store updated value in MaintVolt
SS12_9
 JP SS12EXIT
SS12_7
 LD A,OFFSET  ;set new base offset
 LD OldOff,A  ;save in OldOff
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS12_8
 CALL IniTime2  ;initialize Timer 2
 LDI MINs2,009h  ;set Timer 2 for 9 minutes
 LD A,OFFSET  ;Get current offset
 CPI A,OffFast  ;Is the offset=OffFast?
 JRNZ SS12EXIT  ;NO,just exit
 RES RmpInt,Flags3 ;YES,don′t boost voltage for EndCharge
 JP SS12_10  ;Current not falling,reduce voltage by 1/2V
SS122EXIT
 JP ExitMain
;***************************************************************************
;*       ENDCHARGE   *
;*Charge for desired hours after dI/dt at dV/dt voltage.*
;***************************************************************************
SS13
 CALL Set100p  ;set Percent to 100
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRNZ SS13_2  ;...if so,turn on green LED
 CALL ShowDone  ;turn on charge complete LED
SS13_2
;CALL SetON  ;turn cooling fan on & close output relay
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 JRS VRlmt,Flags4,SS13_1  ;finish not if VoltReg limit reached
;JRR VRlmt,Flags4,SS13_0 ;continue if VoltReg limit not reached
;JP SS5_Maint  ;...otherwise,finish now
;SS13_0
 JRR HR,TicFlag2,SS13EXIT ;exit if 1 hour time not up
SS13_1
 JP SS5_Maint  ;...otherwise,GOTO MAINTAIN
SS13EXIT
JP ExitMain
;***************************************************************************
;*     MAINTAIN    *
;*Battery has reached full charge.Stay here and maintain battery *
;*at 13.2 volts until battery is disconnected.  *
;*        *
;***************************************************************************
SS14
 CALL Set100p  ;set Percent to 100
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZSS14_1  ;...if so,turn on green LED
 CALL ShowYellow  ;...otherwise,turn on yellow LFD
 JP SS14_2  ;...and skip ahead(leave green off)
SS14_1
 CALL ShowDone  ;turn on charge complete LED
SS14_2
 LD A,OFFSET  ;Check whether to open or close relay
 CPI A,HiOff ;Is it minimum(nearly off)?
 JRC SS14_2A  ;...if not,close relay and turn on fan
 JP SS14_3  ;...and open relay
 SS14_2A  ;close relay
 CALL FanON  ;...otherwise,close relay & turn fan on
 .IFC EQ DEBUG ;assemble next line oniy if debugging
 CALL ShowRed  ;turn on Red LED
 .ENDC
 SET Relay,Flags2  ;prepare to close output relay
 JRS RlyCls,Flags4,SS14_4;skip ahead of already closed
 JRR RlySw,Flags4,SS14_5 ;check if too soon to switch
 JRR SEC,TicFlag1,SS14_4 ;skip ahead if too soon to switch
 SET RlyCls,Flags4 ;set to indicate relay now closed
 LDI OFFSET,HiOff-1 ;set for minimum duty cycle
 JP SS14_3a ;and skip ahead
SS14_3  ;open relay
 RES Relay,Flags2  ;...otherwise,open output relay
 JRR RlyCls,Flags4,SS14_4;skip ahead if relay already open
 JRR RlySw,Flags4,SS14_5 ;check if too soon to switch
 JRR SEC,TicFlag1,SS14_4 ;skip ahead if too soon to switch
 CALL ShutOff ;open relay,turn off fan,and set to HiOFF
SS14_3a
 RES RlySw,Flags4 ;allow IT_Timer & PwrCon to switch relay
SS14_4
 CALL CheckBatt  ;check for battery
 JRS Batt,Flags2,SS14EXIT;...connected:continue
 JP MAIN2  ;...disconnected:start over from state 0
SS14_5
 CALL IniTime1  ;start relay interval timer
 LDI SECs1,RlyInt ;set timer to RlyInt secs
 SET RlySw,Flags4 ;set recent change flag
SS14EXIT
 JP ExitMain
;***************************************************************************
;*   SS15MANUAL    *
;*Set offset for selected rate.No voltage limit/battery check.  *
;***************************************************************************
SS15
 JRR RlyCls,Flags4,SS15_2;if relay open,then Burn-In complete
;JRS RlyCls,Flags4,SS15_0;open relay indicates completed Burn-In
;JP SS15_2  ;skip to end if relayis open
;SS15_0
 CALL ShowRate  ;turn on the 2A,15A,or 40A LED
;NOTE:relay already closed,but TurnON saves code space
 CALL TurnON  ;turn Fan and Charging LED on & close relay
 CALL Check17v  ;check for disconnected battery
 JRNZ SS15OK  ;if<>17V,then continue
 CALL SetAbort  ;...otherwise,Abort
 RES Manual,Flags3 ;...end Manual Mode
 JP SS15EXIT  ;...and skip rest of State 15
SS15OK
 JRS BurnIn,Flags3,SS15BI;skip ahead ifBurn-in mode
 RES MtrScale,Flags ;set for Alternator % LED off
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
 CALL ShowMeter  ;update meter LEDs
 JP SS15rmp  ;jump to ramp check
SS15BI
 JRR MIN,TicFlag2,SS15b ;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 CALL IniTime2  ;reset Timer2
 LDI MINs2,1  ;set timer for counter interval(1 minute)
SS15b
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL ShowNum  ;display count on digital LED
 CALL ModeOff  ;turn off all display mode LED′s
SS15rmp
 CALL ShowData  ;update display
 JRR Rapid,Flags2,SS15_1 ;don′t ramp if Rapid is not set
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR Rmpng,Flags3,SS15_1;skip ahead if not Rapid<->Fast transition
 CALL RampOS  ;otherwise,gradually change duty cycle
SS15_1
 JRR HR,TicFlag1,SS15EXIT;continue if not max manual charge time
 JRS BurnIn,Flags3,SS15_2;skip ahead if finished Burn-In
 JP RESET  ;...otherwise,reset
SS15_2
 CALL DigitsOff  ;turn off3-digit LED
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL TurnOff  ;open relay and set for min duty cycle
SS15EXIT
 JP ExitMain
;***************************************************************************
;*   BOOST MODE   *
;* First set the charger offset value for Slow charging.Next,wait *
;* for the voltage to stabilize.Then wait for the voltage to drop *
;* about one volt.When the voltage drops,go full on for 5 seconds.*
;* After five seconds of cranking,wait for 4 minutes and start over.*
;*          *
;****************************************************************************
SS16
 CALL VoltMtr  ;set for volt meter and update display
 CALL CheckBatt  ;check for disconnected battery
 JRR Batt,Flags2,SS16_1 ;skip ahead if not connected
 JRS SEC,TicFlag2,BattOK ;skip if>2 seconds since Boost selected
 JP SS16Exit  ;if<2 seconds,then stay off
SS16_1
 CALL TurnOff  ;open relay and set for min duty cycle
 LDI OFFSET,OffSafe ;set OFFSET to OffSafe
 CALL ShowRed  ;...otherwise,turn on Alert LED
 JP SS16Exit  ;if batt<1.6V,then stay off
BattOK
 CALL ShowCrank  ;turn ON Crank LED & turn Alert LED off
 JRS RlyCls,Flags4,SS16_3;skip ahead if relay already closed
 JP SS2_0a  ;...otherwise,prepare to check IPS(SS7)
SS16_2
 CALL SetSafe  ;set OFFSET for OffSafe(~SA)when relay closes
 LDI VRcnt,OffSafe-OffCrank ;OFFSET delta from Safe to Crank
SS16_3
 CALL TurnON  ;turn Fan and Charging LED on & close relay
 SET Started,Flags  ;set Flags for charge started
 CALL IniTime2  ;reset timer 2
 LDI MSECs2,MS200 ;set Timer2 for 200ms
 LDI CurentSS,17 ;set to next state(17)
SS16Exit
 JP ExitMain  ;goto end of loop
;***************************************************************************
;*   DELAY FOR VOLT READING   *
;***************************************************************************
SS17
 JPS MSEC,TicFlag2,SSt7_1 ;Is 200ms up?
 JP SS17EXIT  ;no,just return
SS17_1
 CALL GetMeter  ;update display
 CALL Check17v  ;check for disconnected battery
 JPC SS17_2  ;skip ahead if connected
 JPMAIN2  ;otherwise,start over
SS17_2
 SUBI A,010h  ;adjust for a one volt drop
 LD OldVolt,A  ;save it
 CALL FstRmp  ;rarnp output from 5A to 20A
 LDI MaintVolt,Volts142;try to hold battery at 14.2V
 INC CurentSS  ;wait for crank
 CALL IniTime2  ;intialize Timer 2
 LDI MINs2,10  ;set Timer 2 for 10 minutes
 LDI VRcnt,OffCrank-MinOff ;OFFSET delta from Safe to Crank
SS17EXIT
 JP ExirMain
;***************************************************************************
;*   WAIT FOR CRANK   *
;***************************************************************************
SS18
 JPS MIN,TicFlag2,SS18rst;re-initialize after 10 minutes
;JRR MIN,TicFlag2,SS18_0;wait for crank up to 10 minutes
;JP MAIN2;then start re-initialize
;SS18_0
 CALL FanON  ;turn cooling fan ON
 CALL GetMeter  ;update display
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,FreshBV  ;get current reading
 SUBI A,010h  ;adjust for a one volt drop
 CP A,OldVolt  ;has voltage increased?
 JPC SS18_2;if not,then skip ahead
 LD OldVolt,A ;updae OldVolt
 JP SS18_X  ;and exit routine
SS18_2
 LD A,FreshBV  ;get current reading
 CPA,OldVolt  ;1V drop indicates craking
 JPC SS18EXIT
 CALL FstRmp  ;ramp output from 20A to almost 100A
 INC CurentSS ;time the cranking
 CALL INiTime2  ;reset Timer2
 LDI SECs2,CrankON ;crank for CrankON(5)seconds
SS18EAIT
 CALL Check17v  ;check for disconnected battery
 JRC SS18_X  ;skip ahead if connected
SS18rst
 JP MAIN2  ;otherwise,start over from state 0
SS18_X
JP ExitMain
;***************************************************************************
;*   CRANK TIMING   *
;*Allow cranking for CrankON seconds and then go back to charging. *
;***************************************************************************
SS19
 LD A,SECs2;get remaining crank seconds
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off display mode LED′s
 JPS SEC,TicFlag2,SS19_1;if time is up,then end routine
 CALL Check17v ;check for disconnected battery
 JPNC SS19_1  ;stop cranking if not connected
 JP SS19EXIT  ;still connected,wait for crank timer
SS19_1
 INC CurentSS ;just wait for time to expire
 LDI OFFSET,OffCrank ;set Offset for 20A
 SET CrankWait,Flags ;indicates crank cool-down time
 CALL TurnON  ;turn Fan and Charging LED on & close relay
 CALL IniTime1  ;reset Tirner1
 LDI SECs1,CCDint ;set timer for counter interval(seconds)
 LDI CCDcnt,CrankOff;set crank cool down counter to 120
SS19EXIT
 JP ExitMain
;***************************************************************************
;*              INTER-CRANK DELAY                  *
;*Stay here until the 4 minute timer has expired then go back to BOOST *
;*if switch still engaged,else goto Slow auto(default)  *
;***************************************************************************
SS20
 CALL FanON  ;turn cooling fan ON
 JPR SEC,TicFlag1,SS20_0;skip ahead if not time to update counter
 DEC CCDcnt  ;decease display count by 1
 JPZ SS20_1  ;finish state 20 if count down to 0
 RES CrankWait,Flags ;reset CranWait bit of Flags
 LDI CurentSS,010h ;set state to 16 to Crank again
 SET SEC,TicFlag2 ;tell State 16 that E/S already running
 JP SS20EXIT  ;and exit State 20
SS20_1
 CALL IniTime1  ;reset Timer1
 LDI SECs1,CCDint ;set timer for counter interval(seconds)
SS20_0
 LD A,CCDcnt ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off display mode LED′s
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 RES Rmpng,Flags3 ;clear flag for CheckBatt
 RES Settle,Flags3 ;clear flag for CheckBatt
 CALL BlinkCrank  ;blink the Crank LED
SS20EXIT
 JP ExitMain
;***************************************************************************
;*   SUB ROUTINES START HERE   *
;***************************************************************************
;***************************************************************************
;* Initialize state(Slow charge,Regular batt,State 0)  *
;*          *
;***************************************************************************
InitState
 CLR Flags  ;0 is default for all bits
 CLR Flags2 ;0 is default for all bits
 CLR Flags3 ;set to indicate no Rapid to Fast change
 CLR TEMP1  ;initialize
 CLR CCDcnt ;initialize
 SET ChMode,Flags2 ;set for Charger Mode(charger mode)
 LDI OFFSET,HiOff  ;set for mimimum duty cycle
 LDI SwData,01101111b ;Initialize switch LEDs for 2A,Reg
 LDI Vmax,Volts155  ;Vmax for Regular batteries
 LDI VltCnt,001h ;initialize VltCnt to 1
 LDI VRcnt,001h ;initialize VRcnt to 1
 LDI PcntL,001h ;initialize PcntL to 1
 LDI PcntH,001h ;initialize PcntH to 1
 LDI CurentSS,000h  ;set charger state to 0
 LDI SECs1,SecInit ;restart TIMER1 second counter
 LDI SECs2,SecInit ;restart TIMER2 second counter
 RET
;***************************************************************************
;*   Reset Watchdog Register  *
;*This routine simiply resets the Watchdog register.RstWDR was  *
;*only to save program space(LDI require 3 bytes,CALL requires only 2).*
;*         *
;***************************************************************************
RstWDR
 LDI WDR,0FEh ;reset watch dog timer
 RET
;***************************************************************************
;*   Set Abort State   *
;*This routine simiply sets CurentSS to ABORT so that the code will go *
;*to the Abort state after the next NMI.SetAbort was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
SetAbort
 LDI CurentSS,ABORT ;set current state to Abort
 RET
;***************************************************************************
;*Set 100 Percent   *
;*This routine simiply sets Percent to 100.Set100p was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
Set100p
 LDI Percent,100;set Percent to 100
 RET
;***************************************************************************
;*   Clear Percent   *
;*This routine simiply sets Percent and DspPcnt to 0.ClrPcnt was  *
;*written only to save program space(CLR require 3 bytes,CALL requires *
;*only 2).Set0p is the second half of ClrPcnt.  *
;*        *
;*Set 0 Percent   *
;*This routine simiply sets Percent to 0.Set0p was written only to *
;*save program space(LDI require 3 bytes,CALL requies only 2). *
;*       *
;***************************************************************************
ClrPcnt
 CLR DspPcnt ;sat Display Percent to 0
Set0p
 LDI Percent,0 ;set Percent to 0
 RET
;***************************************************************************
;*    Update Port A   *
;*This routine updates Port A with the contents of the DRA buffer. *
;*UpdatePA was written only to save program space.  *
;*       *
;***************************************************************************
UpdatePA
 LD A,DRAbuf ;update Accumulator from buffer
 LD DRA,A  ;update port from Accumulator
 RET
;***************************************************************************
;*   Update Port B   *
;*This routine updates Port B with the contents of the DRB buffer.  *
;*UpdatePB was written only to save program space.  *
;*       *
;***************************************************************************
UpdatePB
 LD A,DRBbuf ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
 RET
;***************************************************************************
;*   Update Port B Options   *
;*This routine updates the Port B options with the contents of the ORB *
;*buffer. UpdateORB was written only to save program space.  *
;*        *
;***************************************************************************
UpdateORB
 LD A,ORBbuf ;update Accumulator from buffer
 LD ORB,A ;update options register from Accumulator
 RET
;**************************************************************************
;*   Set Fast    *
;*This routine sets OFFSET to OffSafe and sets VRcnt to ramp from *
;*OffSafe to OffFast.SetFast saves program space since LDI require 3*
;*bytes and CALL requires only 2.      *
;*         *
;*    Set Safe       *
;*This routine sirniply sets OFFSET to OffSafe and was written only to *
;*save program space(LDI require 3  bytes,CALL requires only 2). *
;*GetMeter is the last section of VoltMtr.  *
;*       *
;***************************************************************************
SetFast
 LDI VRcnt,OffSafe-OffFast ;ramp from OffSafe to OffFast
SetSafe
 LDI OFFSET,OffSafe  ;set OFFSET to OffSafe
 CALL FifthSecond  ;wait 1/5second before closing relay
 RET
;***************************************************************************
;*   Initialize Charge Timer  *
;*         *
;***************************************************************************
ChrgTmr
 CALL IniTime2  ;initialize timer 2
 LDI SECs2,002h ;set timer for 2 seconds
 LDI MINs2,006h ;set timer for 5 minutes and 2 seconds
 LDI HRs2,005h ;set timer for 4 hours,5 minutes & 2 seconds
 RET
;***************************************************************************
;*   Wait a Fifth Second   *
;*This routine causes the program to wait one fifth second by waiting *
;*for 24 interrupts.      *
;***************************************************************************
FifthSecond
 CALL IniTime1
 LDI MSECs1,MS100;set timer for 1/10 second
 WFS_1
 WAIT
 CALL RstWDR  ;reset watch dog timer
 JRR MSEC,TicFlag1,WFS_1;wait until timer goes to 0
 RET
;***************************************************************************
;*READ INTERNAL POWER SUPPLY VOLTAGE  *
;*This routine reads the current internal power supply voltage by *
;*temporarily changing the A/D from PB5to PB6.The reading is saved in *
;*IPSA2D.         *
;*       *
;*       *
;***************************************************************************
ReadIPS
;disable PB5 A/D connection
 RES 4,ADCR ;disable A/D convertor
 RES BattA2D,ORBbuf ;Set battery voltage to digital input in buffer
 CALL UpdateORB ;update Port B options from buffer
;establish PB6 A/D connection
 SET IPSA2D,ORBbuf ;Set int.PS voltage to analog input in buffer
 CALL UpdateORB ;update Port B options from buffer
 SET 4,ADCR ;A/D convertor now switched back ON
;activate A/D conversion
 LDI ADCR,0B0h ;start A/D conversion
 LDI ADCR,0B0h ;do again to insure a valid start
 WAIT  ;let the interupt notify us when data is ready
 LD CurIPS,A ;save current reading
 disable PB6 A/D connection
 RES 4,ADCR ;disable A/D convertor
 RES IPSA2D,ORBbuf ;Set int.PS voltage to digital input in buffer
 CALL UpdateORB ;update Port B options from buffer
;establish PB5 A/D connection
 SET BattA2D,ORBbuf ;Set battery voltage to analog input in buffer
 CALL UpdateORB ;update Port B options from buffer
 SET 4,ADCR ;A/D convertor now switched back ON
 RET
;***************************************************************************
;*  CHECK INTERNAL POWER SUPPLY VOLTAGE *
;*This compares the current internal power supply voltage to the minimum *
;*safe level.It sets the IPSlo flag accordingly and increments IPSref *
;*if the voltage is high enough.IPSref can be used to take several *
;*readings and discard a few to allow for bad readings without getting an *
;*actual average of the readings.     *
;*         *
;***************************************************************************
;CheckIPS
;LD A,CurIPS  ;store latest reading in A
;CPI A,MinIPS  ;compare with minimum
;JRC ChkIPSx  ;skip ahead if too low
;INC IPSref ;...otherwise,increment IPSref
;ChkIPSx
;RET
;***************************************************************************
;*    Fast Ramp    *
;*This routine is used to ramp the duty up from SafeOff to SafeOff-VRcnt.*
;*OFFSET is decreased by one with each NMI(120 per second).   *
;*      *
;***************************************************************************
FstRmp
 DEC OFFSET  ;increase duty cycle
 DEC VRcnt  ;update OFFSET change counter
 JRZ FstRrnpX  ;finish loop if counter=0
 LD A,CurentSS  ;check current State
 CPI A,18  ;is it State 18(ramping to full on)?
 JRNZ FstRmpES  ;skip ahead if not
 DEC OFFSET  ;...otherwise,increase duty cycle again
 DEC VRcnt  ;...and update counter again
 JRZ FstRmpX ;finish loop if counter=0
FstRmpES
 WAIT  ;...otherwise,wait for 1 interrupt
 JP FstRmp ;...and then change OFFSET again
FstRmpX
 LDI VRcnt,001h ;re-initialize VRcnt to 1
 RET
;***************************************************************************
;*   Set Ramp Up   *
;*This routine sets the parameters necessary to ramp the duty up from the *
;*fast rate to the rapid rate. It is used before Burn-In and Automatic *
;*Rapid charge.     *
;*        *
;***************************************************************************
SetRmpUp
 LDI RmpCnt,RCinitX2 ;200 0.75-second intervals yields 150 seconds
 SET RampUp,Flags3 ;set for ramp up
SetRamp
 LDI TEMP,RIinit ;180 NMI interrupts yields 1.5 seconds
 SET RmpInt,Flags3 ;counting 1st of two 180 cycle periods
 RES Rmpng,Flags3 ;set for not ramping yet
 RET
;***************************************************************************
;*   CHECK RAPID   *
;*This routine determines whether to reduce or increase the charge rate *
;*from Rapid to Fast or vica versa,if necessary. It sets the flags *
;*used by RampOS appropriately.          *
;*        *
;***************************************************************************
ChkRapid
 JRR Rapid,Flags2,ChkRapX ;if not Rapid charge rate,then exit
 JRS Rmpng,Flags3,ChkRapX ;if Rmpng already set,then exit
 DEC TEMP  ;otherwise,update ramp timer
 JRNZ ChekRapX  ;exit if not time to update count
;JRZ RmpTmr  ;update count if time
;JP ChkRapX  ;...otherwise,just exit
;RmpTmr
 LDI TEMP,RIinit ;count 180 more cycles(1.5sec)
 JRR RmpInt,Flags3,RmpCtr ;skip ahead if just counted 1st half
 RES RmpInt,Flags3  ;...otherwise,start counting 2nd half
ChekRapX
 JP ChkRapX  ;...and exit
RmpCtr
 SET RmpInt,Flags3 ;counting 1st of two 180 cycle periods
 .IFC EQ ShoReg ;assemble next line only if debugging
CALL ShowAlt  ;turn on alternator %LED
 .ENDC
 DEC RmpCnt  ;check if time to ramp
 JRNZ ChkRapX  ;exit if not time to ramp
;JRZ StartRamp  ;if so,start ramping
;JP ChkRapX  ;...otherwise,just exit
;StartRamp
 SET Rmpng,Flags3  ;set to indicate Rapid to Fast transition
 LDI RmpCnt,RCinit  ;100 3-second intervals yields 5 minutes
 JRS RampUp,Flags3,StRmpUp ;skip ahead if about to ramp up
 LDI RmpCnt,RCinitX2 ;...otherwise,double inter-ramp time
StRmpUp
 SET HiPwr,Flags4  ;set flags for>Fast rate
ChkRapX
 RET
;***************************************************************************
;*   RAMP OFFSET   *
;*This routine changes the charge rate between Fast and Rapipd gradually *
;*by changing OFFSET between OffFast and OffRap at a steady rate.OFFSET *
;*is raised by 1 every 4 seconds.That changes the current from 30A to 10A *
;*in about 4 minutes.       *
;*         *
;***************************************************************************
RampOS
 JRR Rapid,Flags2,RmpOffX;ifnot Rapid charge rate,then exit
 DEC TEMP  ;...otherwise,decrement counter
 JRZ RampTime  ;is counter down to zero?
 JP RmpOffX  ;if not,just exit
RampTime   ;...otherwise,time to adjust
 JRS RmpInt,Flags3,RampInt ;skip ahead if only halfway through wait
 LD A,OFFSET  ;get OFFSET
 JRS RampUp,Flags3,RmpUp ;skip ahead if decreasing OFFSET
 JRR Bat6V,Flags2,RmpDwn6;skip ahead ifnot set for 6V
 CPI A,Off6Fst  ;...otherwise,check for Off6Fst
 JP RmpDwn12  ;...and skip ahead
RmpDwn6
 CPI A,OffFast  ;is OFFSET =OffFast yet?
RmpDwn12
 JRNZ RampMore  ;ifnot,skip ahead and continue ramping
 RES Rmpng,Flags3  ;ramping complete,clear flag
 RES HiPwr,Flags4 ;set for not HiPwr
 SET RampUp,Flags3 ;set to ramp up next time
 JP RmpOffX  ;skip to end of routine
RampMore
 INC OFFSET  ;...otherwise,reduce duty cycle
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowRed  ;turn on Red LED
 .ENDC
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 JP RmpOffI  ;skip ahead and re-initialize counter
RmpUp
 JRR Bat6V,Flags2,RmpUp6 ;skip ahead if not set for 6V
 CPI A,Off6Rap  ;...otherwise,check for Off6Rap
 JP RmpUp12  ;...and skip ahead
RmpUp6
 CPI A,OffRap  ;is it OffRap Yet?
RmpUp12
 JRNZ RmpAgain  ;if not,skip ahead and continue ramping
RmpDone
 RES Rmpng,Flags3 ;ramping complete,clear flag
 RES RampUp,Flags3 ;set to ramp down next time
 JP RmpOffX  ;skip to end of routine
RmpAgain
 DEC OFFSET  ;...otherwise,reduce duty cycle
 .IFC EQ ShoReg ;assemble next line only if debugging
 CALL ShowGreen  ;turn on Green LED
 .ENDC
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 JP RmpOfff  ;skip ahead and re-initialize counter
RampInt
 RES RmpInt,Flags3  ;counting last two 180 cycles of interval
RmpOffI
 LDI TEMP,RIinit ;set counter for 180 cycles(1.5 more sec)
RmpOffX
 RET
;***************************************************************************
;*   SHOW NUMBER   *
;*This routine determines what three digits to display on the digital LED *
;*to represent the number stored in LEDNum. The three digits will be *
;*displayed next time the ShowData routine is called.  *
;*         *
;***************************************************************************
ShowNum
 CLR Index  ;initialize LUT Index to 0
 CALL DigiOff ;set registers for all segments off
 LD A,LEDnum ;store LEDnum in accumulator
 CPI A,10  ;check for single digit number
 JRNC ChkMaxNum  ;...if not,check for max number
 JP Next001  ;...otherwise skip to 3rd digit
ChkMaxNum
 CPI A,199 ;check for highest displayable number
 JRC Check100  ;if less,check value
 LDI A,199  ;...otherwise,displaly 199
Check100
 CPI A,100  ;check whehter to show most significant 1
 JRC Check010  ;if not,check for 10
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,100  ;...and subtract 100 from accumulator
Check010
 CPIA,10  ;check if<10
 JRC Check001  ;...if so,skip ahead and check 3rd digit
 INC Index ;...otherwise,show next higher value
 SUBI A,10 ;...and subtract 10 from Acumulator
 JP Check010 ;...and check for next higher value
Check001
 LDI DRWR,Digits0x0.w ;look up table (LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD ATemp,A ;save Accumulator
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 AND A,DigiDat2 ;...set bits in A for second digit
 LD DigiDat2,A ;...store A into DigiDat2
 LD A,ATemp ;restore Accumulator to remainder of LEDnum
Next001
 LDI DRWR,Digits00x.w ;look up table(LUT)for 3rd digit
 LDI X,Digits00x.d ;initialize LUT
 ANDI A,03Fh ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X) ;store value at X into A
 AND A,DigiDat1 ;...set bits in A for segments
 LD DigiDat1,A ;...store A into DigiDat1
ShowNumX
 RET
;***************************************************************************
;*   GetBatt   *
;*This routine adjusts the battery voltage stored in BADhi for the cable *
;*drop by calling GetDrop,then stores the result in the accumulator. *
;*         *
;***************************************************************************
GetBatt
 CALL GetDrop ;get approx batt cable voltage drop
 LD A,BADhi ;get latest avg batt voltage
 SUB A,Vdrop ;adjust for voltage drop in cable
 RET
;***************************************************************************
;*   Double6V   *
;*This routine doubles the accumulator,A,if the Bat6V flag is set.This *
;*routine is called before the accumulator is compared to one of the *
;*constants originally assigned for 12v batteries.   *
;*           *
;*NOTE:If the Hi6V flag is set,then the accumulator is set to MaxVolts *
;*instead of doubled.      *
;***************************************************************************
Double6V
 JRR Bat6V,Flags2,D6VX ;don′t double if not set for 6V
 JRR Hi6V,Flags4,D6V ;double if 6V Batt<8.5V
 LDI A,MaxVolts ;...otherwise,set A to MaxVolts
 JP D6VX  ;...and skip to end of routine
D6V
 SLA A  ;double A
D6VX
 RET
;***************************************************************************
;*   ADJUST VOLTAGE   *
;*This routine adjusts the battery voltage stored in BADhi for the cable *
;*drop by calling GetDrop,and doubles the result if set for 6V battery.*
;*         *
;***************************************************************************
AdjVolt
 CALL GetBatt ;get battery voltage adjusted for drop
 CALL Double6V ;double Battery voltage if set for 6V
RET
;***************************************************************************
;*   ADJUST AVERAGE   *
;*This routine adjusts the battery voltage stored in FreshBV for the cable*
;*drop by calling GetDrop,and doubles the result if set for 6V battery.*
;*         *
;***************************************************************************
AdjAvg
 CALL GetDrop ;get approx batt cable voltage drop
 LD A,FreshBV ;get latest (avg)battery voltage
 SUB A,Vdrop ;adjust for voltage drop in cable
 CALL Double6V  ;double Battery voltage if set for 6V
 RET
;***************************************************************************
;*   GET VOLTAGE DROP   *
;*This routine determines what value to use for the output cable voltage *
;*drop baed on the value of OFFSET,thte state of the output relay,and  *
;*the values in the DropOffs look-up table.   *
;*         *
;***************************************************************************
GeyDrop
 LD ATemp,A ;save Accumulator
 CLR Vdrop  ;set Vdrop to 0
 CLR Index  ;initalize LUT index to 0
 JRR RlyCls,Flags4,GDX ;leave 0 if output is off
 LDI Index,MaxDrop ;max index for High Power mode
GDLUT
 LDI DRWR,DropOffs.w ;look up table(LUT)Vdrop offsets
 LDI X,DropOffs.d ;initiaize LUT
 LD A,Index ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 CPA,OFFSET ;is OFFSET high enough to decrease Vdrop?
 JRNC GDX  ;...if not,skip ahead
 DEC Index ;...otherwise,decrement index
 JP GDLUT ;...and check next table entry
GDX
 LD A,Index ;get Vdrop LUT index
 LD Vdrop,A ;save new drop into Vdrop
 LD A,ATemp  ;restore Accumulator
 RET
;***************************************************************************
;*   GET VOLT DIGITS   *
;*This routine determines what three digits to display on the digital *
;*LED to represent the battery voltage(BADhi).
;*        *
;***************************************************************************
GetVolts
 DEC VltCnt ;decrement interval counter
 JR NewVolt  ;if0,ready to update display
 JP GetVexit  ;...otherwise,just exit
NewVolt
 LDI VltCnt,MS500 ;re-initialize interval counter
 JRR ChMode,Flags2,GVT ;if Tester mode,use FreshBV
 CALL GetBatt  ;get battery voltage adjusted for drop
 JP GV10
GVT
 LD A,FreshBV ;Get latest average battery voltage
GV10
 CALL DigiOff ;set registers for all segments off
 CLR Index ;initialize LUT Index to 0
 CPI A,Volts10  ;check for 10V
 JRC Check1V ;ifnot 10V then skip ahead
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,Volts10  ;...and subtract 10V from aocumulator
Check1V
 CPI A,Volts01  ;check if>1.0V
 JRC Check01V ;...if so,skip ahead and check 3rd digit
 INC Index ;...otherwise,show next higher value
 SUBI A,Volts01;...and subtract 1.0V from accumulator
 JP Check1V  ;...and check for next higher value
Check01V
 LD ATemp,A ;save Accumulator
 LDI DRWR,Digits0x0.w ;look up table (LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD A,Index ;get index from start of LUT
 ANDI A,03Fh ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 AND A,DigiDat2 ;...set bits in A for bottom segments
 LD DigiDat2,A ;...store A into DigiDat2
 LD A,ATemp ;restore Accumulator to remainder of LEDnum
ShowV001
 LDI DRWR,Digits0Vx.w ;look up table(LUT)for 3rd volts digit
 LDI X,Digits0Vx.d ;initialize LUT
 ANDI A,03Fh ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 AND A,DigiDat1 ;...set bits in A for bottom segments
 LD DigiDat1,A ;...store A into DigiDat1
 RES Decimal,DigiDat1;turn ON decimal point
GetVexit
 RET
;***************************************************************************
;*   VoltMeter   *
;*This routine sets the display to show volts,then calls ShowMeter and *
;*ShowData to update the display with the current battery voltage.  *
;*       *
;*   GetMeter     *
;*This routine calls ShowMeter and ShowData to display the latest  *
;*voltage or percentage(dete  ned by MtrScale & MtrUnits)on the  *
;*3-digit LED display.GetMerer is the last section of VoltMtr.  *
;*         *
;***************************************************************************
VoltMtr
 RES MtrScale,Flags ;set for Alternator % LED off
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
GetMeter
 CALL ShowMeter  ;update meter LEDs
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   GET PERCENT   *
;*This routine determines what value to use for the percentage of *
;*charge before the charge state has reached the dv/dt state.The *
;*percent is calculated by reading the battery voltage(BADhi)and  *
;*performing the following calculations:      *
;*As Tester        *
;*1.0V<BADhi<11.6VDC=>Percent=(BADhi/16)+1 *
;*11.61V<BADhi<12.8VDC=>Percent=(BADhi-175)*5+15 *
;*12.80V<BADhi=>Percent=100   *
;*As Charger   *
;*1Volt<BADhi<12Volts=>(BADhi/4)+15=Percent *
;*12Volts<BADhi<dv/dt=>(BADhi/2)-30=Percent *
;***************************************************************************
GetPercent
 JRR ChMode,Flags2,TstrBP;jump to Tester% if not charging
;JRS ChMode,Flags2,GPchg ;skip to Charging % if charging
;JP TstrBP ;...otherwise,jump to Tester %
;GPchg
 LD A,CurentSS ;get current program state
 CPI A,11;has charging reached dV/dt?
 JRC CalcPrcnt ;...if not,calculate percentage
GPend
 JP GetPctEnd ;...otherwise,do nothing
CalcPrcnt
 LD A,Percent ;get Percent
 CPI A,76  ;check for highest calculated %
 JRNC GPend ;exit if already there
;JRC GPmore ;continue if not there yet
;JP GetPctEnd ;...otherwise,just exit
;GPmore
 JRS HiPwr,Flags4,GPend;exit if in High Power mode
;JRR HiPwr,Flags4,GP1 ;continue if not in High Power mode
;JP GetPctEnd ;...otherwise,just exit
;GP1
 CALL AdjVolt ;adjust voltage for cable drop (& 6V scale)
 CPI A,Volts12;is the battery voltage less than 12V?
 JRNC Formula2 ;...No,goto Formula2
 CPI A,Volts01 ;Is battery>1
 JRNC GPform1 ;...if so,skip next line
 JP GPzero ;...if not,set for zero %
GPform1
 CALL Divide4 ;...Yes,use first formula
 ADDI A,15;Add 15and...
 JP GetPctExit ;...store into A
Formula2
 CALL Divide2 ;Divide by 2 and
 SUBI A,30 ;...subtract 30
 JP GetPctExit ;skip ahead and finish routine
TstrBP
 LD A,FreshBV ;get latest (avg)battery voltage
 CALL Double6V ;double Battery voltage if set for 6V
 CPI A,Volts128 ;Is battery>12.8V?
 JRC Tstr100 ;...if not,skip ahead
 CALL Set100p ;...otherwise,Percent=100
 JP GetPctEnd ;...and end routine
Tstr100
 CPI A,BattMin ;Is battery>BatMin
 JRNC TstrBPhi ;...if so,jump ahead
 CPI A,Volts01;Is battery>1
 JRNC TstrBPmed ;...if so,jump ahead
GPzero
 CALL Set0p ;...otherwise set Percent to 0
 JP GetPctEnd ;...and end routine
TstrBPhi
 SUBI A,BattMin ;subtract minimum high voltage
 CALL ATimes5 ;multiply by 5
 ADDI A,15  ;add 15
 JP GetPctExit ;...store into A
TstrBPmed
 SUBI A,15  ;A=battery-15
 CALL Divide4;A=(battery-15)/4
 CALL Divide4;A=(battery-15)/16
 INC A ;A=(battery-15)/16+1
GetPctExit
 LD Percent,A ;store into Percent
GetPctEnd
 RET
;***************************************************************************
;*   UPDATE BATTERY PERCENT   *
;*This routine controls how the battery percentage displayed is updated.*
;*UpdateBP ensures that under norma1 circumstances,the battery % dis-*
;*played is updated according to the following two rules.  *
;*1.The % displayed doesn′t change by more than 1% at a time  *
;*2.The % displayed is not updated twice in<PCint seconds  *
;*There are a few exceptions.     *
;*1.The % displayed canjump up more than 1 if it was 0  *
;*2.The % displayed will drop to 0 immediately for disconnected batt.*
;*3.The % displayed can change by more than 1 if the scale** changes *
;*        *
;***Scale refers to the % scale,which is either battery or alternator *
;*        *
;***************************************************************************
UpdateBP
 LD A,Percent ;check whether % is 0
 JRNZ UBP0  ;...if not,wait for update interval
 JP UBPfinish  ;...otherwise finish routine
UBP0
 LD A,DspPcnt ;get last % displayed
 JRZ UBP00  ;continue if 0%
 JP UBP1  ;skip ahead if not 0%
UBP00
 JRS MtrScale,Flags,UBP1 ;also skip ahead if Alternator %
 JRS Wait0P,Flags2,UBPz ;skip ahead if Wait0P flag already set
 SET Wait0P,Flags2 ;...otherwise,set flag to wait
 CALL IniTime2  ;initialize Timer2
 LDI SECs2,3  ;set Timer2 for 3 seconds
 JRR ChMode,Flags2,UBPz ;skip ahead if in tester mode
 LDI SECs2,5  ;set Timer2 for 5 seconds in charger mode
UBPz
 JRR SEC,TicFlag2,UBPx ;skip ahead if still waiting
;JP UBP0a ;...otherwise,update percent
UBP0a
 RES Wait0P,Flags2 ;set flag to indicate not waiting
 LD A,Percent ;...otherwise,get new %
 JP UBPfinish ;...and don′t wait to display it
UBPx
 JP UBPexit ;...and just exit
UBP1
 DEC PcntL ;decrement % interrupt counter
 JRNZ UBPx  ;if not 0 then just exit
;JRZ NewPsec ;if 0,decrement seconds counter
;JP UBPexit ;...otherwise,just exit
;NewPsec
 LDI PcntL,MSINIT ;re-initialize % interupt counter
 DEC PcntH ;decrement interval counter
 JRNZ UBPx  ;if not down to 0,then just exit
;JRZ NewPrcnt ;if counter=0,ready to update percent
;JP UBPexit ;...otherwise,just exit
;NewPrcnt
 LDI PcntH,PCint ;re-initialize % interval counter
 LD A,DspPcnt ;get last % displayed
 JRNZ UBP2  ;skip ahead if not 0%
 LD A,Percent ;get new %
 JP UBPfinish ;and finish routine
UBP2
 CP A,Percent ;compare to newest %
 JRZ UBPexit ;if equal,do nothing
 JRC IncBP  ;if less,increase display % by 1
 JRS ChMode,Flags2,UBPexit ;don′t decrease % if charging
 DEC A  ;...otherwise,decrease % by 1
 JP UBPfinish ;...and finish
IncBP
 INC A  ;increase display % by 1
UBPfinish
 LD DspPcnt,A ;store updated display %
UBPexit
 RET
;***************************************************************************
;*   HoldNum   *
;*This routine calls NumData to display LEDnum on the 3-digit LED display *
;*then waits 200mS and loads LEDnum into A.       *
;*         *
;***************************************************************************
HoldNum
 CALL NumData ;get data for,and show LED number
 CALL FifthSecond ;wait one fifth second
 CALL FifthSecond ;wait one fifth second
 LD A,LEDnum ;check latest number
 RET
;***************************************************************************
;*   MeterNum   *
;*This routine calls ModeOff,ShowNum,and ShowData to turn off the *
;*display mode LED′s and display LEDnum on the 3-digit LED display.  *
;*         *
;*    NumData     *
;*This routine calls ShowNum and ShowData to display LEDnum on the *
;*3-digit LED display.NumData is the last section of MeterNum.  *
;*         *
;***************************************************************************
MeterNum
 CALL ModeOff ;turn off all display mode LED′s
NumData
 CALL ShowNum  ;get data to show the number
 CALL ShowData  ;show the number
 RET
;***************************************************************************
;*   SHOW DATA   *
;*This routine updates the digital LED and 6 switch LEDs controlled by *
;*the serial to parallel shift registers. It sends the bits of SwData *
;*and DigiData to the registers bit by bit from LSB to MSB using  *
;*SerData. After each bit is sent,ShftClk is toggled to shift the bit *
;*to the next position.After all 24 bits have been sent,LtchClk is  *
;*used to update the outputs,which updates the LEDs.  *
;*        *
;***************************************************************************
ShowData
 CALL RstWDR  ;reset watch dog timer
 RES ClrData,DRAbuf ;clear shift register
 CALL UpdatePA ;update port A from buffer
 SET ClrData,DRAbuf ;prepare to accept data
 CALL UpdatePA ;update port A from buffer
 LDI BitCnt,008h ;initialize bit counter to 8
 LDI BytCnt,003h ;initializie byte counter to 3
 LD A,DigiDatl ;get first 8 bits of digit data
GetBit
 RLC A  ;send MSB of Acumulator to Carry
 JRC SetBit  ;if Carry=1 then data bit is 1
 RES SerData,DRAbuf ;...otherwise set SerData to 0
 JP SendBit ;skip ahead to SendBit
SetBit
 SET SerData,DRAbuf ;set SerData to 1
SendBit
 LD DataBuf,A ;store shifted data from A
 CALL UpdatePA ;update port A from buffer
 RES ShftClk,DRBbuf ;set Shift Clock low
 RES LtchClk,DRBbuf ;set Latch Clock low
 CALL UpdatePB  ;update port B from buffer
 SET ShftClk,DRBbuf ;set Shift Clock high
 CALL UpdatePB  ;update port B from buffer
 DEC BitCnt ;update bit count
 JRZ NextData ;if all bits sent then skip ahead
 LD A,DataBuf ;store shifted data back in A
 JP GetBit ;otherwise,get next bit
NextData
 DEC BytCnt ;update byte count
 JRNZ NextByte ;get next byte is count is not 0
 JP LatchData ;...otherwise,done sending bits
NextByte
 LDI BitCnt,08h ;set bit count for 8 more bits
 LD A,BytCnt ;which byte is next?
 CPI A,02h ;check for 2nd byte is next
 JRZ ScndByte ;skip ahead if equal
 LD A,SwData ;get 8 bits of switch LED data
 JP GetBit ;send bits of second byte
ScndByte
 LD A,DigiDat2 ;get last 8 bits of digit data
 JP GetBit ;send bits of second byte
LatchData
 SET LtchClk,DRBbuf ;update latches
 CALL UpdatePB ;update port B from buffer
 RET
;***************************************************************************
;*   Show Meter   *
;*This routine sets the digital LED to show either the current voltage *
;*or last percent based on Flags and CurentSS. During Engine start,it *
;*will count down seconds of either remaining crank time or cool down *
;*time.       *
;***************************************************************************
ShowMeter
 JRS Alert,Flags2,SMeXit ;exit if abort mode
;JRR Alert,Flags2,ChkMtr ;skip ahead if not abort mode
;JP SMeXit  ;...and exit
;ChkMtr
 JRS MtrUnits,Flags,GetPrcnt ;skip ahead and set for %
 CALL GetVolts ;...otherwise,get volts
 JRS ChMode,Flags2,SM1;skip ahead if not in Tester mode
 CALL ShowStatus ;...otherwise,update Status LEDs
SM1
 JP ShowMtrX ;...and skip to end or routine
GetPrcnt
;JRS ChMode,Flags2,ShoPer;if not tester mode,show %
 JRR ChMode,Flags2,TstMtr;if in tester mode,get %
 JP ShowPrcnt ;...otherwise,skip ahead & show %
Show0
  ALL Set0p ;set to show 0%
ShoPer
 JP ShowPrcnt ;and skip ahead
TstMtr
 LD A,FreshBV ;get latest Battery voltage
 JRZ Show0  ;if0V,show 0%
 JRR MtrScale,Flags,ShoPer;show Battery% if not set f or Alt%
;JRS MtrScale,Flags,AltTest ;skip ahead if set for Alt%
;JP ShowPrcnt ;...otherwise,skip to Battery%
;AltTest
 CALL Double6V ;double Battery voltage if set for 6V
 CPI A,AltMin ;check for<1st LUT value
 JRC Show0  ;if so,show 0%
;JRNC AltMaxT  ;if not,test for>last LUT value
;JP Show0  ;...otherwise,show 0%
;AltMaxT
 CPI A,AltMax ;check for>last LUT value
 JRC AltVal ;if not,skip ahead and check LUT
 LDI Percent,199  ;...otherwise,set to max value
 JP ShowPrcnt ;and skip ahead
AltVal
 LDI DRWR,AltLvls.w ;LUT for alternator %
 LDI X,AltLvls.d ;initialize LUT
 SUBI A,AltMin ;diffence is index in look up table
 ANDI A,03Fh ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 LD Percent,A ;store value into Percent
;JP ShowPrcnt ;and skip ahead
ShowPrcnt
 CALL ShowPercent ;otherwise,show percentage
 CALL ShowStatus ;turn on appropriate status LED
ShowMtrX
 CALL ShoMtrMode ;turn on appropriate meter LED
SMeXit
 CALL RstWDR  ;reset watch dog timer
RET
;***************************************************************************
;*   SHOW METER MODE   *
;*This routine turns on one of the meter units LED′s based on Flags and *
;*Flags2.If the unit is in TesterMode(ChMode=0),the routine will  *
;*also light the appropriate status LED based on the voltage at the *
;*clamps.          *
;*         *
;***************************************************************************
ShoMtrMode
 SET LEDvolt,DRAbuf ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
ShowVolts
 JRS MtrUnits,Flags,ShoPrcnt ;goto ShoPrcnt if set
 RES LEDvolt,DRAbuf ;turn on Voltage LED
 JP ShowMMX
ShoPrcnt
 JRS MtrScale,Flags,ShowAlt ;goro ShowAlt if set
 RES LEDprcnt,DRAbuf ;turn on Battery % LED
 JP ShowMMX
ShowAlt
 RES LEDalt,DRAbuf  ;turn on Alternator % LED
ShowMMX
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*  Hold Meter Mode LED(depending on mode)  *
;*This routine turns on the Battery%,Volts DC,or Alternator% LED based *
;*on Flags & Flags2 and keeps that LED on for one fifth second. *
;***************************************************************************
HoldMtrMd
 CALL ShoMtrMode ;turn on display mode LED
 CALL FifthSecond ;wait one fifth second
RET
;***************************************************************************
;*   SHOW STATUS   *
;*This routie turns on one of the three status LED′s based on the *
;*battery voltage. This routine is for use in the tester mode. *
;*         *
;***************************************************************************
ShowStatus
 JPS ChMode,Flags2,ShoStatX;exit if not Tester mode
;JRR ChMode,Flags2,TstrStat ;check for Tester mode
;JP ShoStatX  ;if not,skip to end
;TstrStat
JRR Batt,Flags2,RedStat ;show red LED if no battery
;JRS Batt,Flags2,StatBatt;skip ahead ifbattery connected
;JP RedStat  ;show red LED if no battery
;StatBatt
 JRR MtrUnits,Flags,ClrStat ;turn off Status LED′s ifvolts mode
;JRS MttrUnits,Flags,StatPrcnt ;skip ahead if not showing voltage
;JP ClrStat  ;...otherwise,turn Status LED′s off
;StatPrcnt
 LD A,FreshBV  ;get latest Battery voltage
 JRS MtrScale,Flags,TesAlt ;skip ahead if set for Alternator
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;Is it 100?
 JRZ GrnBatt  ;...if so,show green LED
 CALL ResetStatus  ;...othetwise,turn Status LED′s off
 JP ShoStatX  ;...and skip to end
GrnBatt
 CALL ShowGreen  ;turn on Green LED
 JP ShoStatX  ;skip to end
TestAlt
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,Volts 15a  ;Is alternator at least 15.07V?
 JRNC RedStat  ;...if so,skip ahead and show red
 CPI A,Volts138;is alternator at least 13.80V?
 JRC RedStat  ;...if not,skip ahead and show red
 CPI A,Volts14  ;Is alternator <14.0V?
 JRC ClrStat  ;...if so,sjkip ahead and show yellow
 CPI A,Volts149  ;is alternator at least 14.87V?
 JRNC ClrStat  ;...if so,skip ahead and show yellow
 CALL ShowGreen  ;...otherwise turn on Green LED
 JP ShoStatX  ;...and skip to end
RedStat
 CALL ShowRed  ;turn on Red LED
 JP ShoStatX  ;skip to end
ClrStat
 CALL ResetStatus  ;turn Status LED′s off
ShoStatX
 RET
;***************************************************************************
;*   METER OFF   *
;*This routine turns off the three display mode LED′s.  *
;*         *
;***************************************************************************
ModeOff
 SET LEDvolt,DRAbuf ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf ;turn off Battery % LED
 SET LEDalt,DRAbuf ;turn off Alternator % LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*   DigiOff   *
;*This routine set the registers to turn off the three-digit LED. *
;*         *
;***************************************************************************
DigiOff
 LDI DigiDat1,DigiOffa ;turn off 8 of 16 digital segments
 LDI DigiDat2,DigiOffb ;turn off other 8 of 16 digital segments
 RET
;***************************************************************************
;*   DIGITS OFF   *
;*This routine turns off the three-digit LED.  *
;*         *
;***************************************************************************
DigitsOff
 CALL DigiOff ;set registers for all segments off
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   DIGITS ON   *
;*This routine turns ON all segments of the three-digit LED.  *
;*         *
;***************************************************************************
DigitsON
 LDI DigiDat1,DigiONa ;turn ON 8 of 16 digital segments
 LDI DigiDat2,DigiONb ;turn ON other 8 of 16 digital segments
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   SHOW PERCENT   *
;*This routine turns ON the Battery % LED.  *
;*         *
;***************************************************************************
ShowPercent
 SET MtrUnits,Flags ;set Flags for %(not volts)
 JRR Wait0P,Flags2,SP1 ;skip ahead if not waiting from 0
 LDI DigiDat1,Dashesl ;...otherwise,show dashes while waiting
 LDI DigiDat2,Dashes2 ;...otherwise,show dashes while waiting
 JPShowPx
SP1
 LD A,DspPcnt ;get Percent value to display
 JRR MtrScale,Flags,SP2 ;don′t use Display% for Alternator%
 LD A,Percent ;...use actual Percent for display
 .IFC EQ ShoOff ;assemble next line only if debugging
 JRR ChMode,Flags2,SP2 ;skip ahead **DEBUG**
 LD A,CurentSS ;get current state **DEBUG**
 CPI A,12  ;check for di/dt or higher state **DEBUG**
 JRNC SP3  ;don′t show Vmax if state>11
 LD A,Vmax  ;get limit for dV/dt **DEBUG**
 JP SP4  ;don′t show MaintVolt if state<12
SP3
 LD A,MaintVolt ;get limit for VoltReg & di/dt
SP4
 CALL GV10;show voltage on digital LED
 JP ShowPx
;LD A,OFFSET  ;display OFFSET **DEBUG**
;JRS Rmpng,Flags3,SP2 ;**DEBUG**
;LD A,RmpCnt  ;display Ramp Count **DEBUG**
  .ENDC
SP2
 LD LEDnum,A ;...and store it in Accumulator
 CALL ShowNum  ;set digital LED for LEDnum
 SET Decima1,DigiDat1 ;turn OFF decimal point
ShowPx
 RET
;***************************************************************************
;*   RESET LEDS   *
;*This routine turns offthe Type,Rate,and Status LED′s  *
;*         *
;*CLEAR LEDS    *
;*This routine turns off the Type and Rate LED′s.  *
;*         *
;***************************************************************************
ResetLEDs
 CALL ResetStatus ;turn off all three status LEDs
ClrLEDs
 LDI SwData,SwsOff ;turn off Type and Rate LED′s
 RET
;***************************************************************************
;*   Reset Status   *
;*This routine turns off the LED′s in the Status area.  *
;*         *
;***************************************************************************
ResetStatus
  SET LEDchgng,DRAbuf ;turn off Charging LED
 SET LEDdone,DRAbuf ;turn off Charged LED
 SET LEDalert,DRAbuf ;turn offFault(red)LED
 RET
;***************************************************************************
;*   BLINK Charging LED   *
;*This routine blinks the Charging LED at a rate of once per second.*
;***************************************************************************
BlnkChrg
 LD A,MSECs1 ;get MSECs count
 CPI A,MS500 ;test for>1/2 sec
 JRNC BlinkCh1  ;if so,skip ahead
 CALL ResetStatus ;...otherwise,turn off status LEDs
 JP BlinkChX ;...and exit routine
BlinkCh1
 CALL ShowChgng ;Turn on Charging LED
BlinkChX
 RET
;***************************************************************************
;*   Show Charging   *
;*This routine turns the Charging LED on and the Check and Charged LEDs *
;*off.         *
;*    Show Yellow        *
;*This routine turns the Charging LED on and does not affect the Check *
;*and Charged LEDs.ShowYellow is actually the last part of ShowChgng *
;*        *
;***************************************************************************
ShowChgng
 CALL ResetStatus  ;turn off all Status LEDs
ShowYellow
 RES LEDchgng,DRAbuf ;turn ON Charging LED
 CALL UpdatePA ;update port A from buffer
 RET
;***************************************************************************
;*   BLINK Alert LED   *
;*This routine blinks the Alert LED at a rate of once per second.*
;*         *
;***************************************************************************
BlinkAlert
 LD A,MSECs1 ;getMSECs count
 CPI A,MS500 ;test for 1/2 sec
 JRNC BlnkAlrt ;if so,skip ahead
 CALL ResetLEDs ;...otherwise,turn off all LEDs
 JRS BurnIn,Flags3,BBI ;skip ahead if not Burn-In
 CALL DigitsON ;...turn on all digital LED segments
 JP BAeXit ;...and exit routine
BBI
 CALL NumData ;get data for,and show LED number
 JP BAeXit ;...and exit routine
BlnkAlrt
 CALL AlertON ;Turn on Alert LED
 CALL DigitsOff ;Turn off 3-digit LED
BAeXit
 PET
;***************************************************************************
;*   Alert LED ON   *
;*This routine turns on the Alert(red)LED and turns the other meter *
;*LEDs off.NOTE:it does not affect the Rate and Type LEDs. *
;***************************************************************************
AlertON
 CALL ModeOff ;Turn off display mode LEDs
ShowRed
 CALL ResetStatus  ;Turn off Status LEDs
 RES LEDalert,DRAbuf ;Turn on Alert LED
 CALL UpdatePA ;update port A from buffer
 RET
;***************************************************************************
;*   Show Done LED   *
;*This routine turns on the Done(green)LED and turns all the other  *
;*LEDs off.NOTE:it turns off the Rate and Type LEDs.  *
;***************************************************************************
ShowDone
 CALL ResetLEDs  ;Turn off all LEDs
 LDI SwData,SwsOff ;set Type & Rate LED′s off
 CALLL ShowType;show battery type & update display
ShowGreen
 CALL ResetStatus ;turn off all three status LEDs
 RES LEDdone,DRAbuf ;Turn on Done LED
 CALL UpdatePA ;update port A from buffer
 RET
;***************************************************************************
;*   BLINK Crank LED   *
;*This routine blinks the Crank LED at a rate of once per second. *
;***************************************************************************
BlinkCrank
 LD A,MSECs2 ;get MSECs count
 CPI A,MS500  ;test for>1/2 sec
 JRNC BlinkES  ;if so,skip ahead
 SET LEDboost,SwData ;...otherwise,turn off Crank LED
 JP BCeXit  ;...and exit routine
BlinkES
 CALL ShowCrank  ;turn on Crnak LED
BCeXit
 RET
;***************************************************************************
;*   ShowCrank   *
;*This routine turns the Engine Stary(Crank/Boost)LED on and turns *
;*the Type and other Rate LEDs off.      *
;*NOTE:The 6V LED will be left on if appropriate.   *
;***************************************************************************
ShowCrank
 CALL CltLEDs  ;turn off all Rate & Type LEDs
 JRR Bat6V,Flags2,ShoES ;skip ahead if not 6V
  RES LED6V,SwData ;turn on Regular 6V LED
ShoES
 RES LEDboost,SwData ;turn ON Crank LED
 CALL ShowData ;update display
 RET
;***************************************************************************
;*   SetSlow   *
;*This routine sets the charger for the Slow rate by setting the appro- *
;*priate flags.       *
;***************************************************************************
SetSlow
 RES Rate,Flags  ;turn on Slow LED
 RES Rapid,Flags2 ;turn off Rapid LED
 RET
;***************************************************************************
;*  Show Charge Rate LED(depending on mode)  *
;*This routine turns on the Slow,Fast,or Rapid LED,based on Flags.*
;*         *
;***************************************************************************
ShowRate
 SET LEDboost,SwData ;turn off Boost LED
  SET LEDrap,SwData  ;turn off Rapid LED
  SET LEDfast,SwData ;turn off Fast LED
  SET LEDslow,SwData  ;turn off Slow LED
  JP ChMode,Flags2,ShoRateX ;exit if in Tester Mode
;JPS ChMode,Flags2,ShowRap ;skip ahead if not Tester Mode
;JP ShoRateX
ShowRap
 JRR apid,Flags2,ShowSlow ;goto ShowSlow if not Rapid
 RES LEDrap,SwData  ;turn on Rapid LED
 JP ShoRateX
ShowSlow
 JPS Rate,Flags,ShowFast ;goto ShowFast if set
 JPS LEDslow,SwData ;turn on Slow LED
 JP ShoRateX
ShowFast
 RES LEDfast,SwData  ;turn on Fast LED
ShoRateX
 RET
;***************************************************************************
;*   Set12V     *
;*This routine sets the charger for the 12V Regular battery type by *
;*resetting the 6V,AGM/Gel,and Deep Cycle flags.  *
;*           *
;*SetReg           *
;*This routine sets the charger for the Regular battery type by reset- *
;*ting the Deep Cycle and AGM/Gel flags.SetReg is actually part of *
;*Set12V          *
;***************************************************************************
Set12V
 RES Bat6V,Flags2 ;turn off 6V LED
SetReg
 RES BatTypeA,Flags ;turn on Regular LED
 RES BatTypeB,Flags ;turn off Gel/AGM LED
 RET
;***************************************************************************
;*  Show Charge Type LED(depending on mode)  *
;*This routine turns on either the Regular,Deep Cycle,Gel/AGM,or 6V *
;*LED based on Flags.The routne also sets Vmax to match. *
;*       *
;***************************************************************************
ShowType
 SET LEDreg,SwData  ;set Regular LED to off
 SET LEDdeep,SwData ;set Deep Cycle LED to off
 SET LEDgel,SwData  ;set Gel/AGM LED to off
 SET LED6V,SwData  ;set 6V LED to off
 JRR Bat6V,Flags2,ShowT1;skip ahead if not 6V
ShowT0
 RES LED6V,SwData  ;turn on Regular 6V LED
 JP ShowT2a  ;set Vmax for regular(15.5V)
ShowT1
 JRR BatTypeB,Flags,ShowT2 ;skip ahead ifnot Gel/AGM
 RES LEDgel,SwData  ;turn on Gel/AGM LED
LDI Vmax,Volts144  ;Vmax=14.4V for Gel/AGM MODE
 JP ShoTypeX
ShowT2
 JRS BatTypeA,Flags,ShowT3 ;goto ShowT3 if set
 RES LEDreg,SwData  ;turn on Regular LED
ShowT2a
 LDI Vmax,Volts155  ;Vmax=15.5V for Regular MODE
 JP ShoTypeX
ShowT3
 RES LEDdeep,SwData ;turn on Deep Cycle LED
 LDI Vmax,Volts16  ;Vmax=16V for Deep Cycle battery
ShoTypeX
 RET
 ;**************************************************************************
;*  Hold Charge Type LED(depending on mode)  *
;*This routine turns on the Regular,Deep Cycle,or Gel/AGM LED based on *
;*Flags and keeps it on for one fifth second.  *
;***************************************************************************
HoldType
 CALL ShowType ;turn on Battery Type LED
CALL ShowData ;update display
 CALL FifthSecond ;wait one fifth second
RET
;***************************************************************************
;*  Hold Charge Rate LED(depending on mode)  *
;*This routine turns on the Slow,Fast,or Rapid LED based on Flags and *
;*keeps it on for one fifth second.    *
;***************************************************************************
HoldRate
 CALL ShowRate ;turn on Charge Rate LED
 CALL NumData ;get data for,and show nominal rate(amps)
 CALL FifthSecond ;wait one fifth second
RET
;***************************************************************************
;*   Check0V     *
;*This routine checks the latest running average of the battery voltage *
;*and sets the Carry bit if it′s less than Volts0+1 DAC count.This *
;*routine is used to check whether a battery is connected. *
;***************************************************************************
Check0V
 LD A,FreshBV ;test latest average voltage
 CPI A,Volts0+1 ;check if higher than zero
 RET
;***************************************************************************
;*   Check17v   *
;*This routine checks the latest running average of the battery voltage *
;*and sets the Carry bit if it′s less than Max Volts.This routine is *
;*used to check whether a battery is connected.  *
;***************************************************************************
Check17v
 LD A,FreshBV ;test latest average voltage
;LD A,BADhi ;test average voltage
 CPI A,MaxVolts ;check for max volt reading
 RET
;***************************************************************************
;*   Check Battery   *
;*CheckBatt compares the latest 32 sample(~1/4 second)average battery *
;*voltage,FreshBV,to the maximum possible battery voltage reading,17V.*
;*If FreshBV is 17V,then the battery was disconnected.CheokBatt also *
;*checks whether the voltage is less than 1.0V.If so,Flags2 is set for *
;*no battery detected.     *
;***************************************************************************
CheckBatt
 SET Batt,Flags2;set flag for connected battery
 JRS Settle,Flags3,ChkBattX ;dont check during settle time
 LD A,FreshBV  ;Get latest 1/4 second average voltage
;LD A,CurVolt  ;Get latest battery voltage
 JRR Bat6V,Flags2,ChkBatt4;skip next line if not set for 6V Batt
 JRR Hi6V,Flags4,ChkBatt4;skip next line if 6V batt<8.5V
;JRS Started,Flags,ChkBatt3;abort charge if 6V batt>8.5V
 JRS Started,Flags,NoBatt ;set for no batt.if 6V batt>8.5V
ChkBatt4
 CPI A,Volts01;Is it at least 1V?
 JRC NoBatt  ;If not,battery is not connected
;JRNC ChkBatt0  ;If so,battery might be connected
;JP NoBatt  ;If not,battery is not connected
;ChkBatt0
 CPI A,MaxVolts ;..otherwise,check for max volt reading
 JRNZ ChkBatX    ;if not,then still connected so just exit
;JRZ ChkBattl  ;fi=MaxVolts,might not be connected
;JP ChkBattX  ;...otherwise,still connected,just exit
;ChkBattl
 JRR SOC,SwDown,ChkBatt2 ;skip ahead if charge started 0-5 sec ago
ChkBatt3
 CALL SetAbort  ;set to start Abort mode
ChkBatX
 JP ChkBattX  ;jump to end of CheckBatt
ChkBatt2
 LD A,BADhi  ;if truly Max Volts,BADhi should be>16V
 CPI A,Volts16  ;if BADhi<16V,then disconnected
 JRNC ChkBattX  ;...otherwise,just exit
;JRC NoBatt  ;...so set for no battery
;JP ChkBattX  ;...otherwise,just exit
NoBatt
 RES Batt,Flags2  ;otherwise,set for not connected
 CALL ShowRed  ;turn on Alert(Red)LED
 CALL ClrPcnt  ;clear Percent and Display Percent
 CLR BADhi  ;clear previous voltage reading
 CLR FreshBV  ;clear previous voltage reading
ChkBattX
 RET
;***************************************************************************
;*   Check Progress   *
;*This routine is used to ensure that the charger will abort if the *
;*battery voltage does not increase throughout the charge.It checks the *
;*voltage every CPint minutes for a measurable increase since the *
;*previous check.If there isn′t,the charge is aborted.  *
;*         *
;***************************************************************************
ChkProg
 JRR MIN,TicFlag1,ChkProgX ;exit if not time to check for progress
ChkProg0
 JRR SOC,SwDown,ChkProg1 ;skip ahead if not Start Of Charge
 RES SOC,SwDown  ;...otherwise,clear SOC flag
 CALL IniTime1  ;initialize Timer1
 LDI MINs1,5  ;...set Timer1 for 5minutes
 CLR LastBatt  ;clear LastBatt(ensure pass 1st test)
 JP ChkProgX  ;...and exit
ChkProg1
 LD A,BADhi  ;get latest battery reading
 SUBI A,1  ;subtract one count
 CP A,LastBatt ;check for increase
 JRC ChkProgA  ;set to abort if no increase
 LD A,BADhi  ;set A back to BADhi
 LD LastBatt,A  ;update LastBatt
 CALL IniTime1  ;initialize Timer1
 .IFC NE FastCP  ;assemble next line only if not debugging
 LDI MINs1,CPint ;set Timer1 for 60minutes
 .ELSE   ;assemble next line only if debugging
 LDI MINs1,3  ;set Timer1 for 3 mins
 .ENDC
 DEC CCDcnt  ;update interval count
 JRNZ ChkProgX  ;just exit if not zero
 SET HR,TicFlag1  ;if zero,set for time expired
ChkProgA
 CALL SetAbort  ;set to start Abort mode
ChkProgX
 RET
;***************************************************************************
;*   Battery Progress   *
;*This routine is used to ensure that ChkProg and CheckBatt are called *
;*only when the charge rate is about to ramp up or isn′t set to ramp at *
;*all.That way,the battery voltage used to check charging progress *
;*won′t be affected by the higher current.BattProg works by checking *
;*RmpCnt to make sure it′s less than 5.If the start of charge flag(SOC)*
;*is set,BattProg does not check RmpCnt.  *
;*          *
;***************************************************************************
BattProg
 JRR Rmpng,Flags3,BtPrg0;skip ahead if not Rapid->Fast transition
 CALL RampOS  ;otherwise,gradually reduce duty cycle
BtPrg0
 CLRA  ;set A to 0 to ensure<(9,12,or 14.2V)
 JRS HiPwr,Flags4,BtPrgX ;exit if high power mode
;JRR HiPwr,Flags4,BtPrg1;skip ahead ifnot high power mode
;JP BtPrgX ;...otherwise,just exit
;BtPrg1
 JRS SOC,SwDown,BtPrg2;skip ahead if Start Of Charge
 LD A,RmpCnt ;get Ramp interval counter
;NOTE:RmpCnt will be 0 if not set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC BtPrgX  ;if not,then exit
BtPrg2
 CALL ChkProg  ;check for charging progress
 CALL AdjVolt ;adjust voltage for cable drop (& 6V scale)
BtPrgX
 RET
;***************************************************************************
;*   Check Dip   *
;*CheckDip compares the latest 32 sample(~1/4second)average battery *
;*voltage,FreshBV,to the maintain voltage used by VoltReg,MaintVolt. *
;*If FreshBV is more than 0.5V below the MaintVolt,the CheckDip checks *
;*the duty cycle.If OFFSET is between OffSlow and HiOff,then the *
;*charge current is more than 0but less than the Slow rate (usually 2A).*
;*In that case,the battery was probably disconnected CheckDip raises *
;*the charge rate to Slow by setting OFFSET to OffSlow.CheckDip also *
;*re-initializes the VoltReg interval counter,VRcnt,so that VoltReg *
;*won′t adjust OFFSET again for another second.If the battery really *
;*was disconnected,the output will shoot to 17V and CheckBatt will  *
;*indicate no battery.If there is a battery connected,then the output *
;*needed a boost to raise the voltage.      *
;*        *
;*NOTES:            *
;*CheckDip is only called by VoltReg,so the output must be on. *
;*VoltReg is only called when the charger is not in high power mode.*
;*If OFFSET if HiOff,then the output is zero.    *
;*       *
;***************************************************************************
CheckDip
 CALL AdjAvg ;get FreshBV adjusted for cable drop and 6V
 ADDI A,Volts005 ;add 1/2 volt
 CP A,MaintVolt ;compare with set value+1
 JRC ChkDp1  ;if FreshBV<MaintVolt-0.5V,continue
 JP ChkDipX ;...otherwise,exit routine
ChkDp1
 LD A,OFFSET ;get OFFSET
 CPI A,OffSlow ;check for rate>Slow
 JRC ChkDipX  ;exit if>Slow
;JRNC ChkDp2  ;if rate<Slow,then continue
;JP ChkDipX  ;...otherwise,exit routine
;ChkDp2
 CPI A,HiOff ;test if output is off
 JRNC ChkDipX ;if so,just exit
 LDI OFFSET,OffSlow ;...otherwise,set for Slow rate
 LDI VRcnt,MSINIT ;re-initialize initerval counter(1 sec)
ChkDipX
 RET
;***************************************************************************
;*      CHECK SWITCHES    *
;*Check if switch is engaged and change modes if appropriate. *
;*         *
;***************************************************************************
CheckSw
 JRR CrankWait,Flags,ChkStart ;check switches if not during Crank wait
 JP ChkSwRET  ;don′t check switches if during Crank wait
ChkStart
 JRS Crank,Flags,ChekRate ;don′t check display mode during Boost
;JRR Crank,Flags,ChkMeter ;check display mode if not during Boost
;JP ChkRate  ;skip display mode switch during Boost
;ChkMeter
 JRR MeterSw,DRC,MeterDown ;If switch is being pressed,skip ahead
 RES MeterSw,SwDown ;set for Meter switch not pressed (up)
ChekRate
 JP ChkRate  ;Meter switch not pressed,so exit CheckSw
MeterDown
 RES Idle,Flags3  ;set for not idle
 JRS MeterSw,SwDown,ChekRate ;If switch wasn′t released,don′t check it
;JRR MeterSw,SwDown,ChngMeter ;If switch was released,then check it
;JP ChkRate  ;Otherwise,skip ahead
;ChngMeter  ;change display mode
 SET MeterSw,SwDown ;set for mode switch pressed (down)
 JRR MtrScale,Flags,ChkPrcnt ;if not set for Alt,then skip ahead
 RES MtrScale,Flags  ;set for Alt%,so change to Batt%
;CLR DspPcnt  ;prepare to show new %(not adjust old %)
 JP ChkRate
ChkPrcnt
 JRR MtrUnits,Flags,ChkAlt ;if set for volts,then skip ahead
 RES MtrUnits,Flags ;set for Batt%,so change to volts
 JP ChkRate
ChkAlt
 SET MtrUnits,Flags ;set for volts,so change to %
 .IFC NE ShoOff ;assemble next line only if not debugging
 JRS ChMode,Flags2,ChkRate ;don′t set for Alt if charging
 .ENDC
 SET MtrScale,Flags ;set for batt,so change to alt
 RES Wait0P,Flags2;set to stop waiting for battery %
;CLR DspPcnt  ;prepare to show new %(not adjust old %)
ChkRate
 CALL ShoMtrMode ;Meter units are set before rate
 JRR RateSw,DRC,RateDown ;If switch is being pressed,skip ahead
 RES RateSw,SwDown  ;set for Rate switch not pressed(up)
ChekType
 JP ChkType  ;Rate switch not pressed,so check Type
RateDown
 RES Idle,Flags3  ;set for not idle
 JRS RateSw,SwDown,ChekType ;If switch wasn′t released,don′t check it
;JRR RateSw,SwDown,ChngRate ;If switch was released,then check it
;JP ChkType  ;Otherwise,skip ahead to Type Switch
;ChngRate  ;change Charge Rate
 SET RateSw,SwDown  ;set for mode switch pressed(down)
 JRS ChMode,Flags2,ChkCM ;skip ahead if already Charger mode
 SET Crank,Flags  ;...otherwise temporarily set Crank flag
 RES Disable,DRBbuf ;enable output after Rate is pressed
;JRR MtrScale,Flags,ChkCM ;skip ahead if not set for Alt%
;CLR DspPcnt  ;...otherwise,don′t use Alt%for charge
 RES MtrScale,Flags  ;set for Batt%(not Alt%)when not tester
ChkCM
 SET ChMode,Flags2  ;set for Charger(not tester)Mode
 JRR Crank,Flags,ChkSlow ;if not set for Crank,check for Slow
 RES Crank,Flags  ;clear Crank bit of Flags
 RES Rate,Flags  ;was Crank,so set for Slow
 JP ModeChange  ;go to end of CheckSw
ChkSlow  ;if set for Slow,then change to Fast
 JRS Rate,Flags,ChkFast ;If not Slow,then check Fast
 SET Rate,Flags  ;...otherwise,set rate for Fast
 JP ModeChange  ;go to end of CheckSw
ChkFast  ;if set for Fast,then change to Rapid
 JRS Rapid,Flags2,ChkES ;If not Rapid,then must be Fast
 SET Rapid,Flags2  ;set Charge rate for Rapid
 JP ModeChange  ;go to end of CheckSw
ChkES  ;was set to Rapid,change to Boost
 CALL SetSlow  ;set for Slow Rate
 SET Crank,Flags  ;set Charge rate for Boost
 CALL SetReg  ;set battery type for Regular
 CALL ShowCrank  ;turn ON Crank LED
  CALL TurnOff  ;open relay and set for min duty cycle
 CALL SetSafe  ;set OFFSET for OffSafe(~5A)when relay closes
 LDI CurentSS,CrankSS ;set Charge state to Crank
 CALL IniTime2  ;reset timer 2
 LDI SECs2,003h ;set Timer2 for 3 seconds
 JP ChkSwRET
ChkType  ;if Gel/AGM,then set for Regular
 JRR TypeSw,DRC,TypeDown ;If Switch is being pressed,skip ahead
 RES TypeSw,SwDown  ;set for Type switch not pressed(up)
ChkSwX
 JP ChkSwRET  ;Type switch not pressed,so exit CheckSw
TypeDown
 RES Idle,Flags3  ;set for not idle
 JRS TypeSw,SwDown,ChkSwX ;If Switch wasn′t released,don′t check it
;JRR TypeSw,SwDown,ChngType ;If Switch was released,then check it
;JP ChkSwRET  ;Otherwise,just exit
;ChngType  ;change Battery Type
 SET TypeSw,SwDown  ;set for mode switch pressed(down)
 JRR Bat6V,Flags2,ChkBT1 ;If not set for 6V,check for Regular
ChkBT0;if set for 6V,change to 12V regular
 RES Hi6V,Flags4  ;clear 6V over voltage flag
 CALL Setl2V  ;set for Regular,12V battery
 CALL ClrPcnt  ;clear Percent and Display Percent
  JP TypeChange  ;go to end of CheckSw
ChkBT1;if set for AGM/Gel,change to 6V
 JRR BatTypeB,Flags,ChkBT2 ;If not set for Gel/AGM,check for Regular
 JRS Hi6V,Flags4,ChkBT0 ;don′t set to 6V if batt>8.5V
 CALL SetReg  ;set battery type for Regular
 SET Bat6V,Flags2  ;set for 6V battery
 CALL ClrPcnt  ;clear Percent and Display Percent
  JP TypeChauge  ;go to end of CheckSw
ChkBT2  ;if Regular,then set for Deep Cycle
 JRS BatTypeA,Flags,ChkBT3 ;If not set for Regular,must be Deep Cycle
 SET BatTypeA,Flags  ;set battery type for Deep Cycle
 RES BatTypeB,Flags  ;set battery type not AGM/Gel
  JP TypeChange  ;go to end of CheckSw
ChkBT3  ;must be Deep Cycle,so set for Gel/AGM
 SET BatTypeB,Flags  ;set battery type for Gel/AGM
 RES BatTypeA,Flags  ;set battery type for not Deep Cycle
TypeChange
 RES Crank,Flags  ;set charge rate for non-Boost
 CALL ShowType     ;turn on Battery Type LED
ModeChange
 RES Crank,Flags  ;clear Crank bit of Flags
 LDI CurentSS,000h  ;restart charging
ChkSwRET
 RET
;***************************************************************************
;*      FAN ON     *
;*This routine turns the cooling fan ON.FanON is called during one of *
;*the following conditions:        *
;*1.Start of charge(end of State 2)    *
;*2.Start of boost(State 16)      *
;*3.If OFFSET<HiOff-3 in Maintain(State 14)     *
;*4.Manual Mode(State 15)      *
;*5.States 4,5,11,12,and 13*
;*         *
;***************************************************************************
FanON
 LD ATemp,A ;save Accumulator
 LDI A,00010000b ;update Accumulator from buffer
 LD DRC,A  ;update port from Accumulator
 LD A,ATemp ;restore Accumulator
 RET
;***************************************************************************
;*      FAN Off    *
;*This routine turns the cooling fan off.FanOff is called during one of*
;*the following conditions:      *
;*1.Before start of charge(State 0)      *
;*2.Start of Abort(State 8)      *
;*3.Before start of Maintain(State 14)   *
;*4.If OFFSET=HiOff in Maintain(State 14)         *
;*        *
;***************************************************************************
FanOff
 LD ATemp,A  ;save Accumulator
 LDI A,00000000b ;update Accumulator from buffer
 LD DRC,A ;update port from Accumulator
 LD A,ATemp  ;restore Accumulator
 RET
;***************************************************************************
;*   ShutOff    *
;*This routine sets the charger for no ouput by opening the output *
;*relay,turning off the fan,and setting the PWM for minimum duty  *
;*cycle(HiOFF).            *
;*        *
;*   TurnOff      *
;*This routine sets the charger for no ouput by opening the output *
;*relay and setting the PWM for minimum duty cycle(HiOFF).TurnOff is *
;*actually part of ShutOff.    *
;*          *
;***************************************************************************
ShutOff
 CALL FanOff  ;turn cooling fan off
TurnOff
 JRR Rlyls,Flags4,TrnOffX ;finish if relay already open
 LDI OFFSET,OffSafe ;set for Safe duty cycle
 CALL FifthSecond ;wait 200ms before opening relay
 RES RlyCls,Flags4 ;open output Relay
 CALL FifthSecond ;wait 200ms before reducing duty cycle
TmOffX
 LDI OFFSET,HiOff ;set for minimum duty cycle
 RET
;***************************************************************************
;*   TurnON      *
;*This routine sets the charger to run with the Charging LED and fan  *
;*on,and the output relay closed.     *
;*          *
;*    SetON       *
;*This routine sets the charger to run with the fan on and output relay *
;*closed.SetON is actually part of TurnON        *
;*         *
;***************************************************************************
TurnON
 CALL ShowChgng  ;turn Chaging LED on
SetON
 CALL FanON  ;turn cooling fan on
 SET RlyCls,Flags4  ;close output relay
 RET
;***************************************************************************
;*Update the clocks and set overflow flags as necessary. *
;*TicFlag1(s)bit 0=hours went to zero     *
;*TicFlag1(s)bit 1=minutes went to zero      *
;*TicFlag1(s)bit 2=seconds went to zero      *
;*TicFlag1(s)bit 3=miliseconds went to zero     *
;***************************************************************************
CLOCKS
 DEC MSECs1  ;decrement millisecond counter
;JRZ DO_MSECs
 ;JP CLOCKS1
  JRNZ Clks1  ;skip to clock2 if MSECs<>0
 DO_MSECs
 LDI A,MSINIT  ;restart millisecond counter
 LD MSECs1,A  ;
 SET MSEC,TicFlag1  ;set millisec flag
 DEC SECs1  ;decrement second counter
 JRZ DO_MINs
Clks1
 JP CLOCKS1
DO_MINs
 SET SEC,TicFlag1   ;set second expired flag
 LDI SECs1,SecInit  ;restart second counter
 DEC MINs1  ;decrement minute counter
;JRZ DO_HRs  ;check for overflow
;JP CLOCKS1
 JRNZ CLOCKS1  ;skip HRs1 if MINs1<>down to zero
DO_HRs
 SET MIN,TicFlag1  ;set minute expired flag
 LDI MINs1,MININIT  ;restart minute counter
 DEC HRs1   ;decrement hour counter
 JRNZ CLOCKS1   ;check for overflow
 SET HR,TicFlag1  ;set hour expired flag
CLOCKS1
 DEC MSECs2  ;decrement millisecond counter
 JRZ DOMSECs2
ClkExit
 JP CLOCEXIT
DOMSECs2
 LDI A,MSINIT  ;restart millisecond counter;
 LD MSECs2,A   ;
 SET MSEC,TicFlag2  ;set millisec flag
 DEC SECs2  ;decrement second counter
;JRZ DO_MINs2
;JP CLOCEXIT
 JRNZ ClkExit  ;exit if not down to zero
DO_MINs2
 SET SEC,TicFlag2   ;set second expired flag
 LDI SECs2,SecInit  ;restart second counter
 DEC MINs2  ;decrement minute counter
;JRZ DO_HRs2  ;check for overflow
;JP CLOCEXIT
 JRNZ CLOCEXIT  ;exit if not down to zero
DO_HRs2
 SET MIN,TicFlag2  ;set minute expired flag
 LDI MINs2,MININIT  ;restart minute counter
 DEC HRs2   ;decrement hour counter
 JRNZ CLOCEXIT  ;check for overflow
 SET HR,TicFlag2  ;set hour expired flag
CLOCEXIT
 RET
;******************************************************************************
;*  INITIALIZE TIMER1     *
;*  Subroutine to initialize timer1  *
;***************************************************************************
IniTime1
 LDI MSECs1,MSINIT
 LDI SECs1,SecInit
 LDI MINs1,MININIT
 CLR HRs1
 CLR TicFlag1
 RET
;***************************************************************************
;*    INITIALIZE TIMER2    *
;*    Subroutine to initialize Timer2  *
;***************************************************************************
IniTime2
 LDI MSECs2,MSINIT
 LDI SECs2,SecInit
 LDI MINs2,MININIT
 CLR HRs2
 CLR TicFlag2
 RET
;***************************************************************************
;*    ShiftA7  *
;*Subroutine to shift the accumulator left 7 times.Used by Divide2 *
;*and Divide4.Written only to save code space.    *
;***************************************************************************
ShiftA7
 SLA A ;shift left
 RLC A ;rotate left through CARRY bit 6 times
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 RET
;***************************************************************************
;*   DIVIDE BY 2     *
;*Subroutine to divide the number in A by 2.The remainder,if any *
;*will be available in the carry bit upon return.  *
;***************************************************************************
Divide2
 CALL ShiftA7 ;shift left once then rotate left 7 times
 RLC A ;rotate left 7th time
 RET
;***************************************************************************
;*   DIVIDE BY 4    *
;*Subroutine to divide the number in A by 4.   *
;***************************************************************************
Divide4
 CALL ShiftA7 ;shift left once then rotate left 7 times
 ANDI A,01111111b ;drop MSB
 RET
;***************************************************************************
;*A   A Times 5   *
;*Subroutine to multiply the accumulator (A)by 5.  *
;*Atimes5 multplies A by 4 by shifting left twice then adding the  *
;*original value of A:(A*4)+A=A*5    *
;***************************************************************************
ATimes5
 LD ATemp,A ;ATemp=A
 ADD A,A  ;A=A+A=A*2
 ADD A,A  ;A=A+A=ATemp*4
 ADD A,ATemp  ;A=A+ATemp=ATemp*5
 RET
;***************************************************************************
;*   VOLTAGE REGULATION   *
;*This subroutine will adjust the value of OFFSET once per second to *
;*control the current and maintain the voltage determined by MaintVolt. *
;*         *
;***************************************************************************
VoltReg
  .IFC EQ ShoReg ;assemble next line only if debugging
 LD A,OFFSET  ;get latest OFFSET
 LD TEMP1,A  ;store latest OFFSET in TEMP1
  .ENDC
  CALL CheckDip ;check for dip in batt voltage
 DEC VRcnt ;decrement interval counter
 JRZ VReg_0  ;Yes: then time to adjust
 JP VRegEXIT ;No: then not time to adjust
VReg_0   ;adjust offset
 LDI VRcnt,MSINIT ;re-initialize initerval counter(1 sec)
 CALL AdjAvg  ;get FreshBV adjusted for cable drop and 6V
 DEC A ;adjust A for comparison
 CPA,MaintVolt ;compare with set value+1
;JRC VReg_1  ;not greater than,test ifless than
 JRNC VRup  ;greater than,skip ahead
 JP VReg_1  ;not greater than,test if less than
VRup
 LD A,OFFSET ;greater than,get phase delay value
 INC A  ;adjust for comparison
 CPI A,HiOff+1 ;test ifat high limit
;JRNC VReg_3  ;at the limit,don′t change OFFSET
 JRC VReg_4  ;not at limit,so change OFFSET
 SET VRlmt,Flags4 ;...otherwise,set VoltReg Limit flag
 JP VReg_3  ;at the limit,don′t change OFFSET
VReg_4
 LD OFFSET,A  ;update OFFSET
 CPI A,HiOff-1 ;check for minimum output
 JRNZ VReg_3  ;if not,then skip next line
 SET MinOut,Flags4 ;...otherwise,set MinOut flag
VReg_3
 JP VRegEXIT  ;done for this pass
VReg_1
 INC A  ;ajdust for comparison
 CP A,MaintVolt ;compare with set value
 JRNC VRegEXIT ;not less than,just exit
 LD A,OFFSET ;less than,get phase delay value
 DEC A  ;
 CPI A,OffFast ;test ifat low limit
;JRNC VReg_4 ;not at the limit,update OFFSET
 JRC VRegEXIT ;at limit,don′t update
 JP VReg_4 ;not at the limit,update OFFSET
VRegEXIT
 JRR RlySw,Flags4,VRR ;skip ifrelay not about to change
 JRS RlyCls,Flags4,VRR ;skip if relay already closed
 LDI OFFSET,HiOff-1 ;OFFSET should be HiOff-1 when relay closes
VRR
;the next section lights LED′s for debugging
  .IFC EQ ShoReg ;assemble next lines only if debugging
 LD A,OFFSET ;get new offset
 CP A,TEMP1 ;compare it to previous value
 JRZ VRegYel ;turn on yellow LED if no change
 JRC VRegRed ;turn on red LED if decreased
 CALL ShowGreen ;turn on Green LED otherwise
 JP VRegDone ;...and exit routine
VRegRed
 CALL ShowRed ;turn on Red LED
 JP VRegDone ;...and exit routine
VRegYel
 LD A,CurentSS ;check current state
 CPI A,9  ;in desulphation mode?
 JRZ VRegDone ;...if so,exit routine
 CALL ShowChgng ;...otherwise,turn on Charging LED
VRegDone
  .ENDC
 RET
;***************************************************************************
;*   TIMER INTERRUPT HANDLER   *
;*This routine turns the FETs on after every timer interupt and inhibits *
;*the timer.It also opens or closes the relay depending on RlyCls. *
;***************************************************************************
PwrCon
 LD ATemp,A  ;save A register
 JRS RlyCls,Flags4,PCon ;skip ahead if charger is on
PCoff
 RES RlyCtl,DRBbuf ;...open output relay
 JP PCend ;not charging,leave relay open
PCon
 SET RlyCtl,DRBbuf ;...otherwise,close output relay
PCend
 RES PWMhi,DRBbuf ;turn FETs on
 CALL UpdatePB ;update port B from buffer
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 CALL RstWDR  ;reset watch dog timer
 LDI A,FULLTIME ;TCR is reloaded here for 1full cycle
 LD TCR,A  ;set timer(on time)for FULLTIME
 LDI TSCR,01011101b ;reload prescaler and start timer
 SET NMInt,Flags2  ;tell ExitMain this was timer interupt
PCexit
 LD A,ATemp ;restore A register
 RETI
;***************************************************************************
;*          NON-MASKABLE INTERRUPT HANDLER   *
;*This is the NMI interrupt routine.The NMI is generated on the falling *
;*edge of the full wave rectified AC line voltage.An interrupt is *
;*generated 120 times per second,once every 8.333ms.After each NMI,*
;*this routine performs the following steps. *
;*1.Reset the watchdog timer and save the registers. *
;*2.Turn off the FETs(unless OFFSET=0 and Relay<>0). *
;*3.Set the interrupt timer according to OFFSET. *
;*4.Reset NMInt so ExitMain knows it′s an NMI (not timer int). *
;*5.Update the clocks.  *
;*6.Restore the registers.  *
;*If turned off,the FETs will remain off for a period determined by *
;*OFFSET.The Timer will then trigger an interrupt which tells PwrCon *
;*to turn the FETs back on if necessary. *
;*            *
;***************************************************************************
IT_TIMER
 CALL RstWDR  ;reset watch dog timer
 LD ATemp,A ;save A register
 LD A,X  ;get X register
 LD XTEMP,A ;save X register
 JRS RlyCls,Flags4,IT_ON ;skip ahead if output is on
IT_OFF
 RES RlyCtl,DRBbuf ;...otherwise,shut off output
 JP IT_PWM ;jump ahead and set PWM
IT_ON
 SET RlyCtl,DRBbuf ;close output relay
 LD A,CurentSS  ;check for CrankON state
 CPI A,013h  ;CrankON state is 013 hex
 JRZ IT_Bst ;jump to full on during CrankON
IT_PWM
 SET PWMhi,DRBbuf ;shut off PWMhi
 LD A,OFFSET ;get latest offset
 CPI A,MinOff ;OFFSET=MinOff means almost full on
 JRNZ IT_OS  ;...otherwise,skip ahead & set offset
;JRZ IT_Bst  ;if almost full on,then go full on
;JP IT_OS  ;skip ahead & set offset
IT_Bst ;Boost(Full Power)
 RES PWMhi,DRBbuf ;turn on high power PWM
 SET RlyCtl,DRBbuf ;close output relay
 LDI TSCR,00010101b ;reset TSCR and inhibit TIMER interupt
 JPIT_TMR
IT_OS
 LD TCR,A ;load the counter with current offset
 LDI TSCR,01011101b ;reload prescaler(32)and start timer
IT TMR
 CALL UpdatePB ;update port B from buffer
 RES NMInt,Flags2 ;tell ExitMain this was NMI interupt
 CALL CLOCKS  ;update clocks
 LD A,XTEMP ;restore registers
 LD X,A
 LD A,ATemp
 RETI
;***************************************************************************
;*  A/D INTERRUPT HANDLER   *
;*This is the A to D interrupt service routine.The only thing it does is *
;*clear the interrupt bit and wakes the processor up from its wait mode.*
;***************************************************************************
ADINT
 RES 7,ADCR
 LD A,ADR
 RETI
;***************************************************************************
;* ROM DATA WINDOW for THIRD VOLTS LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the third(least significant)digit of the voltage display. *
;***************************************************************************
.block 16-$%16
Digits0Vx
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;display_0 for 00h
.byte 01111110b ;display_1 for 01h
.byte 01111110b ;display_1 for 02h
.byte 00110001b ;display_2 for 03h
.byte 00111000b ;display_3 for 04h
.byte 00111000b ;display_3 for 05h
.byte 01011100b ;display_4 for 06h
.byte 10011000b ;display_5 for 07h
.byte 100t1000b ;display_5 for 08h
.byte 10010000b ;display_6 for 09h
.byte 00111110b ;display_7 for 0Ah
.byte 00111110b ;display_7 for 0Bh
.byte 00010000b ;display_8 for 0Ch
.byte 00011000b ;display_9 for 0Dh
.byte 00011000b ;display_9 for 0Eh
;***************************************************************************
;*  ROM DATA WINDOW for THIRD LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the third(least significant)digit on the LED.*
;***************************************************************************
.block 16-$%16
Digits00x
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;bit pattern to display_0
.byte 01111110b ;bit pattern to display_1
.byte 00110001b ;bit pattern to display_2
.byte 00111000b ;bit pattern to display_3
.byte 01011100b ;bit pattern to display_4
.byte 10011000b ;bit pattern to display_5
.byte 10010000b ;bit pattern to display_6
.byte 00111110b ;bit pattern to display_7
.byte 00010000b ;bit pattern to display_8
.byte 00011000b ;bit pattern to display_9
;***************************************************************************
;*  ROM DATA WINDOW for SECOND LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the second(middle significant)digit on the LED. *
;***************************************************************************
.block 16-$%16
Digits0x0
;patterns for DigiDat2-Digit 2(middle digit)and MS 1
.byte 00000101b ;bit pattern to display_0_
.byte 11001111b ;bit pattern to display_1_
.byte 00100011b ;bit pattern to display_2_
.byte 10000011b ;bit pattern to display_3_
.byte 11001001b ;bit pattern to display_4_
.byte 10010001b ;bit pattern to display_5_
.byte 00010001b ;bit pattern to display_6_
.byte 11000111b ;bit pattern to display_7_
.byte 00000001b ;bit pattern to display_8_
.byte 10000001b ;bit pattern to display_9_
;***************************************************************************
;*  ROM DATA WINDOW for Output Cable Voltage Drop  *
;*The following values are the OFFSET values at which Vdrop is adjusted.*
;*The value of OFFSET is a rough indication of the output current,which *
;*is directly related to the voltage drop in the output cable. *
;***************************************************************************
.block 16-$%16
DropOffs
;OFFSET Vdrop Power Current
.byte 0FFh ;00 High > 0.0A
.byte 098h ;01 High > 5.?A
.byte 090h ;02 High > 10.?A
.byte 088h ;03 High > 15.?A
.byte 080h ;04 High > 19.6A
.byte 07Bh ;05 High > 23.5A
.byte 075h ;06 High > 28.2A
.byte 070h ;07 High > 32.1A
.byte 06Dh ;08 High > 34.5A
.byte 069h ;09 High > 37.6A
.byte 065h ;0A High > 40.7A
;.byte 068h ;0B High > 27.2A
;.byte 063h ;0C High > 30.0A
;.byte 05Fh ;0D High > 32.2A
;.byte 05Ah ;0E High > 35.1A
;.byte 056h ;0F High > 37.5A
;.byte 066h ;10 High > 40.2A
;***************************************************************************
;*  ROM DATA WINDOW for Alternator Charge in Percent  *
;*The following values are the Percent values for the alternator voltages *
;*listed below.These numbers are only used when the charger is in *
;*Tester mode.Voltages lower than the first entry are displayed as 0% *
;*charged.Voltages above the last entry are displayed as 199% charged. *
;***************************************************************************
.block 32-$%32
AltLvls
;% Volts Hex
.byte 0 ;13.53 CB red
.byte 12 ;13.60 CC |
.byte 25 ;13.67 CD |
.byte 38 ;13.73 CE red
.byte 50 ;13.80 CF yellow
.byte 62 ;13.87 D0 |
.byte 75 ;13.93 D1 yellow
.byte 85 ;1400 D2 reen
.byte 92 ;14.07 D3 |
.byte 97 ;14.13 D4 |
.byte 100 ;14.20 D5 |
.byte 100 ;14.27 D6 |
.byte 100 ;14.33 D7 |
.byte 100 ;14.40 D8 |
.byte 100 ;14.47 D9 |
.byte 100 ;14.53 DA |
.byte 100 ;14.60 DB |
.byte 103 ;14.67 DC |
.byte 110 ;14.73 DD |
.byte 120 ;14.80 DE green
.byte 130 ;14.87 DF yellow
.byte 140 ;14.93 E0 |
.byte 150 ;15.00 E1 yellow
.byte 160 ;15.07 E2 red
.byte 170 ;15.13 E3 |
.byte 180 ;15.20 F4 |
.byte 190 ;15.27 E5 |
.byte 196 ;15.33 E6 red
.byte 199 ;15.40 E7 red
;****************************************************************************
;*             Interrupt vectors               *
;****************************************************************************
 .org 0FF0h
ADC
 JP ADINT
TIMER
 JP PwrCon
INT2
 NOP
 RETI
INT1
 NOP
 RETI
 .org 0FFCh
NMI
 JP IT_TIMER
RST
 JP RESET
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
71223D.asm
;Checksum
;Raw Code: 6E460
;With Info: 6E460
;***************************************************************************
;*  COPYRIGHT 2004 SCHUMACHER ELECTRIC  *
;*    ALL RIGHTS RESERVED   *
;*    WRITTEnBY   *
;*  THOMAS F.JOHNSON   *
;*     *
;* Digital DieHard 71223 2/15/50/125A Charger/Starter/Tester *
;* This code is for the SGS-THOMPSON micro-controler *
;* Part number ST62T25/ST62E25   *
;*        *
;*;***************************************************************************
 .title ″Digital DieHard 71223 Charger Ver.0.17″
 .LINESIZE 131
 .vers ″ST6225″
 .romsize 4
 .w_on
DEBUG .SET 1;1->normal,0->Ignore Type and Rate switches after SS5
ShoOff .SET 0;1->normal,0->Show OFFSET in Alt% mode during charging
FastCP .SET 1;1->normal,0->3 min ChkProg interval instead of 60 min
ShoADC .SET 1;1->normal,0->Use PB2to indicate A/D activity
LongTst .SET 0;1->normal,0->Set manual mode for 255(not 1)hours
AdjOff .SET 0;1->normal,0->Allow manual adjustment of OFFSET(SS15)
;***************************************************************************
;*   Define the port hardware locations  *
;***************************************************************************
;*  At times,the .def statement is followed by a value and ″!m″.The !m *
;*is used by the simulator/emulator for debugging.This symbol tells the *
;*equipment what registers the user wants to monitor during debuging. *
;***************************************************************************
X .def 80h!m      ;Index register
Y .def 81b       ;Index register
V .def 82h       ;Short direct register
W .def 83h        ;Short direct register
A .def 0ffh!m     ;Accumulator
DRA .def 0c0h!m      ;Port a data register
DRB .def 0c1h!m      ;Port b data register
DRC .def 0c2h       ;Port c data register
DDRA .def 0c4h       ;Port a direction register
DDRB .def 0c5h       ;Port b direction register
DDRC .def 0c6h       ;Port c direction register
ORA .def 0cch       ;Port a option register
ORB .def 0cdh       ;Port b option register
ORC .def 0ceh       ;Port c option register
ADR .def 0d0h!m      ;A/D data register
ADCR .def 0d1h        ;A/D control register
PSC .def 0d2h       ;Timer prescaler register
TCR .def 0d3h!m      ;Timer counter register
TSCR .def 0d4h        ;Timer status control register
WDR .def 0d8h         ;Watchdog register
IOR .def 0c8h!m      ;Interrupt option register
DRWR .def 0c9h          ;Data rom window register
;****************************************************************************
;*    These are the ram equates used by the battery charger.    *
;****************************************************************************
DRAbuf .def084h ;shadow ram for port A data register
DRBbuf .def 085h ;shadow ram for port B data register
DRCbuf .def 086h ;shadow ram for port C data register
ATemp .def 087h ;Accumulator temporary storage
XTEMP .def 088h ;X register temporary storage
MSecs1 .def089h ;storage for 8.333ms tics-count of 120=1 sec
Secs1 .def08Ah ;storage for timer1 seconds
Mins1 .def08Bh ;storage for timer1 minutes
Hrs1 .def 08Ch ;storage for timer1 hours
TicFlag1 .def08Dh ;overflow flags for Secs1,Mins1,and hours
MSecs2 .def 08Eh ;millisecond one counter
Secs2 .def 08Fh ;storage for timer2 seconds
Mins2 .def 090h ;storage for timer2 minutes
Hrs2 .def 091h ;storage for timer2 hours
TicFlag2 .def 092h ;overflow flags for Secs1,Mins2,and hours1
Tries .def 093h ;used by battery detect routines
TEMP .def 094h ;scratch pad area
TEMP1 .def 095h ;scratch pad area
Temp2 .def 096h ;count used for FreshBV
CurVolt .def 097h ;current battery voltage
MaintVolt .def 098h ;storage for MAINTAIN voltage level
OldVolt .def 099h ;previous battery voltage.used for dv/dt
CCDcnt .def 09Ah ;display countdown during crank cool down
OldOff .def 09Bh ;old value of OFFSET used in dI/dt
BADlo .def 09Ch ;low bits battery voltage average
BADhi .def 09Dh ;hi bits battery voltage average
Vmax .def 09Eh ;maximum battery voltage(per Battery Type)
Vref .def 09Fh ;ref voltage for desulfation
OFFSET .def 0A0h ;storage for phase delay value
FreshBV .def 0A1h ;avg batt volt used for di/dt ref
FBVTotLo .def 0A2h ;low byte of total used for FreshBV
FBVTotHi .def 0A3h ;high byte of total used for FreshBV
CurentSS .def 0A4h ;stores current charger state
Flags .def 0A5h ;charger configuration states
  ;bit 0(BatTypeA): 0for Reg,1 for D/C
  ;bit 1(BatTypeB): 0for Norm,1 for AGM/GEL
  ;bit 2(Rate):   0 for Slow,1 for Fast
  ;bit 3(Crank):   1 ifin Boost mode
  ;bit 4(CrankWait): 1 during E/S cool down
  ;bit 5(Started): 1 if charging started
  ;bit 6(MtrUnits): 0 for Volts,1 for %
  ;bit 7(MtrScale): 0 for Batt,1 for Alt
Flags2 .def 0A6h ;stores the following Flags
  ;bit 0(Batt): 1 if battery connected
  ;bit 1(Rapid): 1 if set for Rapid charge rate
  ;bit 2(Bat6V): 1 if set for 6V battery
  ;bit 3(Power): 1 if output is on
  ;bit 4(NMInt): 1 if NMI interrupt,0 if Timer
  ;bit 5(ChMode): 1 if in Charger Mode
  ;bit 6(Wait0P): 1 if waiting for % to change from 0
  ;bit 7(Alert): 1 indicates Alert condition
Flags3 .def 0A7h ;stores the following Flags
  ;bit 0(RmpInt): 1 during 1st half of each Ramp interval
  ;bit 1(Settle): 1 during voltage settle time
  ;bit 2(HiEnd): 1 if higher voltage for EndCharge
  ;bit 3(Idle): 1 until a button is pressed
  ;bit 4(Hi6V): 1 if battery>8.5V
  ;bit 5(NxtCnt): 1-> 1st second of count
  ;bit 6(Manual): 1 if in Manual Mode
  ;bit 7(BumIn): 1 if in Burn-in Mode
SwDown .def 0A8h ;Indicates state of switches(1->pressed)
  ;bit 4=SwOff flag(debugging)
  ;bit 5=Type switch
  ;bit 6=Rate switch
  ;bit 7=Meter switch
DigiDat2 .def 0A9h ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 3 segments B & C
  ;bit 1=digit 2 segment F
  ;bit 2=digit 2 segment G
  ;bit 3=digit 2 segment A
  ;bit 4=digit 2 segment B
  ;bit 5=digit 2 segment C
  ;bit 6=digit 2 segment D
  ;bit 7=digit 2 segment E
DigiDatl .def 0AAh ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 1 segment C
  ;bit 1=digit 1 segment G
  ;bit 2=digit 1 segment D
  ;bit 3=digit 1 segment E
  ;bit 4=digit 2 decimal point
  ;bit 5=digit 1 segment F
  ;bit 6=digit 1 segment A
  ;bit 7=digit 1 segment B
SwData .def 0ABh ;data for the 3 Rate and 3 Type LEDs(0->ON,1->off)
  ;bit 0=6V battery type LED
  ;bit 1=Reg battery type LED
  ;bit 2=D/C battery type LED
  ;bit 3=AGM battery type LED
  ;bit 4=60A charge rate LED
  ;hit 5=15A charge rate LED
  ;bit 6=300A charge rate LED
  ;bit 7=2A charge rate LED
BitCnt .def 0ACh ;Index of bit sent to display
BytCnt .def 0ADh ;Index of word sent to display
DataBuf.def 0AEh ;Temp storage for Data bits
VltCnt .def 0AFh ;Counter for voltage display interval
TempOff .def 0B0h ;temp offset value
RmpCnt .def 0B1h ;counts ramp intervals until next ramp
LEDnum .def 0B2h ;stores number to be shown on digital LED
Percent .def 0B3h ;stores percent to be shown on digital LED
Index .def 0B4h ;used for look up table access
LowOff.def 0B5h ;min offset value for di/dt(highest current)
VRcnt .def 0B6h ;Counter for voltage regulation interval
PcntL .def 0B7h ;NMI counter for percent display update
PcntH .def 0B8h ;Interval counter for percent display update
DspPcnt .def 0B9h ;storage for last percent displayed
Flags4 .def 0BAh ;stores the following Flags
  ;bit 0(IdleSet): 1 if 10 minute Idle timer was started
  ;bit 1(NoRamp): 1 during Manual Fast charge
  ;bit 2(SOC): 1 if at start of charge(1 st 5s)
  ;bit 3(Crnkng): 1 if cranking(State 19)
  ;bit 4(HiPwr): 1 if charge rate>Fast
  ;bit 6(Restore): 1 if in desulfation mode(SS9)
LastBatt .def 0BBh ;stores battery reading used to monitor progress
;free .def 0BCh ;free
ORBbuf.def 0BDh ;shadow RAM for ORB register
;free .def 0BEh ;free
;free .def 0BFh ;free
;0BFh=last RAM location
;***************************************************************************
;*These are the constants used by the battery charger.  *
;***************************************************************************
Volts005 .equ 008h ;0.5 VOLTS
Volts0 .equ 00Ah ;0.7 VOLTS
Volts01 .equ 00Fh ;1.0 VOLTS
Volts016 .equ 017h ;miminum voltage for engine start,1.5V
Volts02 .equ 01Eh ;2.0 VOLTS
Volts05 .equ 04Bh ;5.0 VOLTS
Volts06 .equ 05Ah ;6.0 VOLTS
Volts066 .equ 061h ;6.6 VOLTS
Volts075 .equ 071h ;7.5 VOLTS
Volts09 .equ 087h ;very discharged battery voltage
Volts10 .equ 096h ;10.0 VOLTS
BattMin .equ 0AFh ;lowest value in Battery % LUT
Volts12 .equ 0B4h ;low battery voltage
Volts122 .equ 0B7h
Volts125 .equ 0BCh
BattMax .equ 0BDh ;highest value in Battery % LUT
Volts127 .equ 0BEh
Volts128 .equ 0C0h ;good battery test voltage
Volts13 .equ 0C3h
Volts132 .equ 0C6h
Volts135 .equ 0CAh
AltMin .equ 0CBh ;lowest value in Alternator %LUT
Volts138 .equ 0CFh
Volts14 .equ 0D2h
Volts142 .equ 0D5h ;start monitoring dv/dt voltage
Volts1435 .equ 0D7h
Volts144 .equ 0D8h
Volts146 .equ 0DAh ;maximum allowed voltage for reg/gel mode
Volts147 .equ 0DCh ;start trickle timer voltage
Volts149 .equ 0E0h ;14.87V
Volts15 .equ 0E1h ;maximum allowed voltage for RV/DC Marine
Volts15a .equ 0E2h ;15.07V
AltMax .equ 0E7h ;highest value in Alternator % LUT
Volts155 .equ 0E9h ;maximum allowed voltage for Auto/Marine Starting
Volts16 .equ 0F0h ;maximum allowed voltage
Volts165 .equ 0F7h ;maximum allowed voltage for deep cycle 2
Volts17 .equ 0FCh ;maximum allowed voltage
MaxVolts .equ 0FFh ;maximum voltage reading-17.0V
RCinitR .equ 75 ;ramp count intervals for Rapid rate
RCinitF .equ 180 ;ramp count intervals for Fast rate
RIinit .equ 60 ;NMI interrupts per 1/2 ramp count interval
MSINIT .equ 078h ;millisecond initialization value(120)
MS500 .equ 03Ch ;millisecond counter value for 500mS(60)
MS200 .equ 018h ;millisecond counter value for 200mS(24)
SecInit .equ 03Ch ;second initialization value(60)
MinInit .equ 03Ch ;minute initialization value(60)
MaxHrs .equ 25 ;maximum allowed charge hours+1
CPint .equ 60 ;minutes per charge progress interval
HR .equ 000h ;hours bit of TicFlag1 and TicFlag2
MIN .equ 001h ;minutes bit of TicFlag1 and TicFlag2
SEC .equ 002h ;seconds bit of TicFlag1 and TicFlag2
MSEC .equ 003h ;milliseconds
VLO .equ 0C0h ;low line limit-100 VAC
VHI .equ 0EEh ;high line voltage limit-130 VAC
BatLoSlo .equ 150 ;low battery voltage current adjust-10.0 Vdc
BatLoFst .equ 150 ;low battery voltage current adjust-10.0 Vdc
BatLoRap .equ 135 ;low battery voltage current adjust-9.0 Vdc
Bat6LoSlo .equ 75 ;low battery voltage current adjust-5.0 Vdc
Bat6LoFst .equ 75 ;low battery voltage current adjust-5.0 Vdc
Bat6LoRap .equ 75 ;low battery voltage current adjust-5.0 Vdc
;BatHiSlo .equ 0D5h
;BatHiFst .equ 0C6h
PCint .equ 00Ah ;number of 1-second intervals between % updates
FULLTIME .equ 0ADh ;half second when AC power is OFF
SlowAmps .equ 2 ;Nominal amps out at Slow rate
FastAmps .equ 12 ;Nominal amps out at Fast rate
RapAmps .equ 30 ;Nominal amps out at Rapid rate
CmkAmps .equ 80 ;Nominal amps out at Crank rate
CodeRev .equ 0 ;software revision level
OffLowSlo .equ 130 ;Lowest current in 12V 2A offset table
OffSlow .equ 130 ;Nominal offset for slow charge(~20%)
OffHiSlo .equ 116 ;Current in 12V 2A offset table for 14.2V
MinOffSlo .equ 114 ;Max Current for 12V 2A rate during di/dt
OffLowFst .equ 103 ;Lowest current in 12V Fast offset table
OffFast .equ 103 ;Nominal offset for fast charge(12A)
OffHiFst .equ 87 ;Highest current in 12V Fast offset table
MinOfFst .equ 85 ;Max Current for 12V Fast rate during di/dt
OffRamp .equ 80 ;offset for Fast<>Rapid transition
OffRap .equ 74 ;Nominal offset for rapid charge(~90%)
OffLowRap .equ 74 ;Lowest current in 12V rapid offset table
OffHiRap .equ 30 ;Highest current in 12V rapid offset table
OffCrank .equ 95 ;OFFSET for Crank standby
Off6LoSlo .equ 137 ;First entry in 6V 2A offset table
Off6Slo .equ 137 ;Nominal offset for 6V slow charge(2A)
Off6HiSlo .equ 137 ;Current in 6V 2A offset table for 7.0V
Min6OffSlo .equ 135 ;Max Current for 6V 2A rate during di/dt
Off6LoFst .equ 107 ;Lowest current in 6V Fast offset table
Off6Fst .equ 107 ;Nominal offset for 6V Fast charge(12A)
Off6HiFst .equ 106 ;Highest current in 6V Fast offset table
Min6OfFst .equ 104 ;Max Current for 6V Fast rate during di/dt
Off6Rap .equ 82 ;Nominal offset for 6V Rapid charge
Off6LoRap .equ 82 ;Lowest current in 6V Rapid offset table
Off6HiRap .equ 77 ;Highest current in 6V Rapid offset table
Off6Cmk .equ 90 ;OFFSET for 6V Crank standby
HiOff .equ 140 ;high limit for OFFSET variable
HiOff6 .equ 160 ;high limit for OFFSET variable(6V mode)
ABORT .equ 008h ;abort state
LEDslow .equ 007h ;Slow LED-bit of SwData
LEDboost .equ 006h ;Crank LED-bit of SwData
LEDfast .equ 005h ;Fast LED-bit of SwData
LEDrap .equ 004h ;Rapid LED-bit of SwData
LEDgel .equ 003h ;AGM/Gel LED-bit of SwData
LEDdeep .equ 002h ;Dp Cycl LED-bit of SwData
LEDreg .equ 001h ;Regular LED-bit of SwData
LED6V .equ 000h ;6V Reg LED -bit of SwData
LEDdone .equ 000h ;Charged LED-PORT A
LEDchgng .equ 00lh ;Charging LED-PORT A
LEDalert .equ 002h ;Fault LED-PORT A
LEDprcnt .equ 003h ;Percent LED-PORT A
LEDvolt .equ 004h ;Voltage LED-PORT A
LEDalt .equ 005h ;Altrntr LED-PORT A
SerData .equ 006h ;Serial Data-PORT A
ClrData .equ 007h ;Data Clear-PORT A
ShftClk .equ 000h ;Shift Clock-PORT B
LtchClk .equ 001h ;Latch Clock-PORT B
ESrly .equ 003h ;E/S relay-PORT B
Disable .equ 006h ;Disable ctrl-PORT B
SCRs .equ 007h ;SCR control-PORT B
FanCtl .equ 004h ;Fan control-PORT C
TypeSw .equ 005h ;Type switch-PORT C
RateSw .equ 006h ;Rate switch-PORT C
MeterSw .equ 007h ;Meter switch-PORT C
SwOff .equ 004h ;bit in SwDown for disabled Type & Rate switches
BatTypeA .equ 000h ;bit in Flags for battery type:0=Reg,1=D/C
BatTypeB .equ 001h ;bit in Flags for battery type:1=AGM/Gel Cell
Rate .equ 002h ;bit in Flags for charge rate:0=Slow,1=Fast
Crank .equ 003h ;bit in Flags that indicates engine start
CrankWait .equ 004h ;bit in Flags that indicates cool down between cranks
Started .equ 005h ;bit in Flags that indicates charge started
MtrUnits .equ 006h ;bit in Flags for meter units:0=volts,1=%
MtrScale .equ 007h ;bit in Flags for meter scale:0=batt,1=altrntr
Batt .equ 000h ;bit in Flags2:1 ifb attery is connected
Rapid .equ 001h ;bit in Flags2:1 if charge rate is Rapid
Bat6V .equ 002h ;bit in Flags2:1 if output is > 10A
Power .equ 003h ;bit in Flags2:1 if output is on
NMInt .equ 004h ;bit in Flags2:1 if NMI interrupt,0 if Timer
ChMode .equ 005h ;bit in Flags2:1 if in Charger mode(not Tester)
Wait0P .equ 006h ;bit in Flags2:1 if battery > 10V
Alert .equ 007h ;bit in Flags2:1 indicates trouble
RmpInt .equ 000h ;bit in Flags3:1 during 1st halfeach Ramp interval
Settle .equ 001h ;bit in Flags3:1 during voltage settle time
HiEnd .equ 002h ;bit in Flags3:1 if higher voltage for EndCharge
Idle .equ 003h ;bit in Flags3:1 until a button is pressed
Hi6V .equ 004h ;bit in Flags3:1 if battery>8.5V
NxtCnt .equ 005h ;bit in Flags3:0 during last half of CCDcnt interval
Manual .equ 006h ;bit in Flags3:1 during Manual modes
BurnIn .equ 007h ;bit in Flags3:1 during Burn-In mode
IdleSet .equ 000h ;bit in Flags4:1 if 10 minute Idle timer was started
NoRarnp .equ 001h ;bit in Flags4:1 during manual fast charge
SOC .equ 002h ;bit in Flags4:1 during Start Of Charge(1st 5 sec)
Crnkng .equ 003h ;bit in Flags4:1 during cranking(State19)
HiPwr .equ 004h ;bit in Flags4:1 if charge rate > Fast
Restore .equ 006h ;bit in Flags4:1 if in desulfation routine
CrankOff .equ 180 ;crank offtime in seconds
CrankON .equ 5 ;crank on time in seconds
CCDint .equ 001h ;crank cool down display counter interval(seconds)
CrankSS .equ 010h ;crank SS is state 16=10 hex
Decimal .equ 004h ;bit in DigiDatl for decimal point
Digitl .equ 000h ;bit in DigiDat2 for most significant 1
SwsOff .equ 11111111b ;bit pattern for all switches off
DigiOffa .equ 11111111b ;bit pattern for all segements off
DigiOffb .equ 11111111b ;bit pattern for all segements off
DigiONa .equ 00000000b ;bit pattern for all segements ON
DigiONb .equ 00000000b ;bit pattern for all segements ON
Dashes1 .equ 11111101b ;bit pattern to display__-
Dashes2 .equ 11111011b ;bit pattern to display_-_
DigiRev1 .equ 00010010b ;bit pattern to display__0
DigiRev2 .equ 01100001b ;bit pattern to display_P_
DigiMV1 .equ 11010011b ;bit pattern to display__L
DigiMV2 .equ 00000101b ;bit pattern to display_O_
;****************************************************************************
;*               COLD START                 *
;****************************************************************************
;.org 0880h ;for ST6210/15
 .org 0100h ;for ST6220/25
RESET
 CALL RstWDR ;reset watch dog timer
;****************************************************************************
;*             Clear The Ram Area               *
;****************************************************************************
RAMCLR
 LDI X,084h ;point X to lst RAM Location
RAMCLR1
 CLR A  ;clear A
 LD(X),A ;store A at location pointed to by X
 INC X  ;increment X
 LD A,X  ;get pointer in A
 CPI A,0C0h ;test for end of RAM
 JRNZ RAMCLR1 ;do again ifnot finished
;****************************************************************************
;*          Now Set Up The Hardware I/O Ports           *
;****************************************************************************
PORTA
 ;Bit 0=LED-Done   (Output,0=ON)
 ;Bit 1=LED-Charging(Output,0=ON)
 ;Bit 2=LED-Alert  (Output,0=ON)
 ;Bit 3=LED-Battery%(Output,0=ON)
 ;Bit 4=LED-Volts DC (Output,0=ON)
 ;Bit 5=LED-Altrntr%(Output,0=ON)
 ;Bit 6=Serial Data  (Output,0=ON)
 ;Bit 7=Display Clear (Output,0=clear)
 ;Bit# 76543210
LDI DDRA,11111111b ;Set all bits as outputs
LDI ORA,11000000b ;open-drain outputs 0-5;6-7push-pull
LDI DRA,11111111b ;Set initial values to 1(off)
LDI DRAbuf,11111111b ;store settings in shadow RAM
PORTB
 ;Bit 0=Shift clock(Output,0->1=Shift)
 ;Bit 1=Latch clock(Output,0->1=Latch)
 ;Bit 2=LED-Amps (not used)
 ;Bit 3=E/S relay (Output,0=Charge,1=Start)
 ;Bit 4=Batt sense (not used)
  ;Bit 5=Batt Voltage(Input,Analog)
  ;Bit 6=Disable out(Output,1=disabled)
  ;Bit 7=SCR drive  (Output,0=ON)
  ;Bit# 76543210
  LDI DDRB,11011111b ;bits 5 is input,others are outputs
  LDI ORB,11111111b ;PB5 analog;others push-pull
  LDI DRB,11100111b ;initialize high except 3-4
  LDI DRBbuf,1110011lb ;store settings in shadow RAM
 PORTC
  ;Bit 4=Fan Control(Output,0=off,1=ON)
  ;Bit 5=Type switch(Input,0=IN/change)
  ;Bit 6=Rate switch (Input,0=IN/change)
  ;Bit 7=Meter switch (Input,0=IN/change)
  ;Bit# 76543210
 LDI DDRC,00011111b ;bit 4 is output,others are inputs
 LDI ORC,00011111b ;non-interrupt inputs,push-pull output
 LDI DRC,00001111b ;Set internal pull-ups for bits 5-7
 LDI DRCbuf,00001111b ;store settings in shadow RAM
TSCRINIT
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 SET 4,IOR      ;enable interupts
 RETI
 CALL InitState ;initialize to slow(2A)auto mode
;The next three lines are to set the maximum idle tester time
 CALL IniTime1 ;initialize timer 1
 LDI Mins1,0Ah ;settimer 1 for 10 minutes
 SET Idle,Flags3 ;indicates no buttons pressed yet
;The next three lines set the unit for Tester(not Charger)mode
 RES ChMode,Flags2 ;set for Tester Mode
 CALL ShowData  ;initialize display
INIT_01
;JP MAIN  ;debug
;**************************************************************************************
;*    Test Routines   *
;*This routine checks the switches at power up to determine whether to *
;*enter one of the test modes. The possible test modes and the switch *
;*combinations that trigger them are as follows.  *
;*        *
;*Meter Rate Type Test Mode     *
;*Y x N Power On Self Test(POST):LED′s light in sequence *
;*N Y N Manual Slow Charge(1 hour max for all manual mode)*
;*N N  Y Manual Medium Charge(Fast for boost models)*
;*N Y  Y Manual Fast Charge(Fast-Rapid for boost models)*
;*Y x Y Burn-In Mode:Fast/Rapid Charge for 60 minutes *
;*       *
;*Y->pressed,N->not pressed,x->either(not checked)  *
;*        *
;**************************************************************************************
TEST
 JRS MeterSw,DRC,NoPOST ;Skip ahead if Meter Mode button not pressed
 JRS TypeSw,DRC,POST ;Skip to POST if Type button not pressed
 JP TestBI  ;...otherwise,skip ahead to Burn-In setup
NoPOST
  JRR RateSw,DRC,TEST1 ;Check Type switch if Rate switch is pressed
  JRS TypeSw,DRC,NoTest ;go to MAIN if no switch is pressed
   ;Set for Manual Fast Charge
 SET Rate,Flags  ;turn on Fast LED,turn off Slow LED
 RES Rapid,Flags2 ;turn off Rapid LED
 RES HiPwr,Flags4 ;turn off high power mode
;SET NoRamp,Flags4 ;set for Fast rate w/o ramp up to Rapid
 LDI OFFSET,OffFast ;set for Fast rate
 JP TestMM1  ;set for Manual charge
NoTest
 JP MAIN  ;skip test and go to MAIN
TEST1  ;Set for manual Slow Charge
 JRR TypeSw,DRC,TEST2 ;if Type switch is pressed,set for Fast Test
 CALL SetSlow ;set for Slow Rate
 CALL StartSlow ;set OFFSET for Slow rate
;LDI OFFSET,OffSlow ;set Offset for 2A
 JP TestMM1  ;set for Manual charge
TestBI  ;Set for 60 minute Burn-In
 SET BurnIn,Flags3 ;Set for Burn-In mode
 LDI OFFSET,OffFast ;set for Fast rate
 RES HiPwr,Flags4 ;turn offhigh power
 CALL SetRmpUp  ;prepare to ramp from Fast to Rapid
 TEST2 ;set for Manual Rapid Charge
;SET Manual,Flags3 ;set for Manual mode
 SET Rate,Flags  ;set for non-Slow rate
 SET Rapid,Flags2 ;turn on Rapid LED
;RES NoRamp,Flags4 ;set for ramping
 JRS BurnIn,Flags3,TestRap ;don′t set for ramp down if Burn-In
 SET HiPwr,Flags4 ;turn on high power
 LDI RmpCnt,RCinitR ;set counter for Rapid
;RES RampUp,Flags3 ;set for ramp down
 LDI OFFSET,OffRap ;set Offset for Rapid Charge
 CALL SetRamp ;set ramping parameters
TestRap
 JP TestMM1 ;set for Manual charge
POST
 CALL ResetLEDs ;turn offall type,rate & Status LED′s
 CALL MeterOff ;turn off all meter mode LED′s
 CALL DigitsOff ;turn off 3-digit LED
 RES Power,Flags2 ;make sure output will be off
;show status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL FifthSecond ;wait one Fifth second
 CALL ShowChgng ;light Charging LED
 CALL FifthSecond ;wait one Fifth second
 CALL AlertON ;turn on Alert(Red)LED
 CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
;show charge rate LED′s
 SET ChMode,Flags2 ;must set flag to show rate LED′s
 RES Crank,Flags ;turn off Crank LED
 CALL SetSlow ;set for Slow Rate
 LDI LEDnum,SlowAmps ;set digital LED to show Slow rate
 CALL HoldRate ;show Rate and wait a Fifth second
 SET Rate,Flags  ;turn on Fast LED
 LDI LEDnum,FastAmps ;set digital LED to show Fast rate
 CALL HoldRate  ;show Rate and wait a Fifth second
 SET Rapid,Flags2 ;turn on Rapid LED
 LDI LEDnum,RapAmps ;set digital LED to show Rapid rate
 CALL HoldRate ;show Rate and wait a Fifth second
 RES ChMode,Flags2 ;clear flag to disable output
 LDI LEDnum,CrnkAmps ;set digital LED to show Crank rate
 CALL ShowNum ;get data to show the LED number
  CALL ShowCrank ;turn on Crank(Boost)LED
  CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs ;turn offall type,rate & Status LED′s
 CALL ShowData ;update display
;show battery type LED′s
 CALL Set12V ;set for Regular,12V battery
 LDI DigiDat1,DigiRev1 ;set digital LED to show Code Revision
 LDI DigiDat2,DigiRev2 ;set digital LED to show Code Revision
 CALL HoldType ;show Type and wait a Fifth second
 SET BatTypeA,Flags ;turn on Deep Cycle & turn off Regular LED
  CALL HoldType  ;show Type and wait a Fifth second
 SET BatTypeB,Flags ;turn on Gel/AGM LED
 RES BatTypeA,Flags ;turn offDeep Cycle LED
  CALL HoldType ;show Type and wait a fifth second
 RES BatTypeB,Flags ;turn off Gel/AGM LED
 SET Bat6V,Flags2  ;turn ON 6V LED
  CALL HoldType ;show Type and wait a Fifth second
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
 RES Bat6V,Flags2  ;set for 12V battery(not 6V)
;show display mode LED′s
 CALL ShowData ;update display
 SET MtrUnits,Flags ;set for % LEDs ON,volts LED off
 RES MtrScale,Flags ;set for Alternator % LED off
 CALL HoldMtrMd ;show meter mode and wait one fifth second
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
 CALL HoldMtrMd ;show meter mode and wait one fifth second
 SET MtrUnits,Flags ;set for % LEDs ON,volts LED off
 SET MtrScale,Flags ;set for Alternator % LED ON
 CALL HoldMtrMd  ;show meter mode and wait one fifth second
 CALL MeterOff ;turn off all meter mode LED′s
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
 LDI LEDnum,5 ;initialize to 5 to show 4 lst
POST2
 DEC LEDnum ;the next number will be 1 less
 CALL NumData ;get data for,and show LED number
 CALL FifthSeeond ;wait one fifth second
 LD A,LEDnum ;check for last number
 JRNZ POST2;loop back and repeat if not there
POST3
 ADDI A,20  ;adding 20 changes 2nd digit
 LD LEDnum,A ;prepare to show new number
 CALL NumData ;get data for,and show LED number
 CALL FifthSecond ;wait one fifth second
 LD A,LEDnum ;check latest number
 CPI A,100 ;compare to last number
 JRNZ POST3  ;loop back and repeat if not there
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
 CALL InitState ;reset to Slow,TypeA charge mode
 RES ChMode,Flags2 ;set for Tester mode
 JP TEST  ;repeat POST if necessary
TestMM1  ;Set for manual charge
 SET Manual,Flags3 ;set for Manual mode
 SET ChMode,Flags2 ;set for Charger Mode(output enabled)
 RES Disable,DRBbuf ;enable output
 LDI CurantSS,15 ;State 15 is Manual charge
 SET Started,Flags ;set Flags for charge started
 SET Power,Flags2 ;tell PwrCon charger is on
 CALL IniTimel  ;initialize Timerl
  .IFC NE LongTst ;assemble next line only ifnot debugging
 LDI Hrs1,1  ;set Timerl for 1 hour
  .ELSE  ;assemble next line only if debugging
 LDI Hrs1,255 ;setTimerl for 255 hours
  .ENDC
 JRR BurnIn,Flags3,MAIN ;skip next 2 lines if not Burn-in
TestMM2
 CALL IniTime2  ;reset Timer2
 LDI Mins2,1 ;set timer for counter interval(1 minute)
 LDI CCDcnt,60 ;set Burn-in minute counter to 60
;******************************************************************************
;*                MAIN                    *
;******************************************************************************
;******************************************************************************
;*Because the A/D voltage is being averaged,it would take considerable  *
;*time to notice that a battery has become disconnected.To overcome this *
;*DELAY the program will monitor the instantaneous voltage each time thru *
;*the loop to detect this condition.This cheek will be made only if the *
;*unit is in a charging mode.                     *
;******************************************************************************
MAIN
 CALL RstWDR  ;reset watch dog timer
 LD A,CurentSS  ;get current state
 CPI A,ABORT  ;check for abort
 JRNZ MainMore  ;continue Main if not Abort
 JP MAIN3  ;don′t continue Main if Abort
MainMore
 JRR Manual,Flags3,MainAuto ;continue Main if not Manual Mode
 JP SS15  ;otherwise,goto Manual charge
MainAuto
 JRS CrankWait,Flags,MAIN1;don′t check switches during Crank wait
 CALL CheckSw  ;check if switch is being pressed
MAIN4
 JRS Crank,Flags,MAIN0 ;skip ahead ifduring Crank
 CALL GetPercent ;update the percentage reading
 CALL UpdateBP  ;update % to display
 CALL GetMeter  ;update display
 JRR Idle,Flags3,MAIN0  ;skip ahead if not idle
 JRR Batt,Flags2,MAIN0  ;don′t check idle time limit ifno battery
 JRS IdleSet,Flags4,MAIN5 ;don′t set idle timer if already set
 CALL IniTime1  ;...otherwise initialize timer 1
 LDI Mins1,0Ah  ;set timer 1 for 10 minutes
 SET IdleSet,Flags4  ;Idle timer started,set flag
MAIN5
 JRR MIN,TicFlag1,MAIN0 ;...otherwise,check idle time limit
 RES Disable,DRBbuf ;...enable output after idle time limit
 JP MAIN2  ;...and re-initialize if reached
MAIN0  ;not Crank,check for 0 or 1
 JRS Power,Flags2,MAIN1 ;charger is ON,goto 0V check
 JRS LEDchgng,DRAbuf,MAIN3 ;charger not almost on,skip 0V check
MAIN1  ;Check for disconnected battery
 CALL CheckBatt  ;check for disconnected battery
 JRS Batt,Flags2,MAIN3 ;skip ahead if connected
MAIN2  ;0V detected,prepare to start over from state 0
 LDI DspPcnt,0  ;initialize display Percent to 0
 CALL InitState  ;initialize to Slow Regular Charge mode
MAIN3
;*********************************************************************************
;*            SEQUENCE STATE JUMP TABLE            *
;*Determine what routine to execute on this pass through the the loop.Only*
;*one routine is executed each time through the loop.             *
;*********************************************************************************
NSS0
 LD A,CurentSS
 JRNZ NSS1
 JP SS0 ;*SS0-BATTERY DETECT *
NSS1
 CPI A,001h
 JRNZ NSS2
 JP SS1 ;* SS1-BATTERY DETECT DELAY *
NSS2
 CPI A,002h
 JRNZ NSS3
 JP SS2 ;*SS2-AUTOMATIC CHARGE START *
NSS3
 CPI A,003h
 JRNZ NSS4
 JP SS3 ;*SS3-BELOW 9 Volts *
NSS4
 CPI A,004h
 JRNZ NSS5
 JP SS4 ;*SS4-BELOW 12 Volts *
NSS5
 CPI A,005h
 JRNZ NSS8
 JP SS5 ;*SS5-NORMAL CHARGE *
NSS6
;CPI A,006h
;JRNZ NSS7
;JP SS6 ;* SS6-dv/dtMONITOR *NOT USED
NSS7
;CPI A,007h
;JRNZ NSS8
;JP SS7 ;* SS7-CHARGE COMPLETE * NOT USED
NSS8
 CPI A,008h
 JRNZ NSS9
 JP SS8 ;* SS8-ABORT CHARGE *
NSS9
 CPI A,009h
 JRNZ NSS11
 JP SS9 ;* SS9-DESULFATION *
NSS 10
;CPI A,00Ah
;JRNZ NSS11
;JP SS10 ;* SS10-RESTORE CHARGE *
NSS11
 CPI A,00Bh
 JRNZ NSS12
 JP SS11 ;* SS11-dV/dt MONITOR *
NSS12
 CPI A,00Ch
 JRNZ NSS13
 JP SS12 ;* SS12-dI/dt MONITOR *
NSS13
 CPI A,00Dh
 JRNZ NSS14
 JP SS13 ;* SS13-ENDCHARGE *
NSS14
 CPI A,00Eh
 JRNZ NSS 15
 JP SS14 ;* SS14-MAINTAIN *
NSS15
 CPI A,00Fh
 JRNZ NSS16
 JP SS15 ;* SS15-Manual *
NSS16
 CPI A,010h
 JRNZ NSS17
 JP SS16 ;* SS16-CRANK *
NSS17
 CPI A,011h
 JRNZ NSS18
 JP SS17 ;* SS17-CRANK *
NSS18
 CPI A,012h
 JRNZ NSS19
 JP SS18 ;* SS18-CRANK *
NSS19
 CPI A,013h
 JRNZ NSS20
 JP SS19 ;* SS19-CRANK *
NSS20
 CPI A,014h
 JRNZ NSS21
 JP SS20 ;* SS20-CRANK *
NSS21
 LDI WDR,001h    ;invalid sequence state,reset
;***************************************************************************
;*               END OF MAIN    *
;*Wait for NMI,which indicates end of FET on period,before measuring *
;*battery voltage.                           *
;***************************************************************************
ExitMain
XMain
 WAIT  ;wait for interupt
 JRS NMInt,Flags2,XMain ;timer interupt???
;***************************************************************************
;*             READ BATTERY VOLTAGE                *
;*  This routine is executed at or near zero cross.The current voltage *
;*is stored in CurVolt and the reading is added to BADhi(two locations).*
;*BADhi will containa running average of the last 256 readings.   *
;***************************************************************************
BADREAD
  .IFC EQ ShoADC ;assemble next 2 lines only if debugging
 SET 2,DRBbuf ;set PB2 when A/D sampling starts
 CALL UpdatePB ;update port B from buffer
  .ENDC
 LD A,BADlo ;get average reading
 SUB A,BADhi ;subtract one reading from the running total
 JRNC BADEWAD1 ;no carry,go on
 DEC BADhi ;adjust hgh order bits
BADEWAD1
 LD BADlo,A ;store new value
 LDI ADCR,0B0h ;start A/D conversion
 LDI ADCR,0B0h ;do again to insure a valid start
 WAIT  ;let the interupt notify us when data is ready
 LD CurVolt,A ;save current reading
 ADD A,BADlo ;add into running average
 JRNC BADREAD2 ;no carry,go on
 INC BADhi ;increment high bits
BADEWAD2
 LD BADlo,A ;store new low bits
  .IFC EQ ShoADC ;assemble next 2 lines only if debugging
 RES 2,DRBbuf ;set PB2 when A/D sampling starts
 CALL UpdatePB ;update port B from buffer
  .ENDC
;LDI ORB,01Fh
;LDI ORB,09Fh
;***************************************************************************
;*            di/dt AVERAGE CALCULATION            *
;*For use by the di/dt,about four times every second the average of the *
;*previous 32 curvolt readings is stored in FreshBV for comparison to a *
;*reading taken once every second.   *
;***************************************************************************
DIDTAVG
 LD A,Temp2  ;if Temp2=0 then first reading
 JRNZ DIDTAVG1 ;skip init if not 1 st reading
 LDI Temp2,020h ;initialize Temp2 to 32
DIDTAVG1
 LD A,FBVTotLo ;
 ADD A,CurVolt ;add current voltage to total
 JRNC DIDTAVG2 ;don′t inc high byts if no carry
 INC FBVTotHi ;inc high byte
DIDTAVG2
 LD FBVTotLo,A ;update total
 DEC Temp2 ;update Temp2
 JRZ DIDTAVG3 ;compute avg
 JP DIDTAVGX ;exit to Main
DIDTAVG3
 LDI Temp2,003h ;prepare to shift 3 times
DIDTAVG6
 LD A,FBVTotHi ;load high byte of total into accumulator
 SLA A ;shift accumulator left
 LD FBVTotHi,A ;update high byte of total
 LD A,FBVTotLo ;load low byte of total into accumulator
 SLA A ;shift accumulator
 LD FBVTotLo,A ;update low byte of total
 JRNC DIDTAVG4 ;msb was zero,skip next line
 INC FBVTotHi ;
DIDTAVG4
 DEC Temp2 ;dec loop counter
 JRZ DIDTAVG5 ;ifzero,finish average
 JP DIDTAVG6 ;not zero,shifi again
DIDTAVG5
 LD A,FBVTotHi ;store average in FreshBV
 LD FreshBV,A
 CLR FBVTotHi
 CLR FBVTotLo
 JRS 7,FreshBV,DA7 ;skip ahead if>8.5V
 RES Hi6V,Flags3 ;clear Hi6V flag
 JP DIDTAVGX ;and skip to end of routine
DA7
 SET Hi6V,Flags3 ;set Hi6V flag
DIDTAVGX
 JP MAIN
;*****************************************************************************
;*This is where the sequence states are defined.The number of a given  *
;*sequence state has no relevance to the order in which it is actually  *
;*executed.Any given state can give control to any other state.   *
;*****************************************************************************
;*****************************************************************************
;*               BATTERY DETECT                *
;*This is the charger idle state.The program remains here until a battery *
;*is detected.Dectection is determined by finding a positive voltage   *
;*greater than one volt.                               *
;****************************************************************************
SS0
  .IFC EQ DEBUG ;assemble next line only if debugging
 RES SwOff,SwDown ;set to check Type and Rate switches
  .ENDC
;RES Crank,Flags ;clear Crank bit of Flags
 RES Restore,Flags4 ;clear Restore bit of Flags4
 CALL ShutOff ;low & high power,fan,& crank off;min duty
 CALL ShowRate  ;turn on charge rate LED(Slow or Fast)
 CALL ShowType  ;turn on battery type LED(Reg,D/C or Gel)
;CALL ChrgRly ;change E/S relay ifnecessary
 JRS ChMode,Flags2,Ready ;continue routine if in Charger Mode
 CALL CheckBatt ;...otherwise,cheek iftester should show 0′s
 JP SS0EXIT ;...and exit
Ready
 JRR Started,Flags,SS00 ;skip if output hasn′t been on
 RES Started,Flags ;set Flags for charge not started
SS00
 LD A,FreshBV ;check latest average voltage
 JRNZ RvrsBatt ;Is it 0(exactly)?
 CALL ShowRed ;turn on Red LED until battery is detected
 JP SS0EXIT ;...Yes:must be rev.batt,so stop
RvrsBatt
 CPI A,Volts0+1 ;No:otherwise,check if>~0.7V
 JRC Pulse  ;no: try pulsing the output
 JP SS0_1 ;yes: setup for no spark delay
Pulse  ;turn on charger for 1 cycle each second
 LD A,MSecs1 ;pulse once per second
 CPI A,MSINIT ;time to pulse?
 JRZ PulseON  ;yes,goto to pulse code
 RES Power,Flags2 ;otherwse,tell timer to leave charger off
 JP SS0EXIT  ;and keep waiting (until next second starts)
PulseON   ;pulse charger on once per second
 SET Power,Flags2 ;tell PwrCon charger is on
;CALL ShowGreen ;turn on Green LED ***test***
 JP SS0EXIT ;no battery,just exit
SS0_1
 CALL IniTime1 ;set up timer
 LDI Secsl,002h ;adjust for 2 seconds
 LDI Tries,005h ;5 Tries for debounce
 SET 0,CurentSS ;go on to BATTERY DETECT DELAY
SS0EXIT
 JP ExitMain
;***************************************************************************
;*   BATTERY DETECT DELAY   *
;*This state checks that a voltage is present for two seconds.If the *
;*voltage drops below 1 Vdc,the timer is restarted and the ″try″counter *
;*is decremented.If after 5 Tries the voltage has not been above 1 Vdc *
;*for 2 seconds,go back to battery detect.This delay has the effect of *
;*debouncing the leads being connected to the battery. *
;***************************************************************************
SS1
 CALL CheckBatt ;cheek for connected battery
 JRR Batt,Flags2,SS1_2 ;subtract a try ifnot connected
 CALL ShowChgng ;turn Charging LED on
 JRR 2,TicFlag1,SS1EXIT ;go on if time is up,otherwise exit
 LDI OldVolt,000h ;clear OldVolt before entering SS2
 LDI TEMP1,000h ;clear Temp 1 before entering SS2
 INC CurentSS ;go on to start charge
 JP SS1_3 ;set timer for 2 seconds
SS1_2 ;NOTE: Tries set to 5 in SS0
 DEC Tries ;subtract a try
 JRNZ SS1_3 ;try again if not too many Tries
 DEC CurentSS ;...otherwise,go back to idle(state 0)
 JP SS1EXIT ;...and exit routine
SS1_3
 CALL IniTime1 ;reset timer and try again
 LDI Secs1,002h ;adjust for 2 seconds
SS1EXIT
 JP ExitMain
;******************************************************************************
;*  AUTOMATIC CHARGE START   *
;*This state gets the battery voltage and decides how to continue the *
;*the charge.The maximum allowed charge time is also started.*
;******************************************************************************
SS2
;NOTES:OldVolt SET TO 0 IN SS1
;TEMP1 SET TO 0 AT RESET
FASTAVG
 DEC TEMP1 ;decrease Templ one count(starts at 0)
   ;have we counted down to 0?
 JRZ FASTDONE ;yes,jump to FASTDONE
 LD A,TEMP ;no,load previous TEMP value
 ADD A,CurVolt ;add CURVOLT,Did we overflow the counter?
 JRNC OVER ;no,jump to OVER
 INC OldVolt ;yes,bump up the running average
OVER
 LD TEMP,A ;store the latest value in TEMP
 JP SS2EXIT ;exit and go update CurVolt
FASTDONE
 LD A,TEMP ;load previous TEMP value
 ADD A,CurVolt ;Did we overflow the counter one last time?
 JRNC OVER2 ;no,jump to OVER2
 INC OldVolt ;yes,bump up the running average one last time
OVER2
 CALL CheckBatt ;Check to see ifbattery was removed during FastAvg
 JRS Batt,Flags2,SS2_0c ;Still connected-continue
 LDI CurentSS,0 ;not connected-go back to state 0
 JP SS2EXIT ;...and exit State 2
SS2_0c
 LD A,OldVolt ;get OldVolt (initial battery voltage)
 LD BADhi,A ;initialize BADhi to OldVolt
;LD A,Percent ;get updated %
 LD A,DspPcnt ;compare to last % displayed
 JRNZ SS2_GP ;if % previously shown,skip ahead
 CALL GetPercent ;update Percent for initial voltage
 LD A,Percent ;get latest %
 LD DspPcnt,A ;store latest % in Display Percent
 RES Wait0P,Flags2 ;set flag to indicate not waiting
 JP SS2_BP ;skip ahead
SS2_GP
 CPI A,100 ;check for 100%
 JRNZ SS2_BP ;continue State 2 if not 100%
 CALL SetMinOff ;limit output to max 2A current
 JP SS5_Maint ;...otherwise,go to Maintain
SS2_BP
 CALL ShowChgng ;turn Charging LED on
 CALL IniTimel ;initialize timer 1
 LDI Mins1,5 ;set timer 1 for 5 minutes
;LDI Secs1,005h ;set timer 1 for 5 seconds
 LDI CCDcnt,MaxHrs ;set interval counter to MaxHrs
 CLR LastBatt ;clear LastBatt(ensure pass 1 st test)
;SET SOC,Flags4 ;set Start Of Charge flag
 CALL IniTime2 ;initialize timer 2
 LDI Secs2,001h ;set timer for 1 second
 LDI MSecs2,MS500 ;set timer for 500 milliseconds(0.5secs)
 LDI Mins2,006h ;set timer for 5 minutes and 2 seconds
 LDI Hrs2,005h ;set timer for 4 hours,5 minutes & 2 seconds
 JRS Rate,Flags,SS2Fast ;skip ahead ifuot set for Slow
  ;...otherwise,set for Slow charge
 CALL StartSlow ;set OFFSET for Slow rate
 JP SS2_0a ;skip ahead and read voltage
SS2Fast ;set for Fast charge
 LDI OFFSET,OffFast ;set Offset for Fast rate
 JRR Bat6V,Flags2,SS2Fst ;skip ifnot set for 6V mode
 LDI OFFSET,Off6Fst ;...otherwise,adjust OFFSET
SS2Fst
 JRR Rapid,Flags2,SS2Rap ;skip ahead if rate is not Rapid
 CALL SetRmpUp ;prepare to ramp from Fast to Rapid
SS2Rap ;set for Rapid charge rate
 JP SS2_0a ;...otherwise skip ahead and read voltage
SS2_0a
 CALL GetBatt ;get latest voltage & double if 6V mode
 CPI A,Volts09 ;very low battery?
 JRNC SS2_2 ;no,try next limit
SS2_1;Battery<9V
 LDIA,003h ;yes,service it,below 9 VOLT SS
 JP SS2_5
SS2_2;Battery>9V
 CPIA,Volts12 ;low battery state?
 JRNC SS2_4;no,goto SS5
SS2_3;9V<Battery<12V
 LDIA,004h ;yes,service it,below 12 VOLT SS
 JP SS2_5
SS2_4 ;Battery>12V
;JRS Alert,Flags2,SS2EXIT;don′t start charge if Alert sei by Double6V
 LDI A,005h ;normal charge SS
SS2_5
 LD CurentSS,A ;prepare to go to the correct state(3,4 or 5)
 SET Started,Flags ;set Flags for charge started
 CALL TumON ;turn output,Fan,and Charging LED on
 SET Settle,Flags3 ;initial charge voltage settle mode
SS2EXIT
 JP ExitMain
;****************************************************************************
;*               BELOW 9 Volts   *
;*  Battery is extremely discharged and may be bad.Charge for a maximum *
;*of five minutes.If voltage does not come above 9 Volts in this time *
;*period,abort charge.Otherwise,go to below 12 Volts. *
;****************************************************************************
SS3
 CALL ChkRapid ;update Ramp timer,ifnecessary
 JRR SEC,TicFlag2,SS3EXIT;exit if voltage settle time not expired
 RES Settle,Flags3 ;clear settle flag
 CALL IReg  ;regulate current till we get to dV/dt
JRR MIN,TicFlag2,SS3_1 ;check iftime has expired
 CALL SetAbort ;yes,time to abort
 JP SS3EXIT
SS3_1
 CALL BattProg ;check battery voltage for charge progress
 CPI A,Volts09 ;is battery up to 9V?
 JRC SS3EXIT          ;continue state 3 if<9V
 INC CurentSS ;...otherwise,go to state 4
SS3EXIT
 JP ExitMain
;****************************************************************************
;*              BELOW 12 Volts               *
;*  Battery is very low.Allow a maximum of 2 hours for the voltage to  *
;*rise above 12 volts under charge.If voltage does not come up,go to   *
;*abort charge.Otherwise go to normal charge.                   *
;****************************************************************************
SS4
 CALL ChkRapid ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS4EXIT;exit if voltage settle time not expired
 RES Settle,Flags3 ;...otherwise,clear settle flag
 CALL IReg  ;regulate current till we get to dV/dt
 JRR HR,TicFlag2,SS4_1 ;check if time(4 hours)has expired
 CALL SetAbort ;yes,time to abort
 TP SS4EXIT ;exit routine
SS4_1
 CALL BattProg ;check battery voltage for charge progress
 CPI A,Volts12 ;is battery up to 12V?
 JRC SS4EXIT         ;...ifnot,just exit
 INC CurentSS ;...otherwise,go to state 5
SS4EXIT
 JP ExitMain
;****************************************************************************
;*   NORMAL CHARGE   *
;*Program stays here until the voltage reaches 14.2 volts or the maximum *
;*charge time is exceded.If the voltage limit is reached the program *
;*will transfer to:    *
;*A.SSB(dV/dt)if the the battery has been charging more than 5 *
;*  minutes or     *
;*B.SS9(Desulfation)if the OCV was less than 12.2 volts or *
;*C.SS14(Maintain)if the OCV was more than 12.2 volts  *
;*      *
;*If the maximum charge time is exceded the program will abort *
;*          *
;***************************************************************************
SS5
 CALL ShowChgng ;turn Charging LED on
 CALL ChkRapid ;update Ramp timer,ifnecessary
  .IFC EQ DEBUG ;assemble next line only if debugging
 SET SwOff,SwDown ;set to ignore Type and Rate switches
  .ENDC
 JRR SEC,TicFlag2,SS5x ;exit if voltage settle time not expired
 RES Settle,Flags3 ;...otherwise,clear settle flag
 CALL BattProg ;check battery voltage for charge progress
 JRR HR,TicFlag1,SS5_0;skip next line if max time not expired
;NOTE: CurentSS set to ABORT by BattProg.ChkProg
SS5x
 JP SS5EXIT ;exit(and abort)if max time expired
SS5_0
 CPI A,Volts142+1 ;check if over 14.2 volts yet
SS5_1
 JRNC SS5_2 ;yes,check if>5 minutes
 CALL IReg  ;no,regulate current till we get to dV/dt
 JP SS5EXIT ;...and just return
SS5_2
 LD A,CCDcnt ;get CCDcnt(set by BattPRog w/minutes)
 LD Hrs1,A ;set Timer1 hours to CCDcnt
 RES HiPwr,Flags4 ;set for low power mode
 RES RmpInt,Flags3 ;clear flag before moving on
;RES Settle,Flags3 ;clear flag before moving on
 JRS MIN,TioFlag2,SS5_3 ;if>5 min,go to dV/dt
 LD A,OldVolt ;otherwise,check initial voltage
 CALL Double6V ;double Battery voltage if set for 6V
 CPI A,Volts122 ;initial voltage<12.2V?
 JRC SS5_5 ;Yes: then desulfate
 JP SS5_Maint ;No: goto Maintain
SS5_5
 LDI CurentSS,009h ;battery is sulfated
 LDI MaintVolt,Volts16 ;try to hold battery at 16V
 LDI Vref,Volts15 ;and see if it drops to 15V
 CALL IniTime2   ;
 LDI Hrs2,002h ;in less than 2 hours
 SET Restore,Flags4 ;set Restore flag
 JP SS5EXIT ;
SS5_3
 CALL SetMinOff ;min 2A offset value(max current)
 JRR Rate,Flags,SS5_6 ;check for 15A charge rate
 CALL SetMinFst ;min Fast offset value(max current)
SS5_6
 LD A,LowOff ;Load LowOff into A for next step
 LD OldOff,A ;initialize OldOff for di/dt to LowOff
 LDI CurentSS,00Bh ;goto wait for dv/dt trip voltage
 LDI Percent,77 ;set Percent to 77
 CALL IniTime2
 LDI Mins2,13  ;set to 13 minutes for dV/dt
 LD A,BADhi  ;get latest battery voltage
 SUBI A,4  ;prevent match @ 1st dV/dt check
 LD MaintVolt,A  ;store as maintain voltage for di/dt
 LDI Tries,004h  ;initialize dV/dt for 4 Tries(3 intervals)
 JP SS5EXIT  ;
SS5_Maint  ;goto MAINTAIN,battery is already charged???
 CALL Setl00p  ;set Percent to 100
 LDI MaintVolt,Volts132 ;set maintain voltage to 13.2V
;CALL FanOff  ;turn cooling fan off
 JRR BatTypeB,Flags,SS5_7;skip ahead ifnot Gel/AGM
 LDI MaintVolt,Volts135 ;set maintain voltage to 13.5V for Gel &AGM
SS5_7
 LDI CurentSS,00Eh ;Maintain is state 14(0E hex)
 CALL SetON  ;turn cooling fan & output on
 CALL FanOff  ;turn cooling fan off
 CALL SetHiOff  ;MAX offset value->min duty cycle
SS5EXIT
 JP ExitMain
SS6
SS7
;***************************************************************************
;*        SS8-ABORT CHARGE   *
;*      *
;*Turn off all LED′s.Blink TROUBLE LED at half second interval.If*
;*battery becornes disconnected,goto BATTERY DETECT.  *
;*         *
;***************************************************************************
SS8
 SET Alert,Flags2  ;set Alert flag
;CALL ShutOff  ;low & high power,fan,& crank off;min duty
 CALL SetOff  ;turn off power and set for min duty
;CALL ChrgRly  ;chauge E/S relay if necessary
 CALL BlinkAlert  ;blink red LED
 JRS BurnIn,Flags3,SS8X ;don′t check for battery if Burn-In
 CALL Check0V  ;check for disconnected battery
 JRS Batt,Flags2,SS8X ;if connected,just exit
 RES Alert,Flags2  ;...otherwise,end abort routine
SS8rst
 JP MAIN2  ;re-initialize
SS8X
 JP ExitMain
;***************************************************************************
;*            SS9-DESULFATION   *
;*Desulfation Mode is entered ifthe initial battery voltage is less *
;*than 12.2 volts and the voltage reaches 14.0 volts within five *
;*minutes.         *
;*        *
;*The charger tries to hold the voltage at 16.0 volts.As the battery *
;*starts to conduct,the voltage will fall.If the voltage reaches 14.0*
;*in a reasonable time limit(10 hours),we will transition to the *
;*normal charging sequence(SS5).If the voltage doesn′t fall to 14.0 *
;*volts we will transition to the ABORT sequence state(SS8).  *
;***************************************************************************
SS9
 LDI Percent,15 ;set to 15%
 CALL BlnkChrg  ;blink Charging LED
 CALL CheckBatt  ;check for connected battery
 JRR Batt,Flags2,SS8rst ;re-initialize if not connected
 CALL VoltReg
 JRR SEC,TicFlag2,SS9X ;wait 1 minute
 JRR HR,TicFlag2,SS9_1 ;maximum time out?(1 or 2 hours)
 DEC CurentSS  ;ABORT state
SS9exit
 JP SS9X  ;done
SS9_1
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CP A,Vref  ;are we there?
 JRNC SS9exit  ;if not,then exit
 DEC Vref  ;1 count is 0.0667 volts
 DEC Vref  ;reduce Vref by 0.133 volts
 LD A,Vref  ;see if batt is desulfated yet
 CPI A,Voltsl4  ;is Vref<14.0 Volts?
 JRC SS9_2  ;yes:skip next line
 JP SS9_3  ;no:try another hour
SS9_2
 LDI CurentSS,005h ;prepare to go to normal charge
 RES Restore,Flags4 ;about to finish Restore mode
 LD A,Vmax  ;set MaintVolt to Vmax
 LD MaintVolt,A ;maintain voltage for state 5
 CALL IniTime2  ;initialize timer 2
 LDI Secs2,002h ;set timer for 2 seconds(voltage settle time)
 JP SS9X  ;
SS9_3
 CALL IniTime2  ;reset timer
 LDI Hrs2,001h  ;set max time for 1 hour
SS9X
 JP ExitMain
SS10
 ;**************************************************************************
 ;*    dV/dt MONITOR    *
 ;*  This state is looking for one of three conditions:   *
 ;*1.Maximum time is exceded-set for check battery and turn off charger.*
 ;*2.No change in dV/dt for 45 minutes-battery is about 80% charged.*
 ;*3.MAX voltage is reached-GOTO dI/dt.    *
 ;*     *
 ;**************************************************************************
SS11
 JRR HR,TicFlag1,SS11_1;If not max time out,goto SS11_1
 CALL SetAbort  ;otherwise,go to abort
 JP SS11X
SS11_1
 CALL ShowChgng  ;light Charging LED
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CP A,Vmax  ;is batt voltage<MAX voltage?
 JRC SS11_2  ;yes:continue loop
 SET HiEnd,Flags3  ;no:set to boost during D/C EndCharge
 JP SS11_6  ;...and prepare to GOTO dI/dt
SS11_2
 JRR MIN,TicFlag2,SS11X ;exit if not time for dv/dt test
 LD A,Percent  ;get Percent
 CPI A,84  ;is Percent<84?
 JRNC SS11_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_3
 LD A,BADhi  ;get battery voltage
 DEC A  ;limit for 6V batteries is 1 count
 JRS Bat6V,Flags2,SS11_3a;leave limit at 1 for 6V batteries
 DEC A  ;limit for 12V batteries is 2 counts
SS11_3a
 CP A,MaintVolt ;test for upper limit change
 JRC SS11_4  ;less than 1 count up,test down change
 JP SS11_7  ;otherwise,skip ahead & update MaintVolt
SS11_4
 DEC Tries  ;decrement counter
 JRZ SS11_6  ;a1l done,GOTO dI/dt
 LD A,Percent  ;get Percent
 CPI A,87  ;is Percent<88?
 JRNC SS11_5  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_5
 JP SS11_8  ;no,reload timer
SS11_6
 INC CurentSS  ;GOTO dI/dt next
 LDI Percent,88 ;set Percent to 88-NOTE must always be even
 JRS HiEnd,Flags3,MutMx ;skip ahead if Vmax reached
 CALL GetBatt  ;get latest voltage & double if 6V mode
 LD MaintVolt,A ;save BADhi as maintain voltage
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
MntMx
 LD A,Vmax  ;otherwise,set MaintVolt to Vmax
 LD MaintVolt,A ;MaintVolt used for di/dt
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
SS11_7  ;update MaintVolt
 LD ABADhi  ;get current battery voltage
 LD MaintVolt,A ;update MaintVolt for dV/dt & di/dt
SS11_9
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS11_8
 CALL IniTime2  ;initialize timer
 LDI Mins2,009h ;...for 9 minutes
SS11X
 JP ExitMain
;***************************************************************************
;*    di/dt MONITOR     *
;*In di/dt the OFFSET value is adjusted to hold the voltage at the dV/dt *
;*value.The OFFSET value will increase and stabilize.  *
;*  This state is looking for one of two conditions:   *
;*1.Maximum time is exceded-set for check battery and turn off charger.*
;*2.No change in OFFSET value for 39 minutes -current stabilized at a *
;*low value.Battery is about 97% charged.Goto SS13(EndCharge)for *
;*1 hour.       *
;***************************************************************************
SS12
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS12_14  ;...if so,turn on green LED
 CALL ShowYellow ;...otherwise,turn on yellow LED
 JP SS12_15  ;...and skip ahead(leave green off)
SS12_14
 CALL ShowDone  ;turn on charge complete LED
SS12_15
 JRR HR,TicFlag1,SS12_1;maximum time out?
 JRS Alert,Flags2,SS12_0;If 2nd max time out,goto SS12_0
 SET Alert,Flags2  ;If 1st max time,set Alert flag
 CALL IniTime1   ;and reset timer
 LDI Hrs1,004h  ;to alow 4 more hours
SS12_10
 LD A,MaintVolt  ;and get Maintain voltage
 SUBI A,007h  ;then subtract~0.5V
 LD MaintVolt,A ;and update Maintain voltage
 JP SS12EXTT  ;then restart di/dt
SS12_0
 CALL SetAbort  ;go to abort
 RES Alert,Flags2 ;reset Alert flag for Abort timer
 JP SS12EXIT
SS12_1
 JRR MIN,TicFlag2,SS12EXTT ;time for dI/dt test?
 LD A,Percent  ;get Percent
 CPI A,100  ;is Percent<100?
 JRNC SS12_2  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 LD A,Percent  ;get percent
 CPI A,100  ;Is percent=100?
 JRZ SS12_2  ;YES,don′t increase anymore
 INC Percent  ;No,increase by 2
SS12_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC SS12_13  ;if so,finish di/dt
 DEC A  ;ensure carry if equal
 CP A,OldOff  ;test for lower limit change
 JRC SS12_4  ;offset within 1,finish di/dt
 JP SS12_7  ;offset too high,try again
SS12_13
 JP SS12_6
SS12_4
 DEC Tries  ;decrement counter
 JRZ SS12_13  ;if 0,then prepare for EndCharge(SS13)
;JRNZ SS12_5  ;Are we done?
;JP SS12_6  ;yes,all done,clean up and exit
;SS12_5   ;no,continue
 LD A,Percent  ;get Percent
 CPI A,99  ;is Percent<100
 JRNC SS12_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 JP SS12_8  ;reload timer & check again later
SS12_3
 LD A,Tries  ;get the current tries
 CPI A,03   ;Is tries less than 3?
 JRNC SS12_11  ;No,just exit
 CALL Set100p  ;Yes,show 100% and done
SS12_11
 JP SS12_8  ;reload timer & check again later
SS12_6
 INC CurentSS  ;GOTO EndCharge(SS13)
 CALL IniTime2  ;initialize Timer2
 LDI Hrs2,001h  ;charge for 1 more hour(EndCharge)
 LDI Mins2,00Fh ;charge for only 15 minutes(EndCharge)
 JRR BatTypeA,Flags,SS12_9 ;skip if not Deep Cycle(Voyager)
 JRR HiEnd,Flags3,SS12_9;skip if not using higher EndCharge voltage
 INC Hrs2   ;otherwise,change Hrs2 from 1 to 2
 LD A,MaintVolt  ;also,store MaintVolt in A
 ADDI A,04h  ;increase A by 4 counts~0.267V
 LD MaintVolt,A ;store updated value in MaintVolt
SS12_9
 JP SS12EXIT
SS12_7
 LD A,OFFSET  ;set new base offset
 LD OldOff,A  ;save in OldOff
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS12_8
 CALL IniTime2  ;initialize Timer 2
 LDI Mins2,009h ;set Timer 2 for 9 minutes
 LD A,OFFSET  ;Get current offset
 CP A,LowOff  ;Is the offset=MinOff?
 JRNZ SS12EXIT  ;NO,just exit
 RES HiEnd,Flags3  ;YES,don′t boost voltage for EndCharge
 JP SS12_10  ;Current not falling,reduce voltage by 1/2V
SS12EXIT
 JP ExitMain
;***************************************************************************
;*         ENDCHARGE     *
;*Charge for desired hours after dI/dt at dV/dt voltage.   *
;***************************************************************************
SS13
 CALL Set100p  ;set Percent to 100
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRNZ SS13_2  ;...if so,turn on green LED
 CALL ShowDone  ;turn on charge complete LED
SS13_2
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRZ SS13_1  ;exit ifmax OFFSET reached
 JRR HR,TicFlag2,SS13EXIT ;exit if 1 hour time not up
SS13_1
 JP SS5 Maint  ;...otherwise,GOTO MAINTAIN
SS13EXIT
 JP ExitMain
;***************************************************************************
;*    MAINTAIN     *
;*Battery has reached full charge.Stay here and maintain battery *
;*at 13.2 volts until battery is disconnected.    *
;*         *
;***************************************************************************
SS14
 CALL Set100p  ;set Percent to 100
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS14_1  ;...if so,turn on green LED
 CALL ShowYellow ;...otherwise,turn on yellow LED
 JP SS14_2  ;...and skip ahead(leave green off)
SS14_1
 CALL ShowDone  ;turn on charge complete LED
 .IFC EQ DEBUG  ;assemble next line only if debugging
 RES SwOff,SwDown ;set to check Type and Rate switches
 .ENDC
SS14_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC SS14_3  ;...if so,shut off fan
 JRS Bat6V,Flags2,SS14_5 ;skip ahead if 6V mode
 CPI A,HiOff-4  ;check for sustained output
 JP SS14_7
SS14_5
 CPI A,HiOff6-4 ;check for sustained output
SS14_7
 JRNC SS14_4  ;...if not,leave fan off
SS14_6
 CALL FanON  ;...otherwise,turn fan on
 JP SS14_4  ;...and skip ahead
SS14_3
 CALL FanOff  ;turn cooling fan off
SS14_4
 CALL CheckBatt  ;check for battery
 JRS Batt,Flags2,SS 14EXIT;...connected:continue
 JP MAIN2  ;...disconnected:start over from state 0
SS14EXIT
 JP ExitMain
;***************************************************************************
;*    SS15MANUAL     *
;*Regulate current.No voltage limit.Reset after 1 hour.  *
;***************************************************************************
SS15
 JRR Power,Flags2,SS15_2 ;power off indicates completed Burn-In
 CALL ShowRate  ;turn on the 2A or 15A LED
;NOTE:output already on,but TurnON saves code space
 CALL TurnON  ;turn output,Fan,and Charging LED on
 .IFC EQ AdjOff;assemble next line only if debugging
 JRR BurnIn,Flags3,SS15OK;don′t regulate if not Burn-in mode
 .ENDC
 CALL IReg  ;regulate current at selected rate
;CALL Check17v  ;check for disconnected battery
;JRNZ SS15OK  ;if<>17V,then continue
;LDI CurentSS,ABORT  ;...otherwise,Abort
;RES Manual,Flags3  ;...end Manual Mode
;JP SS15EXIT  ;...and skip rest of State 15
SS15OK
 JRS BurnIn,Flags3,SS15BI;skip ahead if Burn-in mode
 .IFC NE AdjOff ;assemble next lines only if not debugging
 RES MtrScale,Flags ;set for Alternator % LED off
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
 CALL ShowMeter  ;update meter LEDs
.ENDC
 JP SS15rmp  ;jump to ramp check
SS15BI
 JRR MIN,TicFlag2,SS15b ;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 CALL IniTime2  ;reset Timer2
 LDI Mins2,1  ;set timer for counter interval(1 minute)
SS15b
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL ShowNum  ;display count on digital LED
 CALL MeterOff  ;turn off all meter mode LED′s
SS15rmp
 .IFC EQ AdjOff ;assemble next lines only if debugging
 CALL CheckSw ;check if switch is being pressed
 CALL GetMeter  ;update meter LEDs
 JP SS15_1  ;skip next three lines
 .ENDC
 CALL ShowData  ;update display
 JRR Rapid,Flags2,SS15_1 ;don′t ramp if Rapid is not set
 CALL ChkRapid  ;update Ramp timer,if necessary
SS15_1
 JRR HR,TicFlag1,SS15EXIT;continue if not max manual charge time
 JRS BurnIn,Flags3,SS15_2;skip ahead if finished Burn-In
 JP RESET  ;...otherwise,reset
SS15_2
 CALL DigitsOff  ;turn off 3-digit LED
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL SetOff  ;reset Power & Cranking flags;set min.duty
SS15EXIT
 JP ExitMain
;***************************************************************************
;*    BOOST MODE     *
;*First set the charger offset value for 2 amp charging.Next,wait *
;*for the voltage to stabilize.Then wait for the voltage to drop *
;*about two volts.When the voltage drops,go full on for 5 seconds.*
;*After five seconds of cranking,wait for 4 minutes and start over.*
;*         *
;*Comment the CALL and the following two LDI′s for test.Also load offset *
;*with PHASE15 instead of PHAZBOST    *
;***************************************************************************
SS16
 .IFC EQ DEBUG ;assemble next line only if debugging
 RES SwOff,SwDown ;set to check Type and Rate switches
 .ENDC
 CALL VoltMtr  ;set for volt meter and update display
 CALL CheckBatt  ;make sure batt is>1.6V
 JRR Batt,Flags2,SS16_1 ;skip ahead if not connected
 JRS SEC,TicFlag2,BattOK ;skip if>2 seconds since Boost selected
 JP SS16Exit  ;if<2 seconds,then stay off
SS16_1
 CALL TurnOff  ;low & high power and fan off,min duty
 CALL ShowRed  ;turn on Alert LED
 JP SS16Exit  ;if batt<1.6V,then stay off
BattOK
 CALL ShowCrank  ;turn ON Crank LED & turn Alert LED off
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL SetHiOff  ;set for min duty cycle
 SET Started,Flags  ;set Flags for charge started
 CALL IniTime2  ;reset timer 2
 LDI MSecs2,MS200 ;set Timer2 for 200ms
 INC CurentSS  ;set state to 17
SS16Exit
 JP ExitMain  ;goto end of loop
;***************************************************************************
;*    DELAY FOR VOLT READING    *
;***************************************************************************
SS17
 JRS MSEC,TicFlag2,SS17_1;Is 200ms up?
 JP SS17EXIT  ;no,just return
SS17_1
 CALL GetMeter  ;update display
 CALL Check0V  ;make sure batt is connected
 JRS Batt,Flags2,SS17_2  ;skip ahead if connected
 JP MAIN2  ;disconnected,so start over
SS17_2
 SUBIA,010h  ;adjust for a one volt drop
 LD OldVolt,A  ;save it
 LDI MaintVolt,Volts142 ;try to hold battery at 14.2(or 7.1)V
 CALL SetMinFst  ;min Fast offset value(max current)
 INC CurentSS  ;wait for crank
 CALL IniTime2  ;initialize Timer 2
 LDI Mins2,15  ;set Timer 2 for 15 minutes
SS17EXIT
 JP ExitMain
;***************************************************************************
;*    WAIT FOR CRANK    *
;***************************************************************************
SS18
 JRR MIN,TicFlag2,SS18_0 ;wait for crank only 15 minutes
 JP MAIN2  ;then start re-initialize
SS18_0
 CALL GetMeter  ;update display
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,FreshBV  ;get current reading
 SUBI A,010h  ;adjust for a one volt drop
 CPA,OldVolt  ;has voltage increased?
 JRC SS18_2  ;if not,then skip ahead
 LD OldVolt,A  ;update OldVolt
SS18x
 JP SS18EXIT  ;and exit routine
SS18_2
 LD A,FreshBV  ;get current reading
 CP A,OldVolt  ;1V drop might indicate cranking
 JRNC SS18x  ;just exit if no drop
 ADDI A,0Ch  ;store FreshBV+0.8V in A
 CP A,BADhi  ;is latest average>FreshBV+0.8V?
 JRNC SS18EXIT  ;if BADhi>FreshBV+0.8V,start cranking
SS18_1
 SET Power,Flags2  ;turn output on
 INC CurentSS  ;time the cranking
 SET Crnkng,Flags4 ;indicate cranking started
 CALL IniTime2
 LDI Secs2,CrankON ;crank for CrankON(5)seconds
SS18EXIT
 JP ExitMain
;***************************************************************************
;*    CRANK TIMING    *
;*Allow cranking for five seconds and then go back to charging. *
;***************************************************************************
SS19
 LD A,Secs2  ;get remaining crank seconds
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
 JRR SEC,TicFlag2,SS19EXIT;if cranking not finished,then exit
 RES SCRs,DRBbuf ;turn off SCR′s(in buffer)
 CALL UpdatePB  ;update port B from buffer
 CAll ResetStatus  ;turn off Charging LED
 RES Crnkng,Flags4  ;indicate finished cranking
 RES Power,Flags2  ;tell timer to leave charger off
 INC CurentSS  ;just wait for time to expire
 CALL SetOff  ;turn off power and set for min duty
 SET CrankWait,Flags ;indicates crank cool-down time
 CALL IniTime1  ;reset Timer1
 LDI Secs1,CCDint ;set timer for counter interval(seconds)
 LDI CCDcnt,CrankOff ;set crank cool down counter to CrankOff secs
SS19EXIT
 JP ExitMain
;***************************************************************************
;*              INTER-CRANK DELAY                  *
;*Stay here until the 4 minute timer has expired then go back to BOOST *
;*if switch still engaged,else goto 2A auto(default)   *
;***************************************************************************
SS20
CALL FanON  ;turn cooling fan ON
JRR SEC,TicFlag1,SS20_0 ;skip ahead if not time to update counter
DEC CCDcnt  ;decrease display count by 1
 JRNZ SS20_1  ;finish state 20 if count down to 0
 RES CrankWait,Flags ;reset CrankWait bit of Flags
 LDI CurentSS,010h ;set state to 16 to Crank again
 SET SEC,TicFlag2 ;tell State 16 that E/S already running
 JP SS20EXIT  ;and exit State 20
SS20_1
 CALL IniTime1  ;reset Timer1
 LDI Secs1,CCDint ;set timer for counter interval(seconds)
SS20_0
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
;RES Rmpng,Flags3  ;clear flag for CheckBatt
 RES Settle,Flags3  ;clear flag for CheckBatt
 CALL BlinkCrank  ;blink the Crank LED
SS20EXIT
 JP ExitMain
;***************************************************************************
;*    SUB ROUTINES START HERE    *
;***************************************************************************
;***************************************************************************
;*Initialize state(Slow charge,Regular batt,State 0)  *
;*         *
;***************************************************************************
InitState
 CLR Flags  ;0 is default for all bits
 CLR Flags2  ;0 is default for all bits
 CLR Flags3  ;set to indicate no Rapid to Fast change
 CLR TEMP1  ;initialize
 CLR CCDcnt  ;initialize
 RES Disable,DRBbuf ;enable output
;SET ChMode,Flags2 ;set for Charger Mode(charger mode)
;RES ESrly,DRBbuf ;set E/S relay for charge(not boost)
 LDI OFFSET,HiOff-1 ;set for mimimum output current
 LDI LowOff,OffRap ;limit max rate to full 60A offset
 LDI SwData,01111101b ;Initialize switch LEDs for 2A,Reg
 LDI Vmax,Volts155  ;Vmax for Regular batteries
 LDI VltCnt,001h ;initialize VltCnt to 1
 LDI VRcnt,001h ;initialize VRcnt to 1
 LDI PcntL,001h ;initialize PcntL to 1
 LDI PcntH,001h ;initialize PcntH to 1
 LDI CurentSS,000h  ;set charger state to 0
 LDI Secs1,SecInit ;restart TIMER1 second counter
 LDI Secs2,SecInit ;restart TIMER2 second counter
 RET
;***************************************************************************
;*    Reset Watchdog Register    *
;*This routine simiply resets the Watchdog register.RstWDR was *
;*only to save program space(LDI require 3 bytes,CALL requires only 2).*
;*         *
;***************************************************************************
RstWDR
 LDI WDR,0FEH ;reset watch dog timer
 RET
;***************************************************************************
;*    Set Abort State     *
;*This routine simiply sets CurentSS to ABORT so that the code will go *
;*to the Abort state after the next NMI.SetAbort was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
SetAbort
 LDI CurentSS,ABORT ;set current state to Abort
 RET
;***************************************************************************
;*    Set 100 Percent     *
;*This routine simiply sets Percent to 100.Set100p was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
Set100p
 LDI Percent,100 ;set Percent to 100
 RET
;***************************************************************************
;*    Clear Percent     *
;*This routine simiply sets Percent and DspPcnt to 0.ClrPcnt was  *
;*written only to save program space(CLR require 3 bytes,CALL requires *
;*only 2).Set0p is the second half of ClrPcnt.    *
;*        *
;*    Set 0 Percent      *
;*This routine simiply sets Percent to 0.Set0p was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
ClrPcnt
 CLR DspPcnt ;set Display Percent to 0
Set0p
 LDI Percent,0  ;set Percent to 0
 RET
;***************************************************************************
;*    Update Port A      *
;*This routine updates Port A with the contents of the DRA buffer.*
;*UpdatePA was written only to save program space.   *
;*       *
;***************************************************************************
UpdatePA
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A  ;update port from Accumulator
 RET
;***************************************************************************
;*    Update Port B      *
;*This routine updates Port B with the contents of the DRB buffer.*
;*UpdatePB was written only to save program space.   *
;*        *
;***************************************************************************
UpdatePB
 LD A,DRBbuf  ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
 RET
;***************************************************************************
;*    Update Port B Options    *
;*This routine updates the Port B options with the contents of the ORB *
;*buffer.UpdateORB was written only to save program space.   *
;*        *
;***************************************************************************
UpdateORB
 LD A,ORBbuf ;update Accumulator from buffer
 LD ORB,A  ;update options register from Accumulator
 RET
;***************************************************************************
;*    Wait a Fifth Second    *
;*This routine causes the program to wait one fifth second by waiting *
;*for 24 interrupts.       *
;***************************************************************************
FifthSecond
 CALL IniTime1
 LDI MSecs1,MS200 ;set timer for 1/5 second
WFS_1
 WAIT
 CALL RstWDR  ;reset watch dog timer
 JRR MSEC,TicFlag1,WFS_1 ;wait until timer goes to 0
 RET
;***************************************************************************
;*    Set Ramp Up     *
;*This routine sets the parameters necessary to change the duty from the *
;*fast rate to the rapid rate.It is used before Burn-In and Automatic  *
;*Rapid charge.           *
;*        *
;*    Set Ramp       *
;*This routine sets the parameters necessary to change the duty between  *
;*the fast and rapid rates.It is actually the last part of SetRmpUp.  *
;*          *
;***************************************************************************
SetRmpUp
 LDI RmpCnt,RCinitF ;set counter for Fast
 RES HiPwr,Flags4 ;set for low power
SetRamp
 LDI TEMP,RIinit ;120 NMI interrupts yields 1.5 seconds
 SET RmpInt,Flags3 ;counting 1st of two 180 cycle periods
 RET
;***************************************************************************
;*    CHECK RAPID      *
;*This routine determines whether to reduce or increase the charge rate *
;*from Rapid to Fast or vica versa,if necessary.It sets the flags *
;*used by RampOS appropriately.     *
;*        *
;***************************************************************************
ChkRapid
 JRR Rapid,Flags2,ChkRapX ;if not Rapid charge rate,then exit
 DEC TEMP   ;otherwise,update ramp timer
 JRNZ ChekRapX   ;exit if not time to update count
 LDI TEMP,RIinit  ;count 180 more cycles(1.5 sec)
 JRR RmpInt,Flags3,RmpCtr ;skip ahead if just counted 1st half
 RES RmpInt,Flags3  ;...otherwise,start counting 2nd half
ChekRapX
 JP ChkRapX  ;...and exit
RmpCtr
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 DEC RmpCnt  ;check if time to ramp
 JRNZ ChekRapX  ;exit if not time to ramp
 JRR HiPwr,Flags4,StRmpUp ;skip ahead if changing to higher rate
 RES HiPwr,Flags4  ;set for not HiPwr(change to lower rate)
 LDI RmpCnt,RCinitF  ;...otherwise,set for Fast rate
;LDI OFFSET,OffRamp  ;set for between Fast & Rapid rates
 JP ChkRapR
StRmpUp
 SET HiPwr,Flags4  ;set flags for>Fast rate
 LDI RmpCnt,RCinitR  ;set counter for Rapid rate
ChkRapR
 LDI OFFSET,OffRamp  ;set for between Fast & Rapid rates
ChkRapX
 RET
;***************************************************************************
;*    SHOW NUMBER     *
;*This routine determines what three digits to display on the digital LED *
;*to represent the number stored in LEDNum.The three digits will be  *
;*displayed next time the ShowData routine is called.   *
;*        *
;***************************************************************************
ShowNum
 CLR Index  ;initialize LUT Index to 0
 CALL DigiOff  ;set registers for all segments off
 LD A,LEDnum  ;store LEDnum in accumulator
 CPI A,10   ;check for single digit number
 JRNC ChkMaxNum  ;...if not,check for max number
 JP Next001  ;...otherwise skip to 3rd digit
ChkMaxNum
 .IFC NE AdjOff ;assemble next lines only if not debugging
 CPI A,199  ;check for highest displayable number
 JRC Check100  ;if less,check value
 LDI A,199  ;...otherwise,display 199
 .ENDC
Check100
 CPI A,100  ;check whether to show most significant 1
 JRC Check010  ;if not,check for 10
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,100  ;...and subtract 100 from accumulator
 .IFC EQ AdjOff ;assemble next lines only if debugging
 JP Check100  ;check whether number was greater than 200
 .ENDC
Check010
 CPIA,10  ;check if<10
 JRC Check001  ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,10  ;...and subtract 10 from Acumulator
 JP Check010  ;...and check for next higher value
Check001
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD ATemp,A  ;save Accumulator
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for second digit
 LD DigiDat2,A ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
Next001
 LDI DRWR,Digits00x.w ;look up table(LUT)for 3rd digit
 LDI X,Digits00x.d ;initialize LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1  ;...set bits in A for segments
 LD DigiDat1,A ;...store A into DigiDat1
ShowNumX
 RET
;***************************************************************************
;*    GET VOLT DIGITS     *
;*This routine determines what three digits to display on the digital *
;*LED to represent the battery voltage(BADhi).
;*        *
;***************************************************************************
GetVolts
 DEC VltCnt  ;decrement interval counter
 JRZ NewVolt  ;if 0,ready to update display
 JP GetVexit  ;...otherwise,just exit
NewVolt
 LDI VltCnt,MS500 ;re-initialize interval counter
 JRR ChMode,Flags2,GVT ;if Tester mode,use FreshBV
 LD A,BADhi  ;get latest avg batt voltage
 JP GV10
GVT
 LD A,FreshBV  ;Get latest average battery voltage
GV10
 CALL DigiOff  ;set registers for all segments off
 CLR Index  ;initialize LUT Index to 0
 CPI A,MaxVolts  ;check for max volt reading
 JRC GV17   ;skip ahead if less than max
 LDI DigiDat1,DigiMV1 ;set for digit 1 of max volt display
 LDI DigiDat2,DigiMV2 ;set for digit 2 of max volt display
 JP GetVexit  ;exit GetVolts
GV17
 CPI A,Volts10  ;check for 10V
 JRC Check1V  ;if not 10V then skip ahead
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,Volts10  ;...and subtract 10V from accumulator
Check1V
 CPI A,Volts01  ;check if>1.0V
 JRC Check01V  ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,Volts01  ;...and subtract 1.0V from accumulator
 JP Check1V  ;...and check for next higher value
Check01V
 LD ATemp,A  ;save Accumulator
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A   ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for bottom segments
 LD DigiDat2,A  ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
ShowV001
 LDI DRWR,Digits0Vx.w ;look up table(LUT)for 3rd volts digit
 LDI X,Digits0Vx.d ;initialize LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A   ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1 ;...set bits in A for bottom segments
 LD DigiDat1,A ;...store A into DigiDat1
 RES Decimal,DigiDat1 ;turn ON decimal point
GetVexit
 RET
;***************************************************************************
;*    VoltMeter      *
;*This routine sets the display to show volts,then calls ShowMeter and  *
;*ShowData to update the display with the current battery voltage.   *
;*       *
;*    GetMeter      *
;*This routine calls ShowMeter and ShowData to display the latest  *
;*voltage or percentage(determined by MtrScale & MtrUnits)on the  *
;*3-digit LED display.GetMeter is the last section of VoltMtr.  *
;*         *
;***************************************************************************
VoltMtr
 RES MtrScale,Flags ;set for Alternator % LED off
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
GetMeter
 CALL ShowMeter  ;update meter LEDs
 CALL ShowData  ;update display
RET
;***************************************************************************
;*    GET PERCENT     *
;*This routine determines what value to use for the percentage of  *
;*charge before the charge state has reached the dv/dt state.The *
;*percent is calculated by reading the battery voltage(BADhi)and  *
;*performing the following calculations:      *
;* As Tester         *
;* 1.0V<BADhi<11.6V DC=>Percent=(BADhi/16)+1  *
;* 11.61V<BADhi<12.8VDC=>Percent=(BADhi-175)*5+15 *
;* 12.80V<BADhi=>Percent=100   *
;* As Charger     *
;* 1Volt<BADhi<12Volts=>(BADhi/4)+15=Percent  *
;* 12Volts<BADhi<dv/dt=>(BADhi/2)-30=Percent  *
;***************************************************************************
GetPercent
 JRR ChMode,Flags2,TstrBP;jump to Tester% if not charging
 JRS Restore,Flags4,GPend;don′t get % in Restore mode
 LD A,CurentSS ;get current program state
 CPI A,11  ;has charging reached dV/dt?
 JRC CalcPrcnt ;...if not,calculate percentage
GPend
 JP GetPctEnd ;...otherwise,do nothing
CalcPrcnt
 LD A,Percent ;get Percent
 CPI A,76  ;check for highest calculated %
 JRNC GPend ;exit if already there
 JRS HiPwr,Flags4,GPend;exit if in High Power mode
 LD A,R mpCnt ;get Ramp interval counter
;NOTE:RmpCnt will be 0 if not set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC GPend ;don′t update % until end of low power interval
 CALL GetBatt ;get latest voltage & double if 6V mode
 CPI A,Volts12 ;is the battery voltage less than 12V?
 JRNC Formula2 ;...No,goto Formula2
 CPI A,Volts01  ;Is battery>1
 JRNC GPform1 ;...if so,skip next line
 JP GPzero ;...if not,set for zero %
GPform1
 CALL Divide4 ;...Yes,use first formula
 ADDI A,15  ;Add 15 and...
 JP GetPctExit ;...store into A
Formula2
 CALL Divide2 ;Divide by 2 and
 SUBI A,30  ;...subtract 30
 JP GetPctExit ;skip ahead and finish routine
TstrBP
 LD A,FreshBV ;get latest(avg)battery voltage
 CALL Double6V ;double Battery voltage if set for 6V
 CPI A,Volts128 ;Is battery>12.8V?
 JRC Tstr100  ;...if not,skip ahead
 CALL Set100p ;...otherwise,Percent=100
 JP GetPctEnd ;...and end routine
Tstr100
 CPI A,BattMin ;Is battery>BattMin
 JRNC TstrBPhi ;...if so,jump ahead
 CPI A,Volts01 ;Is battery >1
 JRNC TstrBPmed ;...if so,jump ahead
GPzero
 CALL Set0p ;...otherwise set Percent to 0
 JP GetPctEnd ;...and end routine
TstrBPhi
 SUBI A,BattMin ;subtract minimum high voltage
 CALL ATimes5 ;multiply by 5
 ADDI A,15  ;add 15
 JP GetPctExit ;...store into A
TstrBPmed
 SUBI A,15  ;A=battery-15
 CALL Divide4 ;A=(battery-15)/4
 CALL Divide4 ;A=(battery-15)/16
 INC A  ;A=(battery-15)/16+1
GetPctExit
 LD Percent,A ;store into Percent
GetPctEnd
 RET
;***************************************************************************
;*   UPDATE BATTERY PERCENT    *
;* This routine controls how the battery percentage displayed is updated. *
;* UpdateBP ensures that under normal circumstances,the battery % dis- *
;* played is updated according to the following two rules.   *
;* 1.The % displayed doesn′t change by more than 1% at a time *
;* 2.The % displayed is not updated twice in<PCint seconds *
;* There are a few exceptions.     *
;* 1.The % displayed can jump up more than 1 if it was 0   *
;* 2.The % displayed will drop to 0 immediately for disconnected batt. *
;* 3.The % displayed can change by more than 1 if the scale** changes *
;*          *
;***Scale refers to the % scale,which is either battery or alternator *
;*          *
;***************************************************************************
UpdateBP
 LD A,Percent  ;check whether % is 0
 JRNZ UBP0   ;...if not,wait for update interval
 JP UBPfinish  ;...otherwise finish routine
UBP0
 LD A,DspPcnt  ;get last % displayed
 JRZ UBP00  ;continue if 0%
 JP UBP1   ;skip ahead if not 0%
UBP00
 JRS MtrScale,Flags,UBP1;also skip ahead if Alternator %
 JRS Wait0P,Flags2,UBPz ;skip ahead if Wait0P flag already set
 SET Wait0P,Flags2  ;...otherwise,set flag to wait
 CALL IniTime2  ;initialize Timer2
 LDI Secs2,3  ;set Timer2 for 3 seconds
 JRR ChMode,Flags2,UBPz ;skip ahead ifin tester mode
 LDI Secs2,5  ;set Timer2 for 5 seconds in charger mode
UBPz
 JRR SEC,TicFlag2,UBPx ;skip ahead if still waiting
UBP0a
 RES Wait0P,Flags2  ;set flag to indicate not waiting
 LD A,Percent  ;...otherwise,get new %
 JP UBPfinish  ;...and don′t wait to display it
UBPx
 JP UBPexit  ;...and just exit
UBP1
 DEC PcntL  ;decrement % interrupt counter
 JRNZ UBPx  ;ifnot 0 then just exit
 LDI PcntL,MSINIT  ;re-initialize % interupt counter
 DEC PcntH  ;decrement interval counter
 JRNZ UBPx  ;if not down to 0,then just exit
 LDI PcntH,PCint  ;re-initialize % interval counter
 LD A,DspPcnt  ;get last % displayed
 JRNZ UBP2  ;skip ahead if not 0%
 LD A,Percent  ;get new %
 JP UBPfinish  ;and finish routine
UBP2
 CP A,Percent  ;compare to newest %
 JRZ UBPexit  ;if equal,do nothing
 JRC IncBP  ;if less,increase display % by 1
 JRS ChMode,Flags2,UBPexit ;don′t decrease % if charging
 DEC A  ;...otherwise,decrease % by 1
 JP UBPfmish  ;...and finish
IncBP
 INC A  ;increase display % by 1
UBPfinish
 LD DspPcnt,A  ;store updated display %
UBPexit
 RET
;***************************************************************************
;*   MeterNum    *
;* This routine calls MeterOff,ShowNum,and ShowData to turn off the *
;* display mode LED′s and display LEDnum on the 3-digit LED display.  *
;*          *
;*   NumData    *
;* This routine calls ShowNum and ShowData to display LEDnum on the *
;* 3-digit LED display.NumData is the last section of MeterNum.  *
;*          *
;***************************************************************************
MeterNum
 CALL MeterOff  ;turn off all meter mode LED′s
NumData
 CALL ShowNum  ;get data to show the number
 CALL ShowData  ;show the number
 RET
;***************************************************************************
;*   SHOW DATA   *
;* This routine updates the digital LED and 6 switch LEDs controlled by *
;* the serial to parallel shift registers.It sends the bits of SwData *
;* and DigiData to the registers bit by bit from LSB to MSB using *
;* SerData.After each bit is sent,ShftClk is toggled to shift the bit *
;* to the next position.After all 24 bits have been sent,LtchClk is *
;* used to update the outputs,which updates the LEDs.  *
;*          *
;***************************************************************************
ShowData
 CALL RstWDR  ;reset watch dog timer
;RES ClrData,DRAbuf ;clear shift register
;CALL UpdatePA  ;update port A from buffer
;SET ClrData,DRAbuf ;prepare to accept data
;CALL UpdatePA  ;update port A from buffer
 LDI BitCnt,008h  ;initialize bit counter to 8
 LDI BytCnt,003h ;initializie byte counter to 3
 LD A,DigiDat1  ;get first 8 bits of digit data
GetBit
 RLC A  ;send MSB of Acumulator to Carry
 JRC SetBit  ;if Carry=1 then data bit is 1
 RES SerData,DRAbuf ;...otherwise set SerData to 0
 JP SendBit  ;skip ahead to SendBit
SetBit
 SET SerData,DRAbuf ;set SerData to 1
SendBit
 LD DataBuf,A  ;store shifted data from A
 CALL UpdatePA  ;update port A from buffer
 RES ShftClk,DRBbuf ;set Shift Clock low
 RES LtchClk,DRBbuf ;set Latch Clock low
 CALL UpdatePB  ;update port B from buffer
 SET ShftClk,DRBbuf ;set Shift Clock high
 CALL UpdatePB  ;update port B from buffer
 DEC BitCnt  ;update bit count
 JRZ NextData  ;if all bits sent then skip ahead
 LD A,DataBuf  ;store shifted data back in A
 JP GetBit  ;otherwise,get next bit
NextData
 DEC BytCnt  ;update byte count
 JRNZ NextByte  ;get next byte is count is not 0
 JP LatchData  ;...otherwise,done sending bits
NextByte
 LDI BitCnt,08h ;set bit count for 8 more bits
 LD A,BytCnt  ;which byte is next?
 CPI A,02h  ;check for 2nd byte is next
 JRZ ScndByte  ;skip ahead if equal
 LD A,SwData  ;get 8 bits of switch LED data
 JP GetBit  ;send bits of second byte
ScndByte
 LD A,DigiDat2  ;get last 8 bits of digit data
 JP GetBit   ;send bits of second byte
LatchData
 SET LtchClk,DRBbuf ;update latches
 CALL UpdatePB  ;update port B from buffer
 RET
;***************************************************************************
;*   Show Meter   *
;* This routine sets the digital LED to show either the current voltage *
;* or last percent based on Flags and CurentSS.During Engine start,it *
;* will count down seconds of either remaining crank time or cool down *
;* time.       *
;***************************************************************************
ShowMeter
 JRS Alert,Flags2,SMeXit ;exit if abort mode
 JRS MtrUnits,Flags,GetPrcnt ;skip ahead and set for %
 CALL GetVolts  ;...otherwise,get volts
 JRS ChMode,Flags2,SM1;skip ahead if not in Tester mode
 CALL ShowStatus ;...otherwise,update Status LEDs
SM1
 JP ShowMtrX  ;...and skip to end or routine
GetPrcnt
 JRR ChMode,Flags2,TstMtr;if in tester mode,get %
 JP ShowPrcnt  ;...otherwise,skip ahead & show %
Show0
 CALL Set0p ;set to show 0%
ShoPer
 JP ShowPrcnt  ;and skip ahead
TstMtr
 LD A,FreshBV  ;get latest Battery voltage
 JRZ Show0  ;if 0V,show 0%
 JRR MtrScale,Flags,ShoPer;show Battery% ifnot set for Alt%
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,AltMin  ;check for<1st LUT value
 JRC Show0  ;if so,show 0%
 CPI A,AltMax  ;check for>last LUT value
 JRC AltVal  ;if not,skip ahead and check LUT
 LDI Percent,199  ;...otherwise,set to max value
 JP ShowPrcnt  ;and skip ahead
AltVal
 LDI DRWR,AltLvls.w ;LUT for alternator %
 LDI X,AltLvls.d ;initialize LUT
 SUBI A,AltMin  ;diffence is index in look up table
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X);store value at X into A
 LD Percent,A.;store value into Percent
ShowPrcnt
 CALL ShowPercent ;otherwise,show percentage
 CALL ShowStatus ;turn on appropriate status LED
ShowMtrX
 CALL ShoMtrMode ;turn on appropriate meter LED
SMeXit
 CALL RstWDR  ;reset watch dog timer
 RET
;***************************************************************************
;*   SHOW METER MODE   *
;* This routine turns on one of the meter units LED′s based on Flags and *
;* Flags2.If the unit is in TesterMode(ChMode=0),the routine will *
;* also light the appropriate status LED based on the voltage at the *
;* clamps.       *
;*          *
;***************************************************************************
ShoMtrMode
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
ShowVolts
 JRS MtrUnits,Flags,ShoPrcnt ;goto ShoPrcnt if set
 RES LEDvolt,DRAbuf  ;turn on Voltage LED
 JP ShowMMX
ShoPrcnt
 JRS MtrScale,Flags,ShowAlt ;goto ShowAlt if set
 RES LEDprcnt,DRAbuf  ;turn on Battery % LED
 JP ShowMMX
ShowAlt
 RES LEDalt,DRAbuf  ;turn on Alternator % LED
ShowMMX
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;* Hold Meter Mode LED(depending on mode)  *
;* This routine turns on the Battery%,Volts DC,or Alternator% LED based *
;* on Flags & Flags2 and keeps that LED on for one fifth second.  *
;***************************************************************************
HoldMtrMd
 CALL ShoMtrMode ;turn on Meter Mode LED
 CALL FifthSecond ;wait one fifth second
RET
;***************************************************************************
;*   SHOW STATUS   *
;* This routine turns on one of the three status LED′s based on the *
;* battery voltage.This routine is for use in the tester mode. *
;*          *
;***************************************************************************
ShowStatus
 JRS ChMode,Flags2,ShoStatX ;exit ifnot Tester mode
 JRR Batt,Flags2,RedStat ;show red LED if no battery
 JRR MtrUnits,Flags,ClrStat ;turn off Status LED′s if volts mode
 LD A,FreshBV  ;get latest Battery voltage
 JRS MtrScale,Flags,TestAlt ;skip ahead if set for Alternator
 LD A,DspPcnt  ;get last % displayed
 CPIA,100  ;Is it 100%?
 JRZ GmBatt  ;...if so,show green LED
 CALL ResetStatus  ;...otherwise,turn Status LED′s off
 JP ShoStatX  ;...and skip to end
GrnBatt
 CALL ShowGreen  ;turn on Green LED
 JP ShoStatX  ;skip to end
TestAlt
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,Volts15a  ;Is alternator at least 15.07V?
 JRNC RedStat  ;...if so,skip ahead and show red
 CPI A,Volts138  ;is alternator at least 13.80V?
 JRC RedStat  ;...if not,skip ahead and show red
 CPI A,Volts14  ;Is alternator<14.0V?
 JRC ClrStat  ;...if so,skip ahead and show yellow
 CPI A,Volts149  ;is alternator at least 14.87V?
 JRNC ClrStat  ;...if so,skip ahead and show yellow
 CALL ShowGreen  ;...otherwise turn on Green LED
 JP ShoStatX  ;...and skip to end
RedStat
 CALL ShowRed  ;turn on Red LED
 JP ShoStatX  ;skip to end
ClrStat
 CALL ResetStatus  ;turn Status LED′s off
 ShoStatX
 RET
;***************************************************************************
;*   METER OFF    *
;* This routine turns off the three meter mode LED′s.  *
;*          *
;***************************************************************************
MeterOff
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*   DigiOff   *
;* This routine set the registers to turn off the three-digit LED. *
;*          *
;***************************************************************************
DigiOff
 LDI Digiat1,DigiOffa ;turn off 8 of 16 digital segments
 LDI DigiDat2,DigiOffb ;turn off other 8 of 16 digital segments
 RET
;***************************************************************************
;*   DIGITS OFF   *
;* This routine turns off the three-digit LED.    *
;*          *
;***************************************************************************
DigitsOff
 CALL DigiOff  ;set registers for all segments off
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   DIGITS ON   *
;* This routine turns ON all segments of the three-digit LED.  *
;*          *
;***************************************************************************
DigitsON
 LDI DigiDat1,DigiONa ;turn ON 8 of 16 digital segments
 LDI DigiDat2,DigiONb ;turn ON other 8 of 16 digital segments
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   SHOW PERCENT   *
;*This routine turns ON the Battery % LED.   *
;*          *
;***************************************************************************
ShowPercent
 SET MtrUnits,Flags  ;set Flags for %(not volts)
 JRR Wait0P,Flags2,SP1 ;skip ahead if not waiting from 0
 LDI DigiDat1,Dashes1 ;...otherwise,show dashes while waiting
 LDI DigiDat2,Dashes2 ;...otherwise,show dashes while waiting
 JP ShowPx
SP1
 LD A,DspPcnt  ;get Percent value to display
 .IFC EQ AdjOff;assemble next line only if debugging
  LD A,BADhi  ;set to display latest batt.volt.
 .ENDC
JRR MtrScale,Flags,SP2;don′t use Display% for Alternator%
LD A,Percent  ;...use actual Percent for display
.IFC EQ ShoOff  ;assemble next line only if debugging
JRR ChMode,Flags2,SP2 ;skip ahead **DEBUG**
LD A,OFFSET  ;diplay OFFSET **DEBUG**
.ENDC
SP2
 LD LEDnum,A  ;...and store it in Accumulator
 CALL ShowNum  ;set digital LED for LEDnum
 SET Decimal,DigiDatl  ;turn OFF decimal point
ShowPx
 RET
;***************************************************************************
;*   RESET LEDS  *
;* This routine turns off the Type,Rate,and Status LED′s  *
;*          *
;***************************************************************************
ResetLEDs
 CALL ResetStatus  ;turn off all three status LEDs
ClrLEDs
 LDI SwData,SwsOff  ;turn off Type and Rate LED′s
 RET
;***************************************************************************
;*  Reset Status  *
;* This routine turns off the LED′s in the Status area.  *
;*          *
;***************************************************************************
ResetStatus
 SET LEDchgng,DRAbuf  ;turn off Charging LED
SET LEDdone,DRAbuf  ;turn off Charged LED
SET LEDalert,DRAbuf ;turn off Fault(red)LED
RET
;***************************************************************************
;*  BLINK Charging LED  *
;* This routine blinks the Charging LED at a rate of once per second.*
;***************************************************************************
BlnkChrg
 LD A,MSecsl  ;get MSecs count
 CPI A,MS500  ;test for>1/2 sec
 JRNC BlinkChl  ;if so,skip ahead
 CALL ResetStatus  ;...otherwise,turn off status LEDs
 JP BlinkChX  ;...and exit routine
BlinkChl
 CALL ShowChgng  ;Turn on Charging LED
BlinkChX
 RET
;***************************************************************************
;*   Show Charging   *
;* This routine turns the Charging LED on and the rest off. *
;*          *
;* Show Yellow   *
;* This routine turns the Charging LED on and does not affect the Check *
;* and Charged LEDs.ShowYellow is actually the last part of ShowChgng *
;*          *
;***************************************************************************
ShowChgng
 CALL ResetStatus ;turn off all Status LEDs
ShowYellow
 RES LEDchgng,DRAbuf  ;turn ON Charging LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*   BLINK Alert LED   *
;* This routine blinks the Alert LED at a rate of once per second. *
;*          *
;***************************************************************************
BlinkAlert
 LD A,MSecsl  ;get MSecs count
 CPI A,MS500  ;test for 1/2 sec
 JRNC BlnkAlrt  ;if so,skip ahead
 CALL ResetLEDs  ;...otherwise,turn offall LEDs
 JRS BurnIn,Flags3,BBI ;skip ahead ifnot Burn-In
 CALL DigitsON  ;...turn on all digital LED segments
 JP BAeXit  ;...and exit routine
BBI
 CALL NumData  ;get data for,and show LED number
 JP BAeXit  ;...and exit routine
BlnkAlrt
 CALL AlertON  ;Turn on Alert LED
 CALL DigitsOff  ;Turn off 3-digit LED
BAeXit
 RET
;***************************************************************************
;*   Alert LED ON   *
;* This routine turns on the Alert(red)LED and turns the other meter  *
;* LEDs off. NOTE:it does not affect the Rate and Type LEDs.  *
;***************************************************************************
AlertON
 CALL MeterOff  ;Turn of fMeter Mode LEDs
ShowRed
 CALL ResetStatus  ;Turn off Status LEDs
 RES LEDalert,DRAbuf  ;Turn on Alert LED
 CALL UpdatePA  ;update port A from buffer
RET
;***************************************************************************
;*   Show Done LED    *
;*This routine turns on the Done(green)LED and turns all the other  *
;*LEDs off.NOTE:it turns off the Rate and Type LEDs.  *
;***************************************************************************
ShowDone
 CALL ResetLEDs  ;Turn off all LEDs
 LDI SwData,SwsOff  ;set Type & Rate LED′s off
 CALL ShowType  ;show Battery Type & update display
ShowGreen
 CALL ResetStatus  ;turn off all three status LEDs
 RES LEDdone,DRAbuf  ;Turn on Done LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*   BLINK Crank LED   *
;*This routine blinks the Crank LED at a rate of once per second. *
;***************************************************************************
BlinkCrank
 LD A,MSecs2  ;get MSecs count
 CPI A,MS500  ;test for>1/2 sec
 JRNC BlinkES  ;if so,skip ahead
 SET LEDboost,SwData ;...otherwise,turn off Crank LED
 JP BCeXit  ;...and exit routine
BlinkES
 CALL ShowCrank  ;turn on Crank LED
BCeXit
 RET
;***************************************************************************
;*   ShowCrank    *
;* This routine turns the Engine Start(Crank/Boost)LED on and turns *
;* the Type and other Rate LEDs off.    *
;* NOTE:The 6V LED will be left on if appropriate.  *
;***************************************************************************
ShowCrank
 CALL ClrLEDs  ;turn off all Rate & Type LEDs
 JRR Bat6V,Flags2,ShoES  ;skip ahead if not 6V
 RES LED6V,SwData ;turn on Regular 6V LED
ShoES
 RES LEDboost,SwData  ;turn ON Crank LED
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   SetSlow    *
;* This routine sets the charger for the Slow rate by setting the appro- *
;*priate flags.       *
;***************************************************************************
SetSlow
 RES Rate,Flags  ;turn on Slow LED
 RES Rapid,Flags2  ;turn off Rapid LED
 RET
;***************************************************************************
;*   SetSlow    *
;* This routine sets the OFFSET for the correct(12or 6V)Slow rate. *
;*          *
;***************************************************************************
StartSlow
 LDI OFFSET,OffSlow  ;set Offset for 2A
 JRR Bat6V,Flags2,StrtSloX ;skip if not set for 6V mode
 LDI OFFSET,Off6Slo  ;...otherwise,adjust OFFSET
StrtSloX
 RET
;***************************************************************************
;*   SetMinOff   *
;* This routine sets the OFFSET for the correct(12 or 6V)maximum Slow *
;* rate(minimum OFFSET).    *
;*          *
;***************************************************************************
SetMinOff
 LDI LowOff;MinOffSlo  ;limit output to max 2A current
 JRR Bat6V,Flags2,SetMOx  ;skip next line ifnot 6V mode
 LDI LowOff,Min6OffSlo  ;limit output to max 6V 2a current
SetMOx
 RET
;***************************************************************************
;*   SetMinFst   *
;* This routine sets the OFFSET for the correct(12 or 6V)maximum Fast *
;* rate(minimum OFFSET).     *
;*          *
;***************************************************************************
SetMinFst
 LDI LowOff,MinOfFst  ;limit output to max Fast current
 JRR Bat6V,Flags2,SetMFx  ;skip next line ifnot 6V mode
 LDI LowOff,Min6OfFst  ;limit output to max 6V Fast current
SetMFx
 RET
;***************************************************************************
;*  Show Charge Rate LED(depending on mode)  *
;* This routine turns on the Slow,Fast,or Rapid LED,based on Flags. *
;*          *
;***************************************************************************
ShowRate
 SET LEDboost,SwData  ;turn off Boost LED
 SET LEDrap,SwData  ;turn off Rapid LED
 SET LEDfast,SwData  ;turn off Fast LED
 SET LEDslow,SwData  ;turn off Slow LED
 JRR ChMode,Flags2,ShoRateX  ;exit if in Tester Mode
ShowRap
 JRR Rapid,Flags2,ShowSlow  ;goto ShowSlow if not Rapid
 RES LEDrap,SwData  ;turn on Rapid LED
 JP ShoRateX
ShowSlow
 JRS Rate,Flags,ShowFast  ;goto ShowFast if set
 RES LEDslow,SwData  ;turn on Slow LED
 JP ShoRateX
ShowFast
 RES LEDfast,SwData  ;turn on Fast LED
ShoRateX
 RET
;***************************************************************************
;*   Set12V   *
;* This routine sets the charger for the 12V Regular battery type by  *
;* resetting the 6V,AGM/Gel,and Deep Cycle flags.  *
;*          *
;* SetReg   *
;* This routine sets the charger for the Regular battery type by reset- *
;* ting the Deep Cycle and AGM/Gel flags.SetReg is actually part of *
;*Set12V       *
;***************************************************************************
Set12V
 RES Bat6V,Flags2  ;turn off 6V LED
SetReg
 RES BatTypeA,Flags  ;turn on Regular LED
 RES BatTypeB,Flags  ;turn off Gel/AGM LED
 RET
;***************************************************************************
;* Show Charge Type LED(depending on mode) *
;* This routine turns on either the Regular,Deep Cycle,Gel/AGM,or 6V  *
;* LED based on Flags.The routne also sets Vmax to match.  *
;*          *
;***************************************************************************
ShowType
 SET LEDreg,SwData  ;set Regular LED to off
 SET LEDdeep,SwData  ;set Deep Cycle LED to off
 SET LEDgel,SwData  ;set Gel/AGM LED to off
 SET LED6V,SwData  ;set 6V LED to off
 JRR Bat6V,Flags2,ShowT1;skip ahead if not 6V
 RES LED6V,SwData  ;turn on Regular 6V LED
 JP ShowT2a  ;set Vmax for regular(15.5V)
ShowT1
 JRR BatTypeB,Flags,ShowT2  ;skip ahead if not Gel/AGM
 RES LEDgel,SwData  ;turn on Gel/AGM LED
 LDI Vmax,Volts144  ;Vmax=14.4V for Gel/AGM MODE
 JP ShoTypeX
ShowT2
 JRS BatTypeA,Flags,ShowT3 ;goto ShowT3 if set
 RES LEDreg,SwData  ;turn on Regular LED
ShowT2a
 LDI Vmax,Volts155  ;Vmax=15.5V for Regular MODE
 JP ShoTypeX
ShowT3
 RES LEDdeep,SwData  ;turn on Deep Cycle LED
 LDI Vmax,Volts16  ;Vmax=16V for Deep Cycle battery
ShoTypeX
 RET
;***************************************************************************
;*  Hold Charge Type LED(depending on mode) *
;* This routine turns on the Regular,Deep Cycle,or Gel/AGM LED based on *
;* Flags and keeps it on for one Fifth second.   *
;***************************************************************************
HoldType
 CALL ShowType  ;turn on Battery Type LED
 CALL ShowData  ;update display
 CALL FifthSecond  ;wait one Fifth second
 RET
;***************************************************************************
;*  Hold Charge Rate LED(depending on mode)  *
;* This routine turns on the Slow,Fast,or Rapid LED based on Flags and *
;* keeps it on for one Fifth second.     *
;***************************************************************************
HoldRate
 CALL ShowRate  ;turn on Charge Rate LED
 CALL NumData  ;get data for,and show nominal rate (amps)
 CALL FifthSecond  ;wait one Fifth second
 RET
;***************************************************************************
;*   Check High Offset    *
;* This routine is used to check whether the latest OFFSET is equal to the *
;* maximum value,HiOff.When OFFSET=HiOff,the charge rate is 0. *
;***************************************************************************
ChkHiOff
 LD A,OFFSET  ;get current OFFSET
 JRS Bat6V,Flags2,CHO6 ;skip next line if not 6V mode
 CPI A,HiOff-2  ;has OFFSET reached maximum (output off)?
 JP CHOx
CHO6
 CPI A,HiOff6-2  ;has OFFSET reached max for 6V(output off)?
CHOx
 RET
;***************************************************************************
;*    Check0V     *
;* This routine checks the latest running average of the battery voltage *
;* and sets the Carry bit if it′s less than Volts0+1DAC count. This *
;* routine is used to check whether a battery is connected.  *
;***************************************************************************
Check0V
CheckBatt
 SET Batt,Flags2  ;set flag for connected battery
;LD A,FreshBV  ;test latest average voltage
 LDI A,Volts0+1  ;check if higher than zero
 JRR Crnkng,Flags4,ChkBat;skip next line if not cranking
 LDI A,1  ;check for true 0 if cranking
ChkBat
 CP A,FreshBV  ;test latest average voltage
 JRNC NoBatt  ;If not>0,battery not connected
 JP ChkBattX  ;...otherwise,just exit
NoBatt
 RES Batt,Flags2  ;set for battery not connected
 CALL ShowRed  ;turn on Alert(Red)LED
 CALL ClrPcnt  ;clear Percent and Display Percent
 CLR BADhi  ;clear previous voltage reading
 CLR FreshBV  ;clear previous voltage reading
ChkBattX
 RET
;***************************************************************************
;*   Get Battery Voltage  *
;* This routine gets the battery voltage stored in BADhi and saved it in *
;* the accumulator.It also doubles the result if set for 6V battery. *
;*          *
;*  Double6V    *
;* This routine doubles the accumulator,A,if the Bat6V flag is set. This *
;* routine is called before the accumulator is compared to one of the *
;* constants originally assigned for 12v batteries.     *
;*          *
;* NOTE:If the Bat6V flag is set,and the accumulator is>8.5V,the  *
;*Hi6V Flag is set instetad of doubling A.    *
;***************************************************************************
GetBatt
 LD A,BADhi  ;get latest(avg)battery voltage
Double6V
 JRR Bat6V,Flags2,D6VX ;skip ahead if not set for 6V
 JRR Hi6V,Flags3,D6V ;double if 6V Batt<8.5V
 LDI A,MaxVolts  ;...otherwise,set A to MaxVolts
;JRR ChMode,Flags2,D6VX ;check for Charge or Test mode
;CALL SetAbort  ;...set for Abort state if Charge mode
;SET Alert,Flags2  ;...set Alert Flag
 JP D6VX  ;...and skip to end of routine
D6V
 SLA A  ;double A
D6VX
 RET
;***************************************************************************
;*   Check Progress   *
;* This routine is used to ensure that the charger will abort if the *
;* battery voltage does not increase throughout the charge. It checks the *
;* voltage every CPint minutes for a measurable increase since the *
;* previous check.If there isn′t,the charge is aborted.  *
;*          *
;***************************************************************************
ChkProg
 JRR MIN,TicFlag1,ChkProgX ;exit ifnot time to check for progress
;ChkProg0
;JRR SOC,SwDown,ChkProg1  ;skip ahead ifnot Start Of Charge
;RES SOC,SwDown  ;...otherwise,clear SOC flag
;CALL IniTime1  ;initialize Timer1
;LDI Mins1,5  ;...set Timer1 for 5minutes
;CLR LastBatt  ;clear LastBatt(ensure pass 1st test)
;JP ChkProgX  ;...and exit
;ChkProg1
 LD A,BADhi  ;get latest battery reading
 SUBI A,1  ;subtract one count
 CP A,LastBatt  ;check for increase
 JRC ChkProgA  ;set to abort if no increase
 LD A,BADhi  ;set A back to BADhi
 LD LastBatt,A  ;update LastBatt
 CALL IniTime1  ;initialize Timer1
 .IFC NE FastCP  ;assemble next line only if not debugging
 LDI Minsl,CPint  ;set Timerl for 60 minutes
 .ELSE   ;assemble next line only if debugging
LDI Mins1,3  ;set Timerl for 3mins
 .ENDC
 DEC CCDcnt  ;update interval count
 JRNZ ChkProgX  ;just exit if not zero
 SET HR,TicFlag1  ;if zero,set for time expired
ChkProgA
 CALL SetAbort  ;set to start Abort mode
ChkProgX
 RET
;***************************************************************************
;*    Battery Progress   *
;* This routine is used to ensure that ChkProg and CheckBatt are called *
;* only when the charge rate is about to ramp up or isn′t set to ramp at *
;* all.That way,the battery voltage used to check charging progress *
;* won′t be affected by the higher current. BattProg works by checking *
;* RmpCnt to make sure it′s less than 5. If the start of charge flag(SOC)*
;* is set,BattProg does not check RmpCnt.    *
;*           *
;***************************************************************************
BattProg
;JRR Rmpng,Flags3,BtPrg0 ;skip ahead if not Rapid->Fast transition
;CALL RampOS  ;otherwise,gradually reduce duty cycle
;BtPrg0
 CLR A  ;set A to 0 to ensure<(9,12,or 14.2 V)
 JRS HiPwr,Flags4,BtPrgX ;exit if high power mode
;JRS SOC,SwDown,BtPrg2 ;skip ahead if Start Of Charge
 LD A,RmpCnt  ;get Ramp interval counter
;NOTE: RmpCnt will be 0 ifnot set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC BtPrgX  ;if not,then exit
;BtPrg2
 CALL ChkProg  ;check for charging progress
 CALL GetBatt  ;get latest voltage & double if 6V mode
BtPrgX
 RET
;***************************************************************************
;*    Check2V        *
;* This routine checks the latest running average of the battery voltage *
;* and sets the Carry bit if it′s less than Volts016.This routine is *
;* used to check whether a battery is ready for cranking.  *
;***************************************************************************
Check2V
 LD A,FreshBV  ;test latest average voltage
 CPI A,Volts016 ;check if higher than 1.6 volts
 RET
;***************************************************************************
;*    CHECK SWITCHES    *
;* Check if switch is engaged and change modes if appropriate.  *
;*          *
;***************************************************************************
CheckSw
 JRR CrankWait,Flags,ChkStart ;check switches if not during Crank wait
 JP ChkSwRET  ;don′t check switches if during Crank wait
ChkStart
 JRS Crank,Flags,ChekRate ;don′t check display mode during Boost
 JRR MeterSw,DRC,MeterDown ;If switch is being pressed,skip ahead
 RES MeterSw,SwDown  ;set for Meter switch not pressed(up)
ChekRate
 JP ChkRate  ;Meter switch not pressed,so exit CheckSw
MeterDown
 RES Idle,Flags3  ;set for not idle
 JRS MeterSw,SwDown,ChekRate ;If switch wasn′t released,don′t check it
 SET MeterSw,SwDown  ;set for mode switch pressed(down)
 JRR MtrScale,Flags,ChkPrcnt ;if not set for Alt,then skip ahead
 RES MtrScale,Flags  ;set for Alt%,so change to Batt%
 JP ChkRate
ChkPrcnt
 JRR MtrUnits,Flags,ChkAlt ;if set for volts,then skip ahead
 RES MtrUnits,Flags  ;set for Batt%,so change to volts
 JP ChkRate
ChkAlt
 SET MtrUnits,Flags  ;set for volts,so change to %
  .IFC NE ShoOff ;assemble next line only if not debugging
 JRS ChMode,Flags2,ChkRate ;don′t set for Alt if charging
  .ENDC
 SET MtrScale,Flags  ;set for batt,so change to alt
 RES Wait0P,Flags2  ;set to stop waiting for battery %
ChkRate
 CALL ShoMtrMode  ;Meter units are set before rate
  .IFC EQ DEBUG ;assemble next line only if debugging
;JRR SwOff,SwDown,SkpSw ;skip Rate and Type swith if SwOffis set
;JP ChkSwRET  ;Otherwise,just exit
 JRS SwOff,SwDown,ChkSwX ;skip Rate and Type swith if SwOff is set
;SkpSw
 .ENDC
 JRR RateSw,DRC,RateDown ;If switch is being pressed,skip ahead
 RES RateSw,SwDown  ;set for Rate switch not pressed(up)
ChekType
 JP ChkType  ;Rate switch not pressed,so check Type
RateDown
 RES Idle,Flags3  ;set for not idle
 JRS RateSw,SwDown,ChekType ;If switch wasn′t released,don′t check it
 SET RateSw,SwDown  ;set for Rate switch pressed(down)
ChkCM
 .IFC EQ AdjOff ;assemble next lines only if debugging
 JRR Manual,Flags3,ManRate ;debug only in manual mode
 INC OFFSET  ;increase OFFSET(decrease output)
JP ChkSwRET  ;exit CheckSwitch routine
 .ENDC
ManRate
 JRR Crank,Flags,ChkSlow ;ifnot set for Crank,check for Slow
 CALL TurnOff  ;low & high power and fan off,min duty
 RES ChMode,Flags2  ;set for Tester(not Charger)Mode
 SET Disable,DRBbuf  ;disable output if Rate was Boost
  JP ModeChange  ;go to end of CheckSw
ChkSlow
 JRS ChMode,Flags2,ChkFast ;skip ahead if already Charger mode
 SET ChMode,Flags2  ;set for Charger(not tester)Mode
 RES Disable,DRBbuf ;enable output after Rate is pressed
 RES MtrScale,Flags ;set for Batt%(not Alt%)when not tester
 RES Rate,Flags  ;was Crank,so set for Slow
 JP ModeChange  ;go to end of CheckSw
ChkFast  ;if set for Slow,then set to Fast
 JRS Rate,Flags,ChkRap ;If not Slow,then must be Fast
 SET Rate,Flags  ;set Charge rate for Fast
 JP ModeChange  ;go to end of CheckSw
ChkRap  ;if set for Fast,then change to Rapid
 JRS Rapid,Flags2,ChkES ;Ifnot Rapid,then must be Fast
 SET Rapid,Flags2  ;set Charge rate for Rapid
 JP ModeChange  ;go to end of CheckSw
ChkES  ;was set to Rapid,change to Boost
 CALL SetSlow  ;set for Slow Rate
 SET Crank,Flags  ;set Charge rate for Boost
;CALL SetReg  ;set battery type for Regular
 CALL ShowCrank  ;turn ON Crank LED
 CALL TurnOff ;low & high power and fan off,min duty
 LDI CurentSS,CrankSS ;set Charge state to Crank
 CALL IniTime2  ;reset timer 2
 LDI Sees2,003h ;set Timer2 for 3 seconds
 JP ChkSwRET
ChkType  ;if Gel/AGM,then set for Regular
 JRR TypeSw,DRC,TypeDown ;If Switch is being pressed,skip ahead
 RES TypeSw,SwDown  ;set for Type switch not pressed(up)
ChkSwX
 JP ChkSwRET  ;Type switch not pressed,so exit CheckSw
TypeDown
 RES Idle,Flags3  ;set for not idle
 JRS TypeSw,SwDown,ChkSwX ;If Switch wasn′t released,don′t check it
 SET TypeSw,SwDown  ;set for mode switch pressed(down)
 .IFC EQ AdjOff ;assemble next lines only if debugging
 JRR Manual,Flags3,ManType ;debug only in manual mode
 DEC OFFSET  ;decrease OFFSET(increase output)
JP ChkSwRET  ;exit CheckSwitch routine
 .ENDC
ManType
 JRR Bat6V,Flags2,ChkBT1 ;If not set for 6V,check for Regular
ChkBT0  ;if set for 6V,change to 12V regular
 RES Hi6V,Flags3  ;clear 6V over voltage flag
 CALL Set12V  ;set for Regular,12V battery
 CALL ClrPcnt  ;clear Percent and Display Percent
 JP TypeChange  ;go to end of CheckSw
ChkBT1  ;ifset for AGM/Gel,change to 6V
 JRR BatTypeB,Flags,ChkBT2 ;Ifnot set for Gel/AGM,check for Regular
 JRS Hi6V,Flags3,ChkBT0 ;don′t set to 6V if batt>8.5V
 CALL SetReg  ;set battery type for Regular
 SET Bat6V,Flags2  ;set for 6V battery
 CALL ClrPcnt  ;clear Percent and Display Percent
 JP TypeChange  ;go to end of CheckSw
ChkBT2  ;if Regular,then set for Deep Cycle
 JRS BatTypeA,Flags,ChkBT3 ;If not set for Regular,must be Deep Cycle
 SET BatTypeA,Flags ;set battery type for Deep Cycle
 RES BatTypeB,Flags ;set battery type for not AGM/Gel
 JP TypeChange  ;go to end of CheckSw
ChkBT3  ;must be Deep Cycle,so set for Gel/AGM
 SET BatTypeB,Flags ;set battery type for Gel/AGM
 RES BatTypeA,Flags ;set battery type for not Deep Cycle
TypeChange
 RES Crank,Flags  ;set charge rate for non-Boost
 CALL ShowType  ;turn on Battery Type LED
ModeChange
 RES Crank,Flags  ;clear Crank bit of Flags
 LDI CurentSS,000h ;restart charging
ChkSwRET
 RET
;****************************************************************************
;*    FAN ON    *
;* This routine turns the cooling fan ON. FanON is called during one of *
;* the following conditions:       *
;* 1.Start of charge(end of State 2)    *
;* 2.Start of boost(State 16)    *
;* 3.If OFFSET<HiOff-3 in Maintain(State 14)    *
;* 4.Manual Mode(State 15)    *
;* 5.States 4,5,11,12,and 13    *
;*          *
;***************************************************************************
FanON
 LD ATemp,A ;save Accumulator
 LDI A,00010000b ;update Accumulator from buffer
 LD DRC,A ;update port from Accumulator
 LD A,ATemp ;restore Accumulator
 RET
;***************************************************************************
;*    FAN Off    *
;* This routine turns the cooling fan off. FanOffis called during one of *
;* the following conditions:    *
;* 1.Before start of charge(State 0)    *
;* 2.Start of Abort(State 8)    *
;* 3.Before start of Maintain(State 14)    *
;* 4.If OFFSET=HiOffin Maintain(State 14)    *
;*         *
;***************************************************************************
FanOff
 LD ATemp,A ;save Accumulator
 LDI A,00000000b ;update Accumulator from buffer
 LD DRC,A ;update port from Accumulator
 LD A,ATemp ;restore Accumulator
 RET
;***************************************************************************
;*    ShutOff    *
;* This routine sets the charger for no output by turning off the output *
;* FETs,turning off the fan,setting the PWM for minimum duty cycle *
;*(HiOFF),and setting it for non-boost mode.    *
;*         *
;*    TurnOff    *
;* This routine sets the charger for no output by turning off the output *
;* FETs,turning off the fan,and setting the PWM for minimum duty  *
;* cycle(HiOFF).TurnOff is actually part of ShutOff.  *
;*          *
;***************************************************************************
ShutOff
 RES Crank,Flags  ;set charge rate for non-Boost
 CLR RmpCnt ;clear ramp interval counter
TurnOff
 CALL FanOff ;turn cooling fan off
SetOff
 RES Power,Flags2 ;turn output off
 RES Crnkng,Flags4 ;indicate not cranking
SetHiOff
 LDI OFFSET,HiOff ;set for minimum duty cycle
 JRR Bat6V,Flags2,SOx ;skip next line if not 6V mode
 LDI OFFSET,HiOff6 ;set for min. 6V duty cycle
SOx
 RET
;****************************************************************************
;*    TurnON      *
;* This routine sets the charger to run with the Charging LED,fan,and *
;* output on.     *
;*           *
;*    SetON     *
;* This routine sets the charger to run with the fan and output on  *
;* SetON is actually part of TurnON      *
;*          *
;****************************************************************************
TurnON
 CALL ShowChgng ;turn Charging LED on
SetON
 CALL FanON ;turn cooling fan on
 SET Power,Flags2 ;tell PwrCon charger is on
 RET
;***************************************************************************
;*    Charge Relay    *
;* This routine switches the relay from Start to Charge if necessary. *
;* ChrgRly waits 200mS before switching the relay. The output should  *
;* before turned offbefore calling ChrgRly.    *
;*           *
;***************************************************************************
;ChrgRly
;JRR ESrly,DRBbuf,ChgRlyX;skip ahead if relay already set for charge
;CALL FifthSecond ;wait 200mS
;RES ESrly,DRBbuf ;set E/S relay for charge
;ChgRlyX
;RET
;***************************************************************************
;* Update the clocks and set overflow flags as necessary. *
;* TicFlag1(s)bit 0=hours went to zero   *
;* TicFlag1(s)bit 1=minutes went to zero   *
;* TicFlag1(s)bit 2=seconds went to zero   *
;* TicFlag1(s)bit 3=miliseconds went to zero   *
;***************************************************************************
CLOCKS
 DEC MSecs1  ;decrement millisecond counter
 JRNZ Clks1  ;skip to clock2 if MSECs<>0
Do_MSecs
 LDI A,MSINIT  ;restart millisecond counter
 LD MSecs1,A  ;
 SET MSEC,TicFlag1  ;set millisec flag
 DEC Secs1  ;decrement second counter
 JRZ Do_Mins
Clks1
 JP CLOCKS1
Do_Mins
 SET SEC,TicFlag1 ;set second expired flag
 LDI Secs1,SecInit ;restart second counter
 DEC Mins1  ;decrement minute counter
 JRNZ CLOCKS1  ;skip HRs1 ifMINs1<>down to zero
Do_Hrs
 SET MIN,TicFlag1 ;set minute expired flag
 LDI Mins1,MinInit ;restart minute counter
 DEC Hrs1  ;decrement hour counter
 JRNZ CLOCKS1  ;check for overflow
 SET HR,TicFlag1 ;set hour expired flag
CLOCKS1
 DEC MSecs2  ;decrement millisecond counter
 JRZ DOMSecs2
ClkExit
 JP CLOCEXIT
DOMSecs2
 LDI A,MSINIT  ;restart millisecond counter;
 LD MSecs2,A  ;
 SET MSEC,TicFlag2 ;set millisec flag
 DEC Secs2  ;decrement second counter
 JRNZ ClkExit  ;exit if not down to zero
Do_Mins2
 SET SEC,TicFlag2 ;set second expired flag
 LDI Secs2,SecInit ;restart second counter
 DEC Mins2  ;decrement minute counter
 JRNZ CLOCEXIT  ;exit if not down to zero
Do_Hrs2
 SET MIN,TicFlag2 ;set minute expired flag
 LDI Mins2,MinInit ;restart minute counter
 DEC Hrs2  ;decrement hour counter
 JRNZ CLOCEXIT  ;check for overflow
 SET HR,TicFlag2 ;set hour expired flag
CLOCEXIT
 RET
;**************************************************************************
;*   INITIALIZE TIMER1    *
;*  Subroutine to initialize timer1    *
;****************************************************************************
IniTime1
 LDI MSecs1,MSINIT
 LDI Secs1,SecInit
 LDI Mins1,MinInit
  CLR Hrs1
 CLR TicFlag1
 RET
;***************************************************************************
;*  INITIALIZE TIMER2    *
;*  Subroutine to initialize Timer2   *
;***************************************************************************
IniTime2
 LDI MSecs2,MSINIT
 LDI Secs2,SecInit
 LDI Mins2,MinInit
 CLR Hrs2
 CLR TicFlag2
 RET
;***************************************************************************
;*    ShiftA7    *
;* Subroutine to shift the accumulator left 7 times. Used by Divide2 *
;* and Divide4. Written only to save code space.  *
;***************************************************************************
ShiftA7
 SLA A ;shift left
 RLC A ;rotate left through CARRY bit 6times
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 RET
;***************************************************************************
;*    DIVIDE BY 2  *
;* Subroutine to divide the number in A by 2. The reminder,if any *
;* will be available in the carry bit upon return.    *
;***************************************************************************
Divide2
 CALL ShiftA7;shift left once then rotate left 7times
 RLC A ;rotate left 7th time
 RET
;***************************************************************************
;*    DIVIDE BY 4    *
;* Subroutine to divide the number in A by 4.    *
;***************************************************************************
Divide4
 CALL ShiftA7 ;shift left once then rotate left 7times
 ANDI A,01111111b ;drop MSB
 RET
;***************************************************************************
;*    A Times 5    *
;* Subroutine to multiply the accumulator(A)by 5.  *
;* Atimes5 multplies A by 4by shifting left twice then adding the  *
;* original value of A:(A*4)+A=A*5    *
;***************************************************************************
ATimes5
 LD ATemp,A ;ATemp=A
 ADD A,A  ;A=A+A=A*2
 ADD A,A  ;A=A+A=ATemp*4
 ADD A,ATemp ;A=A+ATemp=ATemp*5
 RET
;***************************************************************************
;*    CURRENT REGULATION   *
;* This routine reduces the output current by increasing the OFFSET  *
;* value when the voltage is below 14.2 volts(thru SS5). An offset into *
;* an LUT is determined based on the battery voltage. The value is loaded *
;* into OFFSET which is used to controls the off time of the SCR′s.  *
;***************************************************************************
IReg
 LD A,BADhi  ;get voltage
;LD A,FreshBV  ;get voltage
 JRS Bat6V,Flags2,IR_6V ;skip ahead if 6V mode
 JRS Rate,Flags,PH_1;skip ahead if 15amp mode
 LDI DRWR,OffAdjSlo.w ;look up table for 12V 2amp
 LDI X,OffAdjSlo.d ;initialize look up table
 LDI TempOff,OffLowSlo ;highest 2A offset-lowest current
 SUBI A,BatLoSlo ;sub mininum 12V 2amp table entry(10V)
 JRNC P_A14  ;done
P_A15
 LD A,TempOff
 JP P_A12
P_A14
 LDI TempOff,OffHiSlo ;lowest 12V 2A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC P_A15  ;done
 JP PH_2  ;done with 12V 2amp
PH_1
 JRS Rapid,Flags2,IR_rap ;skip ahead if Rapid rate
IR_1
 LDI DRWR,OffAdjFst.w ;look up table for 12V 15amp
 LDI X,OffAdjFst.d ;initialize look up table
 LDI TempOff,OffLowFst ;highest 15A offset-lowest current
 SUBI A,BatLoFst ;sub mininum 15amp table entry
 JRNC P_A17  ;done
P_A16
 JP P_A15
P_A17
 LDI TempOff,OffHiFst ;lowest 12V 15A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC P_A16  ;done
 JP PH_2  ;done with 12V 15amp
IR_rap
 JRR HiPwr,Flags4,IR_1;use 12V 15A table if low power mode
 LDI DRWR,OffAdjRap.w ;look up table for 60amp
 LDI X,OffAdjRap.d ;initialize look up table
 LDI TempOff,OffLowRap ;highest 60A offset-lowest current
 SUBI A,BatLoRap ;sub minium 60amp table entry
 JRNC IR_rp2  ;done
IR_rp1
 JP P_A15
IR_rp2
 LDI TempOff,OffHiRap ;lowest 60A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC IR_rp1  ;done
PH_2
 ANDI A,03Fh ;limit to 64byte window
 ADD A,X  ;add table base address
 LD X,A  ;
 LD A,(X)  ;get value from table
 JP P_A12  ;skip ahead and update offet value
IR_6V
 JRS Rate,Flags,IR6_3 ;skip ahead if 15amp mode
 LDI DRWR,Of Ad6Slo.w ;look up table for 6V 2amp
 LDI X,Of Ad6Slo.d ;initialize look up table
 LDI TempOff,Off6LoSlo ;highest 2A offset-lowest current
 SUBI A,Bat6LoSlo ;sub mininum 6V 2amp table entry(5V)
 JRNC IR6_2  ;done
IR6_1
 LD A,TempOff
 JP P_A12
IR6_2
 LDI TempOff,Off6HiSlo ;lowest 6V 2A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_1  ;done
 JP IR6_10  ;done with 6V 2amp
IR6_3
 JRS Rapid,Flags2,IR6_7 ;skip ahead if Rapid rate
IR6_4
 LDI DRWR,OfAd6Fst.w ;look up table for 6V 15amp
 LDI X,OfAd6Fst.d ;initialize look up table
 LDI TempOff,Off6LoFst ;highest 15A offset-lowest current
 SUBI A,Bat6LoFst ;sub mininum 6V 15amp table entry
 JRNC IR6_6  ;done
IR6_5
 JP IR6_1
IR6_6
 LDI TempOff,Off6HiFst ;lowest 6V 15A offset-highest current
 CPI A,020h  ;last table entry-highest index
JRNC IR6_5  ;done
 JP IR6_10  ;done with 6V 15amp
IR6_7
 JRR HiPwr,Flags4,IR6_4 ;use 6V 15A table if low power mode
 LDI DRWR,OfAd6Rap.w ;look up table for 60amp
 LDI X,OfAd6Rap.d ;initialize look up table
 LDI TempOff,Off6LoRap ;highest 6V 60A offset-lowest current
 SUBI A,Bat6LoRap ;sub mininum 6V 60amp table entry
 JRNC IR6_9  ;done
IR6_8
 JP IR6_1
IR6_9
 LDI TempOff,Off6HiRap ;lowest 6V 60A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_8  ;done
IR6_10
 ANDI A,01Fh ;limit to 32byte window
 ADD A,X  ;add table base address
 LD X,A ;
 LD A,(X);get value from table
P_A12
;ADD A,FUDGE  ;debug fudge factor
 LD OFFSET,A  ;save new offset value
P_A13
 RET
;***************************************************************************
;*    VOLTAGE REGULATION   *
;* This subroutine will adjust the value of OFFSET once per second to *
;* control the current and maintain the voltage determined by MaintVolt.*
;*          *
;***************************************************************************
VoltReg
;LD A,MSecs2  ;MSec2=MSInit once per second
;CPI A,MSINIT ;Is MSEC1=MSINIT?
;JRZ VReg_0  ;Yes:then time to adjust
;VReg_X
;JP VReg_3 ;No: then not time to adjust
;VReg_0  ;adjust offset
 DEC VRcnt ;decrement interval counter
 JRZ VReg_0 ;Yes: then time to adjust
 JP VoltRegX ;No: then not time to adjust
VReg_0  ;adjust offset
 LDI VRcnt,MSINIT ;re-initialize initerval counter(1sec)
 LD A,FreshBV ;get battery voltage
 CALL Double6V ;double Battery voltage if set for 6V
 DEC A
 CP A,MaintVolt ;compare with set value+1
 JRNC VReg_6 ;greater than,increase OFFSET
 JP VReg_1 ;not greater than,test if less than
VReg_6
 LD A,OFFSET ;greater than,get phase delay value
 INC A  ;
 JRS Bat6V,Flags2,VReg_2
 CPI A,HiOff ;test if at high limit
 JP VReg_5
VReg_2
 CPI A,HiOff6
VReg_5
 JRNC VReg_3 ;at the limit,don′t change OFFSET
VReg_4
 LD OFFSET,A ;update OFFSET
VReg_3
 JP VoltRegX ;done for this pass
VReg_1
 INC A
 CP A,MaintVolt ;compare with set value
 JRNC VoltRegX ;not less than,just exit
 LD A,OFFSET ;less than,get phase delay value
 DEC A  ;
 CP A,LowOff ;test if at low limit
 JRNC VReg_4 ;not at the limit,update OFFSET
VoltRegX
 RET
;***************************************************************************
;*  TIMER INTERRUPT HANDLER   *
;* This routine turns the SCRs on if the power flags are non-zero and *
;* inhibits the timer.       *
;***************************************************************************
PwrCon
 LD ATemp,A ;save A register
 JRS Power,Flags2,PCon ;charger on,turn on SCRs
 JP PWREXIT ;not charging,just exit
PCon
 SET SCRs,DRBbuf ;turn on the SCRs(in buffer)
 CALL UpdatePB ;update port B from buffer
PWREXIT
;LDI TSCR,015h ;inhibit timer
 CALL RstWDR  ;reset watch dog timer
 LDI A,FULLTIME ;TCR is reloaded here for 1full cycle
 LD TCR,A ;
 LDI TSCR,05dh ;reload prescaler and start timer
 JRR Crnkng,Flags4,PC_Norm
PC_Crank
 CALL CLOCKS ;update clocks
 RES NMInt,Flags2 ;tell ExitMain this was NMI interupt
 JP PCexit ;leave SCRs on during Crank
;turn off SCR drive so that only a pulse is generated(SCR′s latch on)
PC_Norm
 SET NMInt,Flags2 ;tell ExitMain this was timer interupt
 LDI A,2Ah ;delay for width of ON pulse
PC_dly
 DEC A  ;decrement A until delay has expired
 JRNZ PC_dly  ;delay has expired when A is down to 0
 RES SCRs,DRBbuf ;turn off SCR′s(in buffer)
 CALL UpdatePB ;update port B from buffer
PCexit
 LD A,ATemp  ;restore A register
 RETI
;***************************************************************************
;*          NON-MASKABLE INTERRUPT HANDLER   *
;* This is the NMI interrupt routine. The NMI is generated on the falling *
;* edge of the full wave rectified AC line voltage. An interrupt is *
;* generated 120times per second,once every 8.333ms. After each NMI,*
;* this routine performs the following steps.    *
;* 1.Reset the watchdog timer and save the registers.  *
;* 2.Turn offthe SCRs(unless during CrankON state).  *
;* 3.Set the interrupt timer according to OFFSET.  *
;* 4.Reset NMInt so ExitMain knows it′s an NMI(not timer int). *
;* 5.Update the clocks.     *
;* 6.Restore the registers.    *
;* If turned off,the SCRs will remain off for a period determined by *
;* OFFSET.The Timer will then trigger an interrupt which tells PwrCon *
;* to turn the SCRs back on if necessary.   *
;*          *
;***************************************************************************
IT_TIMER
 CALL RstWDR ;reset watch dog timer
 LD ATemp,A ;save A register
 LD A,X ;get X register
 LD XTEMP,A ;save X register
 JRS Crnkng,Flags4,IT_X
 LD A,OFFSET ;get current offset
 LD TCR,A ;load the counter with current offset
 LDI TSCR,01011101b ;reload prescaler(32)and start timer
 RES SCRs,DRBbuf ;turn off SCR′s(in buffer)
 CALL UpdatePB ;update port B from buffer
IT_TMR
 RES NMInt,Flags2;tell ExitMain this was NMI interupt
 CALL CLOCKS ;update clocks
 NOP
;LDI X,2Ah ;delay for true zero cross
 LDI X,03h ;delay for true zero cross
IT_T
 DEC X
 JRNZ IT_T
 NOP  ;adjust zero cross delay
IT_X
 LD A,XTEMP ;restore registers
 LD X,A
 LD A,ATemp
 RETI
;***************************************************************************
;*    A/D INTERRUPT HANDLER   *
;* This is the A to D interrupt service routine. The only thing it does is *
;* clear the interrupt bit and wakes the processor up from its wait mode. *
;***************************************************************************
ADINT
 RES 7,ADCR
 LD A,ADR
 RETI
;***************************************************************************
;* ROM DATA WINDOW for THIRD VOLTS LED DIGIT  *
;* The following bit patterns are used to display the indicated numbers as *
;* the third(least significant)digit of the voltage display. *
;***************************************************************************
.block 16-$%16
Digits0Vx
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;display_0 for 00h
.byte 01111110b ;display_1 for 01h
.byte 01111110b ;display_1 for 02h
.byte 00110001b ;display_2 for 03h
.byte 00111000b ;display_3 for 04h
.byte 00111000b ;display_3 for 05h
.byte 01011100b ;display_4 for 06h
.byte 10011000b ;display_5 for 07h
.byte 10011000b ;display_5 for 08h
.byte 10010000b ;display_6 for 09h
.byte 00111110b ;display_7 for 0Ah
.byte 00111110b ;display_7 for 0Bh
.byte 00010000b ;display_8 for 0Ch
.byte 00011000b ;display_9 for 0Dh
.byte 00011000b ;display_9 for 0Eh
;****************************************************************************
;* ROM DATA WINDOW for THIRD LED DIGIT  *
;* The following bit patterns are used to display the indicated numbers as *
;* the third(least significant)digit on the LED.   *
;***************************************************************************
.block 16-$%16
Digits00x
;patterns for DigiDat1-Digit 1(LSD)& decimal point
;segment bafpedgc
.byte 00010010b ;bit pattern to display_0
.byte 01111110b ;bit pattern to display_1
.byte 00110001b ;bit pattern to display_2
.byte 00111000b ;bit pattern to display_3
.byte 01011100b ;bit pattern to display_4
.byte 10011000b ;bit pattern to display_5
.byte 10010000b ;bit pattern to display_6
.byte 00111110b ;bit pattern to display_7
.byte 00010000b ;bit pattern to display_8
.byte 00011000b ;bit pattern to display_9
;***************************************************************************
;* ROM DATA WINDOW for SECOND LED DIGIT *
;* The following bit patterns are used to display the indicated numbers as *
;* the second(middle significant)digit on the LED.  *
;***************************************************************************
.block 16-$%16
Digits0x0
;patterns for DigiDat2-Digit 2(middle digit)and MS 1
.byte 00000101b ;bit pattern to display_0_
.byte 11001111b ;bit pattern to display_1_
.byte 00100011b ;bit pattern to display_2_
.byte 10000011b ;bit pattern to display_3_
.byte 11001001b ;bit pattern to display_4_
.byte 10010001b ;bit pattern to display_5_
.byte 00010001b ;bit pattern to display_6_
.byte 11000111b ;bit pattern to display_7_
.byte 00000001b ;bit pattern to display_8_
.byte 10000001b ;bit pattern to display_9_
;***************************************************************************
;* ROM DATA WINDOW for Alternator Charge in Percent  *
;* The following values are the Percent values for the alternator voltages *
;*listed below. These numbers are onlyused when the charger is in *
;*Tester mode. Voltages lower than the first entry are displayed as 0% *
;*charged. Voltages above the last entry are displayed as 199% charged. *
;***************************************************************************
.block 32-$%32
AltLvls
;% Volts Hex
.byte 0 ;13.53 CB red
.byte 12 ;13.60 CC |
.byte 25 ;13.67 CD |
.byte 38 ;13.73 CE red
.byte 50 ;13.80 CF yellow
.byte 62 ;13.87 D0 |
.byte 75 ;13.93 D1 yellow
.byte 85 ;14.00 D2 green
.byte 92 ;14.07 D3 |
.byte 97 ;14.13 D4 |
.byte 100 ;14.20 D5 |
.byte 100 ;14.27 D6 |
.byte 100 ;14.33 D7 |
.byte 100 ;14.40 D8 |
.byte 100 ;14.47 D9 |
.byte 100 ;14.53 DA |
.byte 100 ;14.60 DB |
.byte 103 ;14.67 DC |
.byte 110 ;14.73 DD |
.byte 120 ;14.80 DE green
.byte 130 ;14.87 DF yellow
.byte 140 ;14.93 E0 |
.byte 150 ;15.00 E1 yellow
.byte 160 ;15.07 E2 red
.byte 170 ;15.13 E3 |
.byte 180 ;15.20 E4 |
.byte 190 ;15.27 E5 |
.byte 196 ;15.33 E6 red
.byte 199 ;15.40 E7 red
;***************************************************************************
;*   ROM DATA WINDOW FOR Slow mode   *
;* These are the off sets to control the current output. *
;***************************************************************************
.block 64-$%64
OffAdjSlo
;Offset  BADhi
;Dec Hex  Index Volts Hex Dec
.byte 130 ;82 0 10.00 96 150
.byte 129 ;81 1 10.07 97 151
.byte 129 ;81 2 10.13 98 152
.byte 129 ;81 3 10.20 99 153
.byte 129 ;81 4 10.27 9A 154
.byte 129 ;81 5 10.33 9B 155
.byte 129 ;81 6 10.40 9C 156
.byte 128 ;80 7 10.47 9D 157
.byte 128 ;80 8 10.53 9E 158
.byte 128 ;80 9 10.60 9F 159
.byte 128 ;80 10 10.67 A0 160
.byte 128 ;80 11 10.73 A1 161
.byte 127 ;7F 12 10.80 A2 162
.byte 127 ;7F 13 10.87 A3 163
.byte 127 ;7F 14 10.93 A4 164
.byte 127 ;7F 15 11.00 A5 165
.byte 127 ;7F 16 11.07 A6 166
.byte 127 ;7F 17 11.13 A7 167
.byte 126 ;7E 18 11.20 A8 168
.byte 126 ;7E 19 11.27 A9 169
.byte 126 ;7E 20 11.33 AA 170
.byte 126 ;7E 21 11.40 AB 171
.byte 126 ;7E 22 11.47 AC 172
.byte 125 ;7D 23 11.53 AD 173
.byte 125 ;7D 24 11.60 AE 174
.byte 125 ;7D 25 11.67 AF 175
.byte 125 ;7D 26 11.73 B0 176
.byte 124 ;7C 27 11.80 B1 177
.byte 124 ;7C 28 11.87 B2 178
.byte 124 ;7C 29 11.93 B3 179
.byte 124 ;7C 30 12.00 B4 180
.byte 124 ;7C 31 12.07 B5 181
.byte 123 ;7B 32 12.13 B6 182
.byte 123 ;7B 33 12.20 B7 183
.byte 123 ;7B 34 12.27 B8 184
.byte 123 ;7B 35 12.33 B9 185
.byte 123 ;7B 36 12.40 BA 186
.byte 122 ;7A 37 12.47 BB 187
.byte 122 ;7A 38 12.53 BC 188
.byte 122 ;7A 39 12.60 BD 189
.byte 122 ;7A 40 12.67 BE 190
.byte 122 ;7A 41 12.73 BF 191
.byte 122 ;7A 42 12.80 C0 192
.byte 121 ;79 43 12.87 C1 193
.byte 121 ;79 44 12.93 C2 194
.byte 121 ;79 45 13.00 C3 195
.byte 121 ;79 46 13.07 C4 196
.byte 120 ;78 47 13.13 C5 197
.byte 120 ;78 48 13.20 C6 198
.byte 120 ;78 49 13.27 C7 199
.byte 120 ;78 50 13.33 C8 200
.byte 120 ;78 51 13.40 C9 201
.byte 119 ;77 52 13.47 CA 202
.byte 119 ;77 53 13.53 CB 203
.byte 119 ;77 54 13.60 CC 204
.byte 119 ;77 55 13.67 CD 205
.byte 119 ;77 56 13.73 CE 206
.byte 118 ;76 57 13.80 CF 207
.byte 118 ;76 58 13.87 D0 208
.byte 118 ;76 59 13.93 D1 209
.byte 118 ;76 60 14.00 D2 210
.byte 117 ;75 61 14.07 D3 211
.byte 117 ;75 62 14.13 D4 212
.byte 116 ;74 63 14.20 D5 213
;***************************************************************************
;*  ROM DATA WINDOW FOR Fast mode  *
;* These ara the off sets to control the current output. *
;***************************************************************************
;.block 64-$%64
OffAdjFst
;Offset  BADhi
;Dec Hex  Index Volts Hex Dec
.byte 103 ;67 0 10.00 96 150
.byte 103 ;67 1 10.07 97 151
.byte 103 ;67 2 10.13 98 152
.byte 103 ;67 3 10.20 99 153
.byte 103 ;67 4 10.27 9A 154
.byte 103 ;67 5 10.33 9B 155
.byte 103 ;67 6 10.40 9C 156
.byte 103 ;67 7 10.47 9D 157
.byte 103 ;67 8 10.53 9E 158
.byte 103 ;67 9 10.60 9F 159
.byte 103 ;67 10 10.67 A0 160
.byte 103 ;67 11 10.73 A1 161
.byte 103 ;67 12 10.80 A2 162
.byte 102 ;66 13 10.87 A3 163
.byte 102 ;66 14 10.93 A4 164
.byte 102 ;66 15 11.00 A5 165
.byte 102 ;66 16 11.07 A6 166
.byte 102 ;66 17 11.13 A7 167
.byte 102 ;66 18 11.20 A8 168
.byte 102 ;66 19 11.27 A9 169
.byte 102 ;66 20 11.33 AA 170
.byte 101 ;65 21 11.40 AB 171
.byte 101 ;65 22 11.47 AC 172
.byte 101 ;65 23 11.53 AD 173
.byte 101 ;65 24 11.60 AE 174
.byte 98 ;62 25 11.67 AF 175
.byte 98 ;62 26 11.73 B0 176
.byte 98 ;62 27 11.80 B1 177
.byte 97 ;61 28 11.87 B2 178
.byte 97 ;61 29 11.93 B3 179
.byte 97 ;61 30 12.00 B4 180
.byte 96 ;60 31 12.07 B5 181
.byte 96 ;60 32 12.13 B6 182
.byte 96 ;60 33 12.20 B7 183
.byte 96 ;60 34 12.27 B8 184
.byte 95 ;5F 35 12.33 B9 185
.byte 95 ;5F 36 12.40 BA 186
.byte 95 ;5F 37 12.47 BB 187
.byte 94 ;5E 38 12.53 BC 188
.byte 94 ;5E 39 12.60 BD 189
.byte 94 ;5E 40 12.67 BE 190
.byte 93 ;5D 41 12.73 BF 191
.byte 93 ;5D 42 12.80 C0 192
.byte 93 ;5D 43 12.87 C1 193
.byte 93 ;5D 44 12.93 C2 194
.byte 93 ;5D 45 13.00 C3 195
.byte 92 ;5C 46 13.07 C4 196
.byte 92 ;5C 47 13.13 C5 197
.byte 92 ;5C 48 13.20 C6 198
.byte 91 ;5B 49 13.27 C7 199
.byte 91 ;5B 50 13.33 C8 200
.byte 91 ;5B 51 13.40 C9 201
.byte 90 ;5A 52 13.47 CA 202
.byte 90 ;5A 53 13.53 CB 203
.byte 90 ;5A 54 13.60 CC 204
.byte 89 ;59 55 13.67 CD 205
.byte 89 ;59 56 13.73 CE 206
.byte 89 ;59 57 13.80 CF 207
.byte 89 ;59 58 13.87 D0 208
.byte 88 ;58 59 13.93 D1 209
.byte 88 ;58 60 14.00 D2 210
.byte 88 ;58 61 14.07 D3 211
.byte 88 ;58 62 14.13 D4 212
.byte 87 ;57 63 14.20 D5 213
;***************************************************************************
;*  ROM DATA WINDOW FOR Rapid mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 64-$%64
OffAdjRap
;Offset  BADhi
;Dec Hex Index Volts Hex Dec
.byte 74 ;4A 0 9.00 87 135
.byte 74 ;4A 1 9.07 88 136
.byte 74 ;4A 2 9.13 89 137
.byte 73 ;49 3 9.20 8A 138
.byte 73 ;49 4 9.27 8B 139
.byte 73 ;49 5 9.33 8C 140
.byte 73 ;49 6 9.40 8D 141
.byte 73 ;49 7 9.47 8E 142
.byte 73 ;49 8 9.53 8F 143
.byte 73 ;49 9 9.60 90 144
.byte 73 ;49 10 9.67 91 145
.byte 72 ;48 11 9.73 92 146
.byte 72 ;48 12 9.80 93 147
.byte 71 ;47 13 9.87 94 148
.byte 71 ;47 14 9.93 95 149
.byte 71 ;47 15 10.00 96 150
.byte 71 ;47 16 10.07 97 151
.byte 70 ;46 17 10.13 98 152
.byte 70 ;46 18 10.20 99 153
.byte 70 ;46 19 10.27 9A 154
.byte 70 ;46 20 10.33 9B 155
.byte 70 ;46 21 10.40 9C 156
.byte 69 ;45 22 10.47 9D 157
.byte 69 ;45 23 10.53 9E 158
.byte 69 ;45 24 10.60 9F 159
.byte 68 ;44 25 10.67 A0 160
.byte 68 ;44 26 10.73 A1 161
.byte 68 ;44 27 10.80 A2 162
.byte 67 ;43 28 10.87 A3 163
.byte 67 ;43 29 10.93 A4 164
.byte 67 ;43 30 11.00 A5 165
.byte 67 ;43 31 11.07 A6 166
.byte 66 ;42 32 11.13 A7 167
.byte 66 ;42 33 11.20 A8 168
.byte 66 ;42 34 11.27 A9 169
.byte 65 ;41 35 11.33 AA 170
.byte 64 ;40 36 11.40 AB 171
.byte 63 ;3F 37 11.47 AC 172
.byte 62 ;3E 38 11.53 AD 173
.byte 61 ;3D 39 11.60 AE 174
.byte 60 ;3C 40 11.67 AF 175
.byte 59 ;3B 41 11.73 B0 176
.byte 58 ;3A 42 11.80 B1 177
.byte 57 ;39 43 11.87 B2 178
.byte 56 ;38 44 11.93 B3 179
.byte 55 ;37 45 12.00 B4 180
.byte 53 ;35 46 12.07 B5 181
.byte 52 ;34 47 12.13 B6 182
.byte 50 ;32 48 12.20 B7 183
.byte 48 ;30 49 12.27 B8 184
.byte 47 ;2F 50 12.33 B9 185
.byte 46 ;2E 51 12.40 BA 186
.byte 45 ;2D 52 12.47 BB 187
.byte 44 ;2C 53 12.53 BC 188
.byte 42 ;2A 54 12.60 BD 189
.byte 41 ;29 55 12.67 BE 190
.byte 40 ;28 56 12.73 BF 191
.byte 39 ;27 57 12.80 C0 192
.byte 37 ;25 58 12.87 C1 193
.byte 36 ;24 59 12.93 C2 194
.byte 34 ;22 60 13.00 C3 195
.byte 33 ;21 61 13.07 C4 196
.byte 31 ;1F 62 13.13 C5 197
.byte 30 ;1E 63 13.20 C6 198
;********************************************************************************
;*   ROM DATA WINDOW FOR 6V 2amp mode  *
;* These are the off sets to control the current output. *
;********************************************************************************
;.block 32-$%32
OfAd6Slo
;Offset   Volts
;Dec Hex  Index Dec Hex
.byte 137 ;89 0 5.00 4B
.byte 137 ;89 1 5.07 4C
.byte 137 ;89 2 5.13 4D
.byte 137 ;89 3 5.20 4E
.byte 137 ;89 4 5.27 4F
.byte 137 ;89 5 5.33 50
.byte 137 ;89 6 5.40 51
.byte 137 ;89 7 5.47 52
.byte 137 ;89 8 5.53 53
.byte 137 ;89 9 5.60 54
.byte 137 ;89 10 5.67 55
.byte 137 ;89 11 5.73 56
.byte 137 ;89 12 5.80 57
.byte 137 ;89 13 5.87 58
.byte 137 ;89 14 5.93 59
.byte 137 ;89 15 6.00 5A
.byte 137 ;89 16 6.07 5B
.byte 137 ;89 17 6.13 5C
.byte 137 ;89 18 6.20 5D
.byte 137 ;89 19 6.27 5E
.byte 137 ;89 20 6.33 5F
.byte 137 ;89 21 6.40 60
.byte 137 ;89 22 6.47 61
.byte 137 ;89 23 6.53 62
.byte 137 ;89 24 6.60 63
.byte 137 ;89 25 6.67 64
.byte 137 ;89 26 6.73 65
.byte 137 ;89 27 6.80 66
.byte 137 ;89 28 6.87 67
.byte 137 ;89 29 6.93 68
.byte 137 ;89 30 7.00 69
.byte 137 ;89 31 7.07 6A
;***************************************************************************
;*   ROM DATA WINDOW FOR 6V 15amp mode  *
;* These are the off sets to control the current output. *
;***************************************************************************
;.block 32-$%32
OfAd6Fst
;Offset  BADhi
;Dec Hex  Index Volts Hex Dec
.byte 107 ;6B 0 5.00 4B 75
.byte 107 ;6B 1 5.07 4C 76
.byte 107 ;6B 2 5.13 4D 77
.byte 107 ;6B 3 5.20 4E 78
.byte 107 ;6B 4 5.27 4F 79
.byte 107 ;6B 5 5.33 50 80
.byte 107 ;6B 6 5.40 51 81
.byte 107 ;6B 7 5.47 52 82
.byte 107 ;6B 8 5.53 53 83
.byte 107 ;6B 9 5.60 54 84
.byte 107 ;6B 10 5.67 55 85
.byte 107 ;6B 11 5.73 56 86
.byte 107 ;6B 12 5.80 57 87
.byte 107 ;6B 13 5.87 58 88
.byte 107 ;6B 14 5.93 59 89
.byte 107 ;6B 15 6.00 5A 90
.byte 107 ;6B 16 6.07 5B 91
.byte 107 ;6B 17 6.13 5C 92
.byte 107 ;6B 18 6.20 5D 93
.byte 107 ;6B 19 6.27 5B 94
.byte 107 ;6B 20 6.33 5F 95
.byte 107 ;6B 21 6.40 60 96
.byte 107 ;6B 22 6.47 61 97
.byte 107 ;6B 23 6.53 62 98
.byte 107 ;6B 24 6.60 63 99
.byte 107 ;6B 25 6.67 64 100
.byte 107 ;6B 26 6.73 65 101
.byte 107 ;6B 27 6.80 66 102
.byte 107 ;6B 28 6.87 67 103
.byte 107 ;6B 29 6.93 68 104
.byte 107 ;6B 30 7.00 69 105
.byte 106 ;6A 31 7.07 6A 106
;***************************************************************************
;*   ROM DATA WINDOW FOR 6V 60 amp mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 32-$%32
OfAd6Rap
;Offset  BADhi
;Dec Hex  Index Volts Hex Dec
.byte 82 ;52 0 5.00 4B 75
.byte 82 ;52 1 5.07 4C 76
.byte 82 ;52 2 5.13 4D 77
.byte 82 ;52 3 5.20 4E 78
.byte 81 ;51 4 5.27 4F 79
.byte 81 ;51 5 5.33 50 80
.byte 81 ;51 6 5.40 51 81
.byte 81 ;51 7 5.47 52 82
.byte 80 ;50 8 5.53 53 83
.byte 80 ;50 9 5.60 54 84
.byte 80 ;50 10 5.67 55 85
.byte 80 ;50 11 5.73 56 86
.byte 79 ;4F 12 5.80 57 87
.byte 79 ;4F 13 5.87 58 88
.byte 79 ;4F 14 5.93 59 89
.byte 79 ;4F 15 6.00 5A 90
.byte 79 ;4F 16 6.07 5B 91
.byte 79 ;4F 17 6.13 5C 92
.byte 79 ;4F 18 6.20 5D 93
.byte 79 ;4F 19 6.27 5E 94
.byte 78 ;4E 20 6.33 5F 95
.byte 78 ;4E 21 6.40 60 96
.byte 78 ;4E 22 6.47 61 97
.byte 78 ;4E 23 6.53 62 98
.byte 78 ;4E 24 6.60 63 99
.byte 78 ;4E 25 6.67 64 100
.byte 78 ;4E 26 6.73 65 101
.byte 78 ;4E 27 6.80 66 102
.byte 78 ;4E 28 6.87 67 103
.byte 78 ;4E 29 6.93 68 104
.byte 78 ;4E 30 7.00 69 105
.byte 77 ;4D 31 7.07 6A 106
;****************************************************************************
;*                Interrupt vectors                   *
;****************************************************************************
 .org 0FF0h
ADC
 JP ADINT
TIMER
 JP PwrCon
INT2
 NOP
 RETI
INT1
 NOP
 RETI
 .org 0FFCh
NMI
 JP IT_TIMER
RST
 JP RESET
 .END
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------71224D.asm
;Checksum
;Raw Code: 71808
;With Info: 6FF42
;***************************************************************************
;*  COPYRIGHT 2004 SCHUMACHER ELECTRIC  *
;*   ALL RIGHTS RESERVED   *
;*
;*     *
;* Digital DieHard 71224 2/15/50/125A Charger/Starter/Tester *
;* This code is for the SGS-THOMPSON micro-controler *
;* Part number ST62T25/ST62E25   *
;*        *
;*;****************************************************************************
 .title″Digital DieHard 71224 Charger Ver. 0.19″
 .LINESIZE 131
 .vers″ST6225″
 .romsize 4
 .w_on
DEBUG .SET 0;1->normal,0->Ignore Type and Rate switches after SS5
ShoOff .SET 0;1->normal,0->Show OFFSET in Alt% mode during charging
FastCP .SET 1;1->normal,0->3min ChkProg interval instead of 60min
ShoADC .SET 1;1->normal,0->Use PB2 to indicate A/D activity
LongTst .SET 1;1->normal,0->Set manual mode for 255(not 1)hours
AdjOff .SET 1;1->normal,0->Allow manual adjustment of OFFSET(SS15)
;***************************************************************************
;* Define the port hardware locations  *
;***************************************************************************
;* At times,the .def statement is followed by a value and″!m″.The !m *
;* is used by the simulator/emulator for debugging. This symbol tells the *
;* equipment what registers the user wants to monitor during debuging.   *
;***************************************************************************
X .def 80h!m      ;Index register
Y .def 81h       ;Index register
V .def 82h       ;Short direct register
W .def 83h         ;Short direct register
A .def 0ffh!m      ;Accumulator
DRA .def 0c0h!m        ;Port a data register
DRB .def 0c1h!m        ;Port b data register
DRC .def 0c2h         ;Port c data register
DDRA .def 0c4h          ;Port a direction register
DDRB .def 0c5h          ;Port b direction register
DDRC .def 0c6h          ;Port c direction register
ORA .def 0cch         ;Port a option register
ORB .def 0cdh         ;Port b option register
ORC .def 0ceh         ;Port c option register
ADR .def 0d0h!m        ;A/D data register
ADCR .def 0d1h          ;A/D control register
PSC .def 0d2h         ;Timer prescaler register
TCR .def 0d3h!m        ;Timer counter register
TSCR .def 0d4h          ;Timer status control register
WDR .def 0d8h           ;Watchdog register
IOR .def 0c8h!m        ;Interrupt option register
DRWR .def 0c9h            ;Data rom window register
;****************************************************************************
;*    These are the ram equates used by the battery charger.      *
;****************************************************************************
DRAbuf .def084h ;shadow ram for port A data register
DRBbuf .def085h ;shadow ram for port B data register
DRCbuf .def086h ;shadow ram for port C data register
ATemp .def 087h ;Accumulator temporary storage
XTEMP .def 088h ;X register temporary storage
MSecs1 .def089h ;storage for 8.333ms ties-count of 120=1sec
Secs1 .def08Ah ;storage for timer1 seconds
Mins1 .def 08Bh ;storage for timer1 minutes
Hrs1 .def 08Ch ;storage for timer1 hours
TicFlag1 .def 08Dh ;overflow flags for Secs1,Mins1,and hours
MSecs2 .def 08Eh ;millisecond one counter
Secs2 .def 08Fh ;storage for timer2 seconds
Mins2 .def 090h ;storage for timer2 minutes
Hrs2 .def 091h ;storage for timer2 hours
TicFlag2 .def 092h ;overflow flags for Secs1,Mins2,and hours1
Tries .def 093h ;used by battery detect routines
TEMP .def 094h ;scratch pad area
TEMP1 .def 095h ;scratch pad area
Temp2 .def 096h ;count used for FreshBV
CurVolt .def 097h ;current battery voltage
MaintVolt .def 098h ;storage for MAINTAIN voltage level
OldVolt .def099h ;previous battery voltage.used for dy/dt
CCDcnt .def 09Ah ;display countdown during crank cool down
OldOff .def 09Bh ;old value of OFFSET used in dI/dt
BADlo .def 09Ch ;low bits battery voltage average
BADhi .def 09Dh ;hi bits battery voltage average
Vmax .def 09Eh ;maximum battery voltage(per Battery Type)
Vref .def 09Fh ;ref voltage for desulfation
OFFSET .def 0A0h ;storage for phase delay value
FreshBV .def 0A1h ;avg batt volt used for di/dt ref
FBVTotLo .def 0A2h ;low byte of total used for FreshBV
FBVTotHi .def 0A3h ;high byte of total used for FreshBV
CurentSS .def 0A4h ;stores current charger state
Flags .def 0A5h ;charger configuration states
  ;bit 0(BatTypeA): 0 for Reg,1 for D/C
  ;bit 1(BatTypeB): 0 for Norm,1 for AGM/GEL
  ;bit 2(Rate):  0 for Slow,1 for Fast
  ;bit 3(Crank):  1 if in Boost mode
  ;bit 4(CrankWait): 1 during E/S cool down
  ;bit 5(Started):  1 if eharging started
  ;bit 6(MtrUnits): 0 for Volts,1 for %
  ;bit 7(MtrScale): 0 for Batt,1 for Alt
Flags2 .def 0A6h ;stores the following Flags
  ;bit 0(Batt):  1 if battery connected
  ;bit 1(Rapid): 1 if set for Rapid charge rate
  ;bit 2(Bat6V): 1 if set for 6V battery
  ;bit 3(Power): 1 if output is on
  ;bit 4(NMInt): 1 if NMI interrupt,0 if Timer
  ;bit 5(ChMode): 1 if in Charger Mode
  ;bit 6(Wait0P): 1 if waiting for % to change from 0
  ;bit 7(Alert): 1 indicates Alert condition
Flags3 .def 0A7h ;stores the following Flags
  ;bit 0(RmpInt): 1 during 1st half of each Ramp interval
  ;bit 1(Settle): 1 during voltage settle time
  ;bit 2(HiEnd): 1 if higher voltage for EndCharge
  ;bit 3(Idle): 1 until a button is pressed
  ;bit 4(Hi6V): 1 if battery>8.5V
  ;bit 5(NxtCnt): 1 ->1st second of count
  ;bit 6(Manual): 1 if in Manual Mode
  ;bit 7(BurnIn): 1 if in Burn-in Mode
SwDown .def 0A8h ;Indicates state of switches(1->pressed)
  ;bit 4=SwOff flag(debugging)
  ;bit 5=Type switch
  ;bit 6=Rate switch
  ;bit 7=Meter switch
DigiDat2 .def 0A9h ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 3 segments B & C
  ;bit 1=digit 2 segment F
  ;bit 2=digit 2 segment G
  ;bit 3=digit 2 segment A
  ;bit 4=digit 2 segment B
  ;bit 5=digit 2 segment C
  ;bit 6=digit 2 segment D
  ;bit 7=digit 2 segment E
DigiDat1 .def 0AAh ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 1 segment C
  ;bit 1=digit 1 segment G
  ;bit 2=digit 1 segment D
  ;bit 3=digit 1 segment E
  ;bit 4=digit 2 decimal point
  ;bit 5=digit 1 segment F
  ;bit 6=digit 1 segment A
  ;bit 7=digit 1 segment B
SwData .def 0ABh ;data for the 3 Rate and 3 Type LEDs(0->ON,1->off)
  ;bit 0=6V battery type LED
  ;bit 1=Reg battery type LED
  ;bit 2=D/C battery type LED
  ;bit 3=AGM battery type LED
  ;bit 4=60A charge rate LED
  ;bit 5=15A charge rate LED
  ;bit 6=300A charge rate LED
  ;bit 7=2A charge rate LED
BitCnt .def 0ACh ;Index of bit sent to display
BytCnt .def 0ADh ;Index of word sent to display
DataBuf.def 0AEh ;Temp storage for Data bits
VltCnt .def 0AFh ;Counter for voltage display interval
TempOff .def 0B0h ;temp offset value
RmpCnt .def 0B1h ;counts ramp intervals until next ramp
LEDnum .def 0B2h ;stores number to be shown on digital LED
Percent .def 0B3h ;stores percent to be shown on digital LED
Index .def 0B4h ;used for look up table access
LowOff.def 0B5h ;min offset value for di/dt(highest current)
VRent .def 0B6h ;Counter for voltage regulation interval
PcntL .def 0B7h ;NMI counter for percent display update
PcntH .def 0B8h ;Interval counter for percent display update
DspPcnt .def 0B9h ;storage for last percent displayed
Flags4 .def 0BAh ;stores the following Flags
  ;bit 0(IdleSet): 1 if 10 minute Idle timer was started
  ;bit 1(NoRamp): 1 during Manual Fast charge
  ;bit 2(SOC):  1 if at start of charge(1st 5s)
  ;bit 3(Crnkng): 1 if cranking(State 19)
  ;bit 4(HiPwr):  1 if charge rate>Fast
  ;bit 6(Restore): 1 if in desulfation mode(SS9)
LastBatt .def 0BBh ;stores battery reading used to monitor progress
;free .def 0BCh ;free
ORBbuf .def 0BDh ;shadow RAM for ORB register
;free .def 0BEh ;free
;free .def 0BFh ;free
;0BFh=last RAM location
;***************************************************************************
;*These are the constants used by the battery charger.  *
;***************************************************************************
Volts005 .equ 008h ;0.5VOLTS
Volts0 .equ 00Ah;0.7VOLTS
Volts01 .equ 00Fh ;1.0VOLTS
Volts016 .equ 017h ;miminum voltage for engine start,1.5V
Volts02 .equ 01Eh ;2.0VOLTS
Volts05 .equ 04Bh ;5.0VOLTS
Volts06 .equ 05Ah;6.0VOLTS
Volts066 .equ 061h ;6.6VOLTS
Volts075 .equ 071h ;7.5VOLTS
Volts09 .equ 087h ;very discharged battery voltage
Volts10 .equ 096h ;10.0VOLTS
BattMin .equ 0AFh ;lowest value in Battery % LUT
Volts12 .equ 0B4h ;low battery voltage
Volts122 .equ 0B7h
Volts125 .equ 0BCh
BattMax .equ 0BDh ;highest value in Battery % LUT
Volts127 .equ 0BEh
Volts128 .equ 0C0h ;good battery test voltage
Volts13 .equ 0C3h
Volts132 .equ 0C6h
Volts135 .equ 0CAh
AltMin .equ 0CBh ;lowest value in Alternator % LUT
Volts138 .equ 0CFh
Volts14 .equ 0D2h
Volts142 .equ 0D5h ;start monitoring dy/dt voltage
Volts1435 .equ 0D7h
Volts144 .equ 0D8h
Volts146 .equ 0DAh;maximum allowed voltage for reg/gel mode
Volts147 .equ 0DCh ;start trickie timer voltage
Volts149 .equ 0E0h ;14.87V
Volts15 .equ 0E1h ;maximum allowed voltage for RV/DC Marine
Volts15a .equ 0E2h;15.07V
AltMax .equ 0E7h ;highest value in Alternator % LUT
Volts 155 .equ 0E9h ;maximum allowed voltage for Auto/Marine Starting
Volts16 .equ 0F0h ;maximum allowed voltage
Volts165 .equ 0F7h ;maximum allowed voltage for deep cycle 2
Volts17 .equ 0FCh ;maximum allowed voltage
MaxVolts .equ 0FFh;maximum voltage reading-17.0V
RCinitR .equ 105;ramp count intervals for Rapid rate
RCinitF .equ 180;ramp count intervals for Fast rate
RIinit .equ 60 ;NMI interrupts per 1/2 ramp count interval
MSINIT .equ 078h ;millisecond initialization value(120)
MS500 .equ 03Ch ;millisecond counter value for 500mS(60)
MS200 .equ 018h ;millisecond counter value for 200mS(24)
SecInit .equ 03Ch ;second initialization value(60)
MinInit .equ 03Ch ;minute initialization value(60)
MaxHrs .equ 25;maximum allowed charge hours+1
CPint .equ 60;minutes per charge progress interval
HR  .equ 000h ;hours bit of TicFlag1 and TicFlag2
MIN  .equ 001h ;minutes bit of TicFlag1 and TicFlag2
SEC .equ 002h ;seconds bit of TicFlag1 and TicFlag2
MSEC .equ 003h ;milliseconds
VLO .equ 0C0h ;low line limit-100VAC
VHI .equ 0EEh ;high line voltage limit-130VAC
BatLoSlo .equ 096h ;low battery voltage current adjust-10.0Vdc
BatLoFst .equ 096h ;low battery voltage current adjust-10.0Vdc
BatLoRap .equ 096h ;low battery voltage current adjust-10.0Vdc
Bat6LoSlo .equ 04Bh ;low battery voltage current adjust-5.0Vdc
Bat6LoFst .equ 043h ;low battery voltage current adjust-4.5Vdc
Bat6LoRap .equ 043h ;low battery voltage current adjust-4.5Vdc
;BatHiSlo .equ 0D5h
;BatHiFst .equ 0C6h
PCint .equ 00Ah ;number of 1-second intervals between % updates
FULLTIME .equ 0ADh ;half second when AC power is OFF
SlowAmps .equ 2;Nominal amps out at Slow rate
FastAmps .equ 15;Nominal amps out at Fast rate
RapAmps .equ 40;Nominal amps out at Rapid rate
CrnkAmps .equ 100;Nominal amps out at Crank rate
CodeRev .equ 0;software revision level
OffLowSlo .equ 132;Lowest current in 12V 2A offset table
OffSlow .equ 126;Nominal offset for slow charge(~20%)
OffHiSlo .equ 119;Current in 12V 2A offset table for 14.0V
MinOffSlo .equ 117;Max Current for 12V 2A rate during di/dt
OffLowFst .equ 107;Lowest current in 12V Fast offset table
OffFast .equ 107;Nominal offset for fast charge(15A)
OffHiFst .equ 99;Highest current in 12V Fast offset table
MinOfFst .equ 88;Max Current for 12V Fast rate during di/dt
OffRamp .equ 76;offset for Fast<>Rapid transition
OffRap .equ 80;Nominal offset for rapid charge(~90%)
OffLowRap .equ 80;Lowest current in 12V rapid offset table
OffHiRap .equ 30;Highest current in 12V rapid offset table
OffCrank .equ 95;OFFSET for Crank standby
Off6LoSlo .equ 135;First entry in 6V 2A offset table
Off6Slo .equ 136;Nominal offset for 6V slow charge(2A)
Off6HiSlo .equ 136;Current in 6V 2A offset table for 7.0V
Min6OffSlo .equ 134;Max Current for 6V 2A rate during di/dt
Off6LoFst .equ 121;Lowest current in 6V 15A offset table
Off6Fst .equ 117;Nominal offset for 6V fast charge(15A)
Off6HiFst .equ 117;Highest current in 6V 15A offset table
Min6OfFst .equ 115;Max Current for 6V 15A rate during di/dt
Off6Rap .equ 88;Nominal offset for 6V rapid charge(60A)
Off6LoRap .equ 88;Lowest current in 6V 60A offset table
Off6HiRap .equ 82;Highest current in 6V 60A offset table
Off6Crnk .equ 105;OFFSET for 6V Crank standby
HiOff .equ 140;high limit for OFFSET variable
HiOff6.equ 150;high limit for OFFSET variable(6V mode)
ABORT .equ 008h ;abort state
LEDslow .equ 007h ;Slow LED-bit of SwData
LEDboost .equ 006h ;Crank LED-bit of SwData
LEDfast .equ 005h ;Fast LED-bit of SwData
LEDrap .equ 004h ;Rapid LED-bit of SwData
LEDgel .equ 003h ;AGM/Gel LED-bit of SwData
LEDdeep .equ 002h ;Dp Cycl LED-bit of SwData
LEDreg .equ 001h ;Regular LED-bit of SwData
LED6V .equ 000h ;6V Reg LED-bit of SwData
LEDdone .equ 000h ;Charged LED-PORT A
LEDchgng .equ 001h ;Charging LED-PORT A
LEDalert .equ 002h ;Fault LED-PORT A
LEDprcnt .equ 003h ;Percent LED-PORT A
LEDvolt .equ 004h ;Voltage LED-PORT A
LEDalt .equ 005h ;Altrntr LED-PORT A
SerData .equ 006h ;Serial Data-PORT A
ClrData .equ 007h ;Data Clear-PORT A
ShftClk .equ 000h ;Shift Clock-PORT B
LtchClk .equ 001h ;Latch Clock-PORT B
ESrly .equ 003h ;E/S relay-PORT B
Disable .equ 006h ;Disable ctrl-PORT B
SCRs .equ 007h ;SCR control-PORT B
FanCtl .equ 004h ;Fan control-PORT C
TypeSw .equ 005h ;Type switch-PORT C
RateSw .equ 006h ;Rate switch-PORT C
MeterSw .equ 007h ;Meter switch-PORT C
SwOff .equ 004h ;bit in SwDown for disabled Type & Rate switches
BatTypeA .equ 000h ;bit in Flags for battery type:0=Reg,1=D/C
BatTypeB .equ 001h ;bit in Flags for battery type:1=AGM/Gel Cell
Rate .equ 002h ;bit in Flags for charge rate:0=Slow,1=Fast
Crank .equ 003h ;bit in Flags that indicates engine start
CrankWait .equ 004h ;bit in Flags that indicates cool down between cranks
Started .equ 005h ;bit in Flags that indicates charge started
MtrUnits .equ 006h ;bit in Flags for meter units:0=volts,1=%
MtrScale .equ 007h ;bit inFlags for meter scale:0=batt,1=altrntr
Batt .equ 000h ;bit in Flags2:1 ifbattery is connected
Rapid .equ 001h ;bit in Flags2:1 if charge rate is Rapid
Bat6V .equ 002h ;bit in Flags2:1 if output is>10A
Power .equ 003h ;bit in Flags2:1 if output is on
NMInt .equ 004h ;bit in Flags2:1 if NMI interrupt,0 if Timer
ChMode .equ 005h ;bit in Flags2:1 if in Charger mode(not Tester)
Wait0P .equ 006h ;bit in Flags2:1 if battery>10V
Alert .equ 007h ;bit in Flags2:1 indicates trouble
RmpInt .equ 000h ;bit in Flags3:1 during 1st half each Ramp interval
Settle .equ 001h ;bit in Flags3:1 during voltage settle time
HiEnd .equ 002h ;bit in Flags3:1 if higher voltage for EndCharge
Idle .equ 003h ;bit in Flags3:1 until a button is pressed
Hi6V .equ 004h ;bit in Flags3:1 if battery>8.5V
NxtCnt .equ 005h ;bit in Flags3:0 during last half of CCDcnt interval
Manual .equ 006h ;bit in Flags3:1 during Manual modes
BurnIn .equ 007h ;bit in Flags3:1 during Burn-In mode
IdleSet .equ 000h ;bit in Flags4:1 if 10 minute Idle timer was started
NoRamp .equ 001h ;bit in Flags4:1 during manual fast charge
SOC .equ 002h ;bit in Flags4:1 during Start Of Charge(1st 5sec)
Crnkng .equ 003h ;bit in Flags4:1 during cranking(State19)
HiPwr .equ 004h ;bit in Flags4:1 if charge rate>Fast
Restore .equ 006h ;bit in Flags4:1 if in desulfation routine
CrankOff .equ 180;crank off time in seconds
CrankON .equ 5;crank on time in seconds
CCDint .equ 001h ;crank cool down display counter interval(seconds)
CrankSS .equ 010h ;crank SS is state 16=10 hex
Decimal .equ 004h ;bit in DigiDatl for decimal point
Digitl .equ 000h ;bit in DigiDat2 for most significant 1
SwsOff .equ 11111111b ;bit pattern for all switches off
DigiOffa .equ 11111111b ;bit pattern for all segements off
DigiOffb .equ 11111111b ;bit pattern for all segements off
DigiONa .equ 00000000b ;bit pattern for all segements ON
DigiONb .equ 00000000b ;bit pattern for all segements ON
Dashes1 .equ 11111101b ;bit pattern to display_-
Dashes2 .equ 11111011b ;bit pattern to display_-_
DigiRev1 .equ 00010010b ;bit pattern to display_0
DigiRev2 .equ 01100001b ;bit pattern to display_P_
DigiMV1 .equ 11010011b ;bit pattern to display_L
DigiMV2.equ 00000101b ;bit pattern to display_O_
;****************************************************************************
;*                COLD START                *
;****************************************************************************
;.org 0880h ;for ST6210/15
 .org 0100h ;for ST6220/25
RESET
 CALL RstWDR ;reset watch dog timer
;****************************************************************************
;*              Clear The Ram Area               *
;****************************************************************************
RAMCLR
 LDI X,084h ;point X to 1st RAM Location
RAMCLR1
 CLR A  ;clear A
 LD(X),A ;store A at location pointed to by X
 INC X  ;increment X
 LD A,X  ;get pointer in A
 CPI A,0C0h ;test for end of RAM
 JRNZRAMCLR1 ;do again if not finished
;****************************************************************************
;*           Now Set Up The Hardware I/O Ports           *
;****************************************************************************
PORTA
 ;Bit 0=LED-Done(Output,0=ON)
 ;Bit 1=LED-Charging(Output,0=ON)
 ;Bit 2=LED-Alert(Output,0=ON)
 ;Bit 3=LED-Battery%(Output,0=ON)
 ;Bit 4=LED-Volts DC(Output,0=ON)
 ;Bit 5=LED-Altrntr%(Output,0=ON)
 ;Bit 6=Serial Data(Output,0=ON)
 ;Bit 7=Display Clear(Output,0=clear)
 ;Bit# 76543210
 LDI DDRA,11111111b ;Set all bits as outputs
 LDI ORA,11000000b ;open-drain outputs 0-5;6-7 push-pull
 LDI DRA,11111111b ;Set initial values to 1(off)
 LDI DRAbuf,11111111b ;store settings in shadow RAM
PORTB
 ;Bit 0=Shift clock(Output,0->1=Shift)
  ;Bit 1=Latch clock(Output,0->1=Latch)
  ;Bit 2=LED-Amps(not used)
  ;Bit 3=E/S relay(Output,0=Charge,1=Start)
  ;Bit 4=Batt sense(not used)
  ;Bit 5=Batt Voltage(Input,Analog)
  ;Bit 6=Disable out(Output,1=disabled)
  ;Bit 7=SCR drive(Output,0=ON)
  ;Bit# 76543210
 LDI DDRB,11011111b ;bits 5 is input,others are outputs
 LDI ORB,11111111b ;PB5 analog;others push-pull
  LDI DRB,11100111b ;initialize high except 3-4
 LDI DRBbuf,11100111b ;store settings in shadow RAM
 PORTC
  ;Bit 4=Fan Control(Output,0=off,1=ON)
  ;Bit 5=Type switch(Input,0=IN/change)
  ;Bit 6=Rate switch(Input,0=IN/change)
  ;Bit 7=Meter switch(Input,0=IN/change)
  ;Bit# 76543210
 LDI DDRC,00011111b ;bit 4 is output,others are inputs
 LDI ORC,00011111b ;non-interrupt inputs,push-pull output
 LDI DRC,00001111b ;Set internal pull-ups for bits 5-7
 LDI DRCbuf,00001111b ;store settings in shadow RAM
TSCRINIT
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 SET 4,IOR      ;enable interupts
 RETI
 CALL InitState ;initialize to slow(2A)auto mode
;The next three lines are to set the maximum idle tester time
 CALL IniTime1  ;initialize timer 1
 LDI Mins1,0Ah ;set timer 1 for 10 minutes
 SET Idle,Flags3;indicates no buttons pressed yet
;The next three lines set the unit for Tester(not Charger)mode
 RES ChMode,Flags2 ;set for Tester Mode
 CALL ShowData ;initialize display
INIT_01
;JP MAIN  ;debug
;***************************************************************************
;*    Test Routines    *
;* This routine checks the switches at power up to determine whether to *
;* enter one of the test modes. The possible test modes and the switch *
;* combinations that trigger them are as follows.    *
;*        *
;* Meter Rate Type Test Mode     *
;* Y x N Power On SelfTest(POST): LED′s light in sequence *
;* N Y N Manual Slow Charge(1 hour max for all manual mode) *
;* N N  Y Manual Medium Charge(Fast for boost models)  *
;* N Y  Y Manual Fast Charge(Fast-Rapid for boost models)  *
;* Y x Y Burn-In Mode: Fast/Rapid Charge for 60minutes *
;*        *
;* Y->pressed,N->not pressed,x->either(not checked)  *
;*        *
;***************************************************************************
TEST
 JRS MeterSw,DRC,NoPOST ;Skip ahead if Meter Mode button not pressed
 JRS TypeSw,DRC,POST ;Skip to POST if Type button not pressed
 JP TestBI ;...otherwise,skip ahead to Burn-In setup
NoPOST
 JRR RateSw,DRC,TEST1;Check Type switch if Rate switch is pressed
 JRS TypeSw,DRC,NoTest ;go to MAIN if no switch is pressed
  ;Set for Manual Fast Charge
 SET Rate,Flags  ;turn on Fast LED,turn off Slow LED
 RES Rapid,Flags2 ;turn off Rapid LED
  RES HiPwr,Flags4 ;turn off high power mode
;SET NoRamp,Flags4 ;set for Fast rate w/o ramp up to Rapid
 LDI OFFSET,OffFast ;set for Fast rate
  JP TestMM1  ;set for Manual charge
NoTest
 JP MAIN  ;skip test and go to MAIN
TEST1  ;Set for manual Slow Charge
  JRR TypeSw,DRC,TEST2;if Type switch is pressed,set for Fast Test
 CALL SetSlow ;set for Slow Rate
 CALL StartSlow ;set OFFSET for Slow rate
;LDI OFFSET,OffSlow ;set Offset for 2A
 JP TestMM1  ;set for Manual charge
TestBI  ;Set for 60minute Burn-In
 SET BurnIn,Flags3 ;Set for Burn-In mode
 LDI OFFSET,OffFast ;set for Fast rate
 RES HiPwr,Flags4;turn off high power
 CALL SetRmpUp ;prepare to ramp from Fast to Rapid
TEST2  ;set for Manual Rapid Charge
;SET Manual,Flags3 ;set for Manual mode
 SET Rate,Flags  ;set for non-Slow rate
 SET Rapid,Flags2 ;turn on Rapid LED
;RES NoRamp,Flags4 ;set for ramping
 JRS BurnIn,Flags3,TestRap ;don′t set for ramp down if Burn-In
 SET HiPwr,Flags4 ;turn on high power
 LDI RmpCnt,RCinitR ;set counter for Rapid
;RES RampUp,Flags3 ;set for ramp down
 LDI OFFSET,OffRap ;set Offset for Rapid Charge
 CALL SetRamp ;set ramping parameters
TestRap
  JP TestMM1  ;set for Manual charge
POST
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
 CALL MeterOff ;turn off all meter mode LED′s
 CALL DigitsOff ;turn off 3-digit LED
 RES Power,Flags2 ;make sure output will be off
;show status LED′s
 CALL ShowGreen ;light Green LED only
 CALL FifthSecond ;wait one Fifth second
 CALL ShowChgng ;light Charging LED
 CALL FifthSecond ;wait one Fifth second
 CALL AlertON ;turn on Alert(Red)LED
 CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
;show charge rate LED′s
 SET ChMode,Flags2 ;must set flag to show rate LED′s
 RES Crank,Flags ;turn off Crank LED
 CALL SetSlow ;set for Slow Rate
 LDI LEDnum,SlowAmps ;set digital LED to show Slow rate
  CALL HoldRate ;show Rate and wait a Fifth second
 SET Rate,Flags  ;turn on Fast LED
 LDI LEDnum,FastAmps ;set digital LED to show Fast rate
  CALL HoldRate ;show Rate and wait a Fifth second
 SET Rapid,Flags2 ;turn on Rapid LED
 LDI LEDnum,RapAmps ;set digital LED to show Rapid rate
  CALL HoldRate ;show Rate and wait a Fifth second
 RES ChMode,Flags2 ;clear flag to disable output
 LDI LEDnum,CrnkAmps ;set digital LED to show Crank rate
 CALL ShowNum ;get data to show the LED number
  CALL ShowCrank ;turn on Crank(Boost)LED
  CALL FifthSecond ;wait one Fifth second
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
 CALL ShowData ;update display
;show battery type LED′s
 CALL Set12V ;set for Regular,12V battery
 LDI DigiDat1,DigiRev1;set digital LED to show Code Revision
 LDI DigiDat2,DigiRev2;set digital LED to show Code Revision
  CALL HoldType ;show Type and wait a Fifth second
 SET BatTypeA,Flags ;turn on Deep Cycle & turn off Regular LED
  CALL HoldType ;show Type and wait a Fifth second
 SET BatTypeB,Flags ;turn on Gel/AGM LED
 RES BatTypeA,Flags ;turn off Deep Cycle LED
  CALL HoldType ;show Type and wait a fifth second
;RES BatTypeB,Flags ;turn off Gel/AGM LED
;SET Bat6V,Flags2  ;turn ON 6V LED
;CALL HoldType ;show Type and wait a Fifth second
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
;RES Bat6V,Flags2  ;set for 12V battery(not 6V)
;show display mode LED′s
 CALL ShowData ;update display
 SET MtrUnits,Flags ;set for % LEDs ON,volts LED off
 RES MtrScale,Flags ;set for Alternator % LED off
 CALL HoldMtrMd ;show meter mode and wait one fifth second
 RES MtrUnits,Flags ;set for Volts LED ON,batt% LED off
 CALL HoldMtrMd ;show meter mode and wait one fifth second
 SET MtrUnits,Flags ;set for % LEDs ON,volts LED off
 SET MtrScale,Flags ;set for Alternator % LED ON
 CALL HoldMtrMd ;show meter mode and wait one fifth second
 CALL MeterOff ;turn off all meter mode LED′s
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 LDI LEDnum,5  ;initialize to 5 to show 4 1st
POST2
 DEC LEDnum  ;the next number will be 1 less
 CALL NumData  ;get data for,and show LED number
 CALL FifthSecond ;wait one fifth second
 LD A,LEDnum  ;check for last number
 JRNZ POST2  ;loop back and repeat if not there
POST3
 ADDI A,20  ;adding 20 changes 2nd digit
 LD LEDnum,A  ;prepare to show new number
 CALL NumData  ;get data for,and show LED number
 CALL FifthSecond ;wait one fifth second
 LD A,LEDnum  ;check latest number
 CPI A,100  ;compare to last number
 JRNZ POST3  ;loop back and repeat if not there
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL InitState  ;reset to Slow,TypeA charge mode
 RES ChMode,Flags2 ;set for Tester mode
 JP TEST  ;repeat POST if necessary
TestMM1  ;Set for manual charge
 SET Manual,Flags3 ;set for Manual mode
 SET ChMode,Flags2 ;set for Charger Mode(output enabled)
 RES Disable,DRBbuf ;enable output
 LDI CurentSS,15 ;State 15 is Manual charge
 SET Started,Flags ;set Flags for charge started
 SET Power,Flags2  ;tell PwrCon charger is on
 CALL IniTimel  ;initialize Timer1
 .IFC NE LongTst ;assemble next line only if not debugging
 LDI Hrs1,1  ;set Timer1 for 1 hour
 .ELSE  ;assemble next line only if debugging
 LDI Hrs1,255  ;set Timer1 for 255 hours
 .ENDC
 JRR BurnIn,Flags3,MAIN ;skip next 2 lines ifnot Burn-in
 TestMM2
 CALL IniTime2  ;reset Timer2
 LDI Mins2,1  ;set timer for counter interval(1 minute)
 LDI CCDcnt,60  ;set Burn-in minute counter to 60
;***************************************************************************
;*                MAIN                           *
;***************************************************************************
;***************************************************************************
;*Because the A/D voltage is being averaged,it would take considerable  *
;*time to notice that a battery has become disconnected.To overcome this  *
;*DELAY the program will monitor the instantaneous voltage each time thru  *
;*the loop to detect this condition.This check will be made only if the  *
;*unit is in a charging mode.                            *
;***************************************************************************
MAIN
 CALL RstWDR   ;reset watch dog timer
 LD A,CurentSS  ;get current state
 CPI A,ABORT   ;check for abort
 JRNZ MainMore  ;continue Main if not Abort
 JP MAIN3  ;don′t continue Main if Abort
MainMore
 JRR Manual,Flags3,MainAuto ;continue Main ifnot Manual Mode
 JP SS15   ;otherwise,goto Manual charge
MainAuto
 JRS CrankWait,Flags,MAIN1 ;don′t check switches during Crank wait
 CALL CheckSw  ;check if switch is being pressed
MAIN4
 JRS Crank,Flags,MAIN0 ;skip ahead if during Crank
 CALL GetPercent  ;update the percentage reading
 CALL UpdateBP  ;update % to display
 CALL GetMeter  ;update display
 JRR Idle,Flags3,MAIN0  ;skip ahead if not idle
 JRR Batt,Flags2,MAIN0 ;don′t check idle time limit if no battery
 JRS IdleSet,Flags4,MAIN5;don′t set idle timer if already set
 CALL IniTime1  ;...otherwise initialize timer 1
 LDI Mins1,0Ah  ;set tiner 1 for 10 minutes
 SET IdleSet,Flags4  ;Idle timer started,set flag
MAIN5
 JRR MIN,TicFlag1,MAIN0 ;...otherwise,check idle time limit
 RES Disable,DRBbuf  ;...enable output after idle time limit
 JP MAIN2   ;...and re-initialize if reached
MAIN0   ;not Crank,check for 0 or 1
 JRS Power,Flags2,MAIN1 ;charger is ON,goto 0V check
 JRS LEDchgng,DRAbuf,MAIN3;charger not almost on,skip 0V check
MAIN1  ;Check for disconnected battery
 CALL CheckBatt  ;check for disconnected battery
 JRS Batt,Flags2,MAIN3 ;skip ahead if connected
MAIN2  ;0V detected,prepare to start over from state 0
 LDI DspPcnt,0   ;initialize display Percent to 0
 CALL InitState  ;initialize to Slow Regular Charge mode
MAIN3
;***************************************************************************
;*            SEQUENCE STATE JUMP TABLE                     *
;*Determine what routine to execute on this pass through the the loop.Only*
;*one routine is executed each time through the loop.              *
;***************************************************************************
NSS0
 LD A,CurentSS
 JRNZ NSS1
 JP SS0;*SS0-BATTERY DETECT *
NSS1
 CPI A,001h
 JRNZ NSS2
 JP SS1;*SS1-BATTERYDETECTDELAY *
NSS2
 CPI A,002h
 JRNZ NSS3
 JP SS2;*SS2-AUTOMATIC CHARGE START *
NSS3
 CPI A,003h
 JRNZ NSS4
 JP SS3 ;* SS3-BELOW 9 Volts *
NSS4
 CPI A,004h
 JRNZ NSS5
 JP SS4 ;* SS4-BELOW 12 Volts *
NSS5
 CPI A,005h
 JRNZ NSS8
 JP SS5 ;* SS5-NORMAL CHARGE *
NSS6
;CPI A,006h
;JRNZ NSS7
;JP SS6 ;* SS6-dv/dt MONITOR *NOT USED
NSS7
;CPI A,007h
;JRNZ NSS8
;JP SS7 ;* SS7 - CHARGE COMPLETE * NOT USED
NSS8
 CPI A,008h
JRNZ NSS9
 JP SS8 ;* SS8-ABORT CHARGE *
NSS9
 CPI A,009h
 JRNZNSS11
 JP SS9 ;* SS9-DESULFATION *
NSS10
;CPI A,00Ah
;JRNZ NSS11
;JP SS10 ;* SS10-RESTORE CHARGE *
NSS11
 CPI A,00Bh
 JRNZ NSS12
 JP SS11 ;* SS11-dV/dt MONITOR *
NSS12
 CPI A,00Ch
 JRNZ NSS13
 JP SS12 ;* SS12-dI/dt MONITOR *
NSS13
 CPI A,00Dh
 JRNZ NSS14
 JP SS13;*SS13-ENDCHARGE *
NSS14
 CPI A,00Eh
 JRNZ NSS15
 JP SS14;*SS14-MAINTAIN *
NSS15
 CPI A,00Fh
 JRNZ NSS16
 JP SS15 ;* SS15-Manual *
NSS16
 CPI A,010h
 JRNZNSS17
 JP SS16 ;* SS16-CRANK *
NSS17
 CPI A,011h
 JRNZ NSS18
 JP SS17 ;* SS17-CRANK *
NSS18
 CPI A,012h
 JRNZ NSS19
 JP SS18 ;* SS18-CRANK *
NSS19
 CPI A,013h
 JRNZ NSS20
 JP SS19 ;* SS19-CRANK *
NSS20
 CPI A,014h
 JRNZ NSS21
 JP SS20 ;* SS20-CRANK *
NSS21
 LDI WDR,001h     ;invalid sequence state,reset
;***************************************************************************
;*               END OF MAIN      *
;*Wait for NMI,which indicates end of FET on period,before measuring *
;*battery voltage.                           *
;***************************************************************************
ExitMain
XMain
 WAIT  ;wait for interupt
 JRS NMInt,Flags2,XMain ;timer interupt???
;***************************************************************************
;*             READ BATTERY VOLTAGE                   *
;*This routine is executed at or near zero cross.The current voltage *
;*is stored in CurVolt and the reading is added to BADhi(two locations).*
;*BADhi will contain a running average of the last 256 readings.*
;***************************************************************************
BADREAD
  .IFC EQ ShoADC ;assemble next 2 lines only if debugging
 SET 2,DRBbuf ;set PB2 when A/D sampling starts
 CALL UpdatePB  ;update port B from buffer
  .ENDC
 LD A,BADlo ;get average reading
 SUB A,BADhi  ;subtract one reading from the running total
 JRNC BADREAD1  ;no carry,go on
 DEC BADhi  ;adjust high order bits
BADREAD1
 LD BADlo,A  ;store new value
 LDI ADCR,0B0h ;start A/D conversion
 LDI ADCR,0B0h ;do again to insure a valid start
 WAIT  ;let the interupt notify us when data is ready
 LD CurVolt,A ;save current reading
 ADD A,BADlo ;add into running average
 JRNC BADREAD2;no carry,go on
 INC BADhi ;increment high bits
BADREAD2
 LD BADlo,A ;store new low bits
 .IFC EQ ShoADC ;assemble next 2 lines only if debugging
 RES 2,DRBbuf ;set PB2 when A/D sampling starts
 CALL UpdatePB ;update port B from buffer
  .ENDC
;LDI ORB,01Fh
;LDI ORB,09Fh
;***************************************************************************
;*            di/dt AVERAGE CALCULATION                *
;*For use by the di/dt,about four times every second the average oft he *
;*previous 32 curvolt readings is stored in FreshBV for comparison to a *
;*reading taken once every second.       *
;***************************************************************************
DIDTAVG
 LD A,Temp2  ;ifTemp2=0 then first reading
 JRNZ DIDTAVG1;skip init if not 1st reading
 LDI Temp2,020h ;initialize Temp2 to 32
DIDTAVG1
 LD A,FBVTotLo;
 ADD A,CurVolt ;add current voltage to total
 JRNC DIDTAVG2  ;don′t inc high byts ifno carry
 INC FBVTotHi  ;inc high byte
DIDTAVG2
 LD FBVTotLo,A ;update total
 DEC Temp2  ;update Temp2
 JRZ DIDTAVG3  ;compute avg
 JP DIDTAVGX ;exit to Main
DIDTAVG3
 LDI Temp2,003h ;prepare to shift3 times
DIDTAVG6
 LD A,FBVTotHi ;load high byte of total into accumulator
 SLA A ;shift accumulator left
 LD FBVTotHi,A ;update high byte of total
 LD A,FBVTotLo ;load low byte of total into accumulator
 SLA A  ;shift accumulator
 LD FBVTotLo,A ;update low byte of total
 JRNC DIDTAVG4 ;msb was zero,skip next line
 INC FBVTotHi ;
DIDTAVG4
 DEC Temp2 ;dec loop counter
 JRZ DIDTAVG5  ;if zero,finish average
 JP DIDTAVG6 ;not zero,shift again
DIDTAVG5
 LD A,FBVTotHi ;store average in FreshBV
 LD FreshBV,A
 CLR FBVTotHi
 CLR FBVTotLo
 JRS 7,FreshBV,DA7 ;skip ahead if>8.5V
RES Hi6V,Flags3 ;clear Hi6V flag
 JP DIDTAVGX ;and skip to end of routine
DA7
 SET Hi6V,Flags3 ;set Hi6V flag
DIDTAVGX
 JP MAIN
;****************************************************************************
;*This is where the sequence states are defined.The number of a given    *
;*sequence state has no relevance to the order in which it is actually  *
;*executed.Any given state can give control to any other state.       *
;****************************************************************************
;****************************************************************************
;*              BATTERY DETECT                   *
;*This is the charger idle state.The program remains here until a battery *
;*is detected.Dectection is determined by finding a positive voltage    *
;*greater than one volt.                              *
;****************************************************************************
SS0
 .IFC EQ DEBUG ;assemble next line only if debugging
RES SwOff,SwDown ;set to check Type and Rate switches
 .ENDC
;RES Crank,Flags  ;clear Crank bit of Flags
 RES Restore,Flags4 ;clear Restore bit of Flags4
 CALL ShutOff ;low & high power,fan,& crank off;min duty
 CALL ShowRate  ;turn on charge rate LED(Slow or Fast)
 CALL ShowType  ;turn on battery type LED(Reg,D/C or Gel)
;CALL ChrgRly  ;change E/S relay ifnecessary
 JRS ChMode,Flags2,Ready ;continue routine if in Charger Mode
 CALL CheckBatt  ;...otherwise,check iftester should show 0′s
 JP SS0EXIT  ;...and exit
Ready
 JRR Started,Flags,SS00 ;skip ifoutput hasn′t been on
 RES Started,Flags  ;set Flags for charge not started
SS00
 LD A,FreshBV  ;check latest average voltage
 JRNZ RvrsBatt  ;Is it 0(exactly)?
 CALL ShowRed  ;turn on Red LED until battery is detected
 JP SS0EXIT  ;...Yes:must be rev.batt,so stop
RvrsBatt
 CPI A,Volts0+1  ;No:otherwise,check if>~0.7V
 JRC Pulse   ;no:try pulsing the output
 JP SS0_1   ;yes:setup for no spark delay
Pulse   ;turn on charger for 1 cycle each second
 LD A,MSecsl   ;pulse once per second
 CPI A,MSINIT  ;time to pulse?
 JRZ PulseON   ;yes,goto to pulse code
 RES Power,Flags2  ;otherwse,tell timer to leave charger off
 JP SS0EXIT   ;and keep waiting(until next second starts)
PulseON    ;pulse charger on once per second
 SET Power,Flags2  ;tell PwrCon charger is on
;CALL ShowGreen   ;turn on Green LED ***test***
 JP SS0EXIT   ;no battery,just exit
SS0_1
 CALL IniTime1  ;set up timer
 LDI Secs1,002h ;adjust for 2 seconds
 LDI Tries,005h ;5Tries for debounce
 SET 0,CurentSS  ;go on to BATTERY DETECT DELAY
SS0EXIT
 JP ExitMain
;***************************************************************************
;*   BATTERY DETECT DELAY   *
;*This state checks that a voltage is present for two seconds.Ifthe *
;*voltage drops below 1 Vdc,the timer is restarted and the ″try″counter *
;*is decremented.If after 5 Tries the voltage has not been above 1 Vdc   *
;*for 2 seconds,go back to battery detect.This delay has the effect of *
;*debouncing the leads being connected to the battery.   *
;***************************************************************************
SS1
 CALL CheckBatt  ;check for connected battery
 JRR Batt,Flags2,SS1_2  ;subtract a try ifnot connected
 CALL ShowChgng   ;turn Charging LED on
 JRR 2,TicFlag1,SS1EXIT ;go on if time is up,otherwise exit
 LDI OldVolt,000h  ;clear OldVolt before entering SS2
 LDI TEMP1,000h  ;clear Temp1 before entering SS2
 INC CurentSS    ;go on to start charge
 JP SS1_3   ;set timer for 2 seconds
SS1_2   ;NOTE:Tries setto 5 in SS0
 DEC Tries   ;subtract a try
 JRNZ SS1_3   ;try again ifnot too many Tries
 DEC CurentSS  ;...otherwise,go back to idle(state 0)
 JP SS1EXIT   ;...and exit routine
SS1_3
 CALL IniTime1   ;reset timer and try again
 LDI Secs1,002h  ;adjust for 2 seconds
SS1EXIT
 JP ExitMain
;***************************************************************************
;*AUTOMATIC CHARGE START   *
;*This state gets the battery voltage and decides how to continue the *
;*the charge.The maximum allowed charge time is also started.*
;***************************************************************************
SS2
;NOTES:OldVolt SETTO 0 IN SS1
;TEMP1 SET TO 0 AT RESET
FASTAVG
 DEC TEMP1  ;decrease Temp1 one count(starts at 0)
  ;have we counted down to 0?
 JRZ FASTDONE ;yes,jump to FASTDONE
 LD A,TEMP  ;no,load previous TEMP value
 ADD A,CurVolt  ;add CURVOLT,Did we overflow the counter?
 JRNC OVER  ;no,jump to OVER
 INC OldVolt ;yes,bump up the running average
OVER
 LD TEMP,A ;store the latest value in TEMP
 JP SS2EXIT ;exit and go update CurVolt
FASTDONE
 LD A,TEMP ;load previous TEMP value
 ADD A,CurVolt ;Did we overflow the counter one last time?
 JRNC OVER2 ;no,jump to OVER2
 INC OldVolt ;yes,bump up the running average one last time
OVER2
 CALL CheckBatt  ;Check to see ifbattery was removed during FastAvg
 JRS Batt,Flags2,SS2_0c ;Still connected-continue
 LDI CurentSS,0 ;not connected-go back to state 0
 JP SS2EXIT  ;...and exit State 2
SS2_0c
 LD A,OldVolt  ;get OldVolt(initial battery voltage)
 LD BADhi,A   ;initialize BADhi to OldVolt
;LD A,Percent   ;get updated %
 LD A,DspPcnt   ;compare to last % displayed
 JRNZ SS2_GP   ;if % previously shown,skip ahead
 CALL GetPercent  ;update Percent for initial voltage
 LD A,Percent   ;get latest %
 LD DspPcnt,A   ;store latest % in Display Percent
 RES Wait0P,Flags2  ;set flag to indicate not waiting
 JP SS2_BP   ;skip ahead
SS2_GP
 CPIA,100   ;check for 100%
 JRNZ SS2_BP   ;continue State 2 if not 100%
 CALL SetMinOff   ;limit output to max 2A current
;LDI LowOff,MinOffSlo   ;limit output to max 2A current
;JRR Bat6V,Flags2,SS2_6S ;skip next line if not 6V mode
;LDI LowOff,Min6OffSlo ;limit output to max 6V 2a current
;SS2_6S
 JP SS5_Maint   ;...otherwise,go to Maintain
SS2_BP
 CALL ShowChgng   ;turn Charging LED on
 CALL IniTime1   ;initialize timer 1
 LDI Mins1,5   ;set timer 1 for 5 minutes
;LDI Secs1,005h  ;set timer 1 for 5 seconds
 LDI CCDcnt,MaxHrs  ;set interval counter to MaxHrs
 CLR LastBatt  ;clear LastBatt(ensure pass 1 st test)
;SET SOC,Flags4 ;set Start Of Charge flag
 CALL IniTime2  ;initialize timer 2
 LDI Secs2,001h  ;set timer for 1 second
 LDI MSecs2,MS500  ;set timer for 500 milliseconds(0.5secs)
 LDI Mins2,006h  ;set timer for 5 minutes and 2 seconds
 LDI Hrs2,005h  ;set timer for 4 hours,5 minutes & 2 seconds
 JRS Rate,Flags,SS2Fast ;skip ahead if not set for Slow
  ;...otherwise,set for Slow charge
 CALL StartSlow  ;set OFFSET for Slow rate
;LDI OFFSET,OffSlow  ;set Offset for 2A
;JRR Bat6V,Flags2,SS2Slo ;skip ifnot set for 6V mode
;LDI OFFSET,Off6Slo  ;...otherwise,adjust OFFSET
;SS2Slo
 JP SS2_0a ;skip ahead and read voltage
SS2Fast  ;set for Fast charge
 LDI OFFSET,OffFast  ;set Offset for Fast rate
 JRR Bat6V,Flags2,SS2Fst ;skip if not set for 6V mode
 LDI OFFSET,Off6Fst  ;...otherwise,adjust OFFSET
SS2Fst
 JRR Rapid,Flags2,SS2Rap ;skip ahead if rate is not Rapid
 CALL SetRmpUp  ;prepare to ramp from Fast to Rapid
SS2Rap   ;set for Rapid charge rate
 JP SS2_0a  ;...otherwise skip ahead and read voltage
SS2_0a
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CPI A,Volts09  ;very low battery?
 JRNC SS2_2;no,try next limit
SS2_1;Battery<9V
 LDI A,003h ;yes,service it,below 9 VOLT SS
 JP SS2_5
SS2_2  ;Battery>9V
 CPIA,Volts12  ;low battery state?
 JRNC SS2_4   ;no,goto SS5
SS2_3  ;9V<Battery<12V
 LDI A,004h  ;yes,service it,below 12 VOLT SS
 JP SS2_5
SS2_4  ;Battery>12V
;JRS Alert,Flags2,SS2EXIT;don′t start charge if Alert set by Double6V
 LDI A,005h  ;normal charge SS
SS2_5
 LD CurentSS,A  ;prepare to go to the correct state(3,4 or 5)
 SET Started,Flags  ;set Flags for charge started
 CALL TurnON   ;turn output,Fan,and Charging LED on
 SET Settle,Flags3  ;initial charge voltage settle mode
SS2EXIT
 JP ExitMain
;***************************************************************************
;*          BELOW 9Volts      *
;*Battery is extremely discharged and may be bad.Charge for a maximum  *
;*of five minutes.If voltage does not come above 9 Volts in this time *
;*period,abort charge.Otherwise,go to below 12 Volts.  *
;***************************************************************************
SS3
 CALL ChkRapid  ;update Ramp timer,ifnecessary
 JRR SEC,TicFlag2,SS3EXIT;exit if voltage settle time not expired
 RES Settle,Flags3  ;clear settle flag
 CALL IReg  ;regulate current till we get to dV/dt
 JRR MIN,TicFlag2,SS3_1 ;check if time has expired
 CALL SetAbort  ;yes,time to abort
 JP SS3EXIT
SS3_1
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts09  ;is battery up to 9V?
     JRC SS3EXIT       ;continue state 3if<9V
 INC CurentSS  ;...otherwise,go to state 4
    SS3EXIT
 JP ExitMain
;***************************************************************************
;*              BELOW 12Volts                 *
;*Battery is very low.Allow a maximum of 2 hours for the voltage to   *
;*rise above 12 volts under charge.If voltage does not come up,go to  *
;*abort charge.Otherwise go to normal charge.                    *
;***************************************************************************
SS4
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS4EXIT;exit if voltage settle time not expired
 RES Settle,Flags3  ;...otherwise,clear settle flag
 CALL IReg  ;regulate current till we get to dV/dt
 JRR HR,TicFlag2,SS4_I ;check if time(4 hours)has expired
 CALL SetAbort  ;yes,time to abort
 JP SS4EXIT  ;exit routine
SS4_1
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts12  ;is battery up to 12V?
 JRC SS4EXIT           ;...ifnot,just exit
 INC CurentSS    ;...otherwise,go to state 5
SS4EXIT
 JP ExitMain
;***************************************************************************
;*NORMAL CHARGE   *
;*Program stays here until the voltage reaches 14.2 volts or the maximum *
;*charge time is exceded.Ifthe voltage limit is reached the program *
;*will transfer to:     *
;*A.SSB(dV/dt)if the the battery has been charging more than 5 *
;*  minutes or     *
;*B.SS9(Desulfation)if the OCV was less than 12.2 volts or *
;*C.SS14(Maintain)if the OCV was more than 12.2 volts  *
;*      *
;*If the maximum charge time is exceded the program will abort *
;*         *
;***************************************************************************
SS5
 CALL ShowChgng  ;turn Charging LED on
 CALL ChkRapid  ;update Ramp timer,if necessary
  .IFC EQ DEBUG  ;assemble next line only if debugging
SET SwOff,SwDown  ;set to ignore Type and Rate switches
  .ENDC
 JRR SEC,TicFlag2,SS5x ;exit if voltage settle time not expired
 RES Settle,Flags3  ;...otherwise,clear settle flag
 CALL BattProg  ;check battery voltage for charge progress
 JRR HR,TicFlag1,SS5_0 ;skip next line ifmax time not expired
 ; NOTE:CurentSS set to ABORT by BattProg.ChkProg
SS5x
 JP SS5EXIT  ;exit(and abort)ifmax time expired
SS5_0
;JRS Rate,Flags,SS5_0b ;change delta if slow rate
 CPI A,Volts142+1  ;check if over 14.2 volts yet
;JP SS5_1
SS5_0b
;CPI A,Volts142+3  ;check if over 14.2 volts yet
SS5_1
 JRNC SS5_2  ;yes,check if>5minutes
 CALL IReg  ;no,regulate current till we get to dV/dt
 JP SS5EXIT  ;...and just return
SS5_2
 LD A,CCDcnt  ;get CCDcnt(set by BattPRog w/minutes)
 LD Hrs1,A  ;set Timer1 hours to CCDcnt
 RES HiPwr,Flags4  ;set for low power mode
 RES RmpInt,Flags3  ;clear flag before moving on
;RES Settle,Flags3  ;clear flag before moving on
 JRS MIN,TicFlag2,SS5_3 ;if>5 min,go to dV/dt
 LD A,OldVolt  ;otherwise,check initial voltage
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,Volts122  ;initial voltage<12.2V?
 JRC SS5_5  ;Yes:then desulfate
 JP SS5_Maint  ;No:goto Maintain
SS5_5
 LDI CurentSS,009h  ;battery is sulfated
 LDI MaintVolt,Volts16;try to hold battery at 16V
 LDI Vref,Volts15  ;and see if it drops to 15V
 CALL IniTime2    ;
 LDI Hrs2,002h  ;in less than 2 hours
 SET Restore,Flags4  ;set Restore flag
 JP SS5EXIT  ;
SS5_3
 CALL SetMinOff  ;min 2A offset value(max current)
;LDI LowOff,MinOffSlo ;min 2A offset value(max current)
;JRR Bat6V,Flags2,SS5_6V ;skip next line ifnot 6V mode
;LDI LowOff,Min6OffSlo ;min 6V 2A offset value(max current)
;SS5_6V
 JRR Rate,Flags,SS5_6  ;check for 15A charge rate
 CALL SetMinFst  ;min Fast offset value(max current)
;LDI LowOff,MinOfFst ;min 15A offset value(max current)
;JRR Bat6V,Flags2,SS5_6;skip next line if not 6V mode
;LDI LowOff,Min6OfFst ;min 6V 15A offset value(max current)
SS5_6
 LD A,LowOff  ;Load LowOff into A for next step
 LD OldOff,A  ;initialize OldOff for di/dt to LowOff
 LDI CurentSS,00Bh  ;goto wait for dv/dt trip voltage
 LDI Percent,77  ;set Percent to 77
 CALL IniTime2
 LDI Mins2,13;set to 13minutes for dV/dt
 LD A,BADhi  ;get latest battery voltage
 SUBI A,4  ;prevent match @ 1 st dV/dt check
 LD MaintVolt,A  ;store as maintain voltage for di/dt
 LDI Tries,004h  ;initialize dV/dt for 4Tries(3 intervals)
 JP SS5EXIT  ;
SS5_Maint  ;goto MAINTAIN,battery is already charged???
 CALL Set100p  ;set Percent to 100
 LDI MaintVolt,Volts132 ;set maintain voltage to 13.2V
;CALL FanOff  ;turn cooling fan off
 JRR BatTypeB,Flags,SS5_7;skip ahead if not Gel/AGM
 LDI MaintVolt,Volts135 ;set maintain voltage to 13.5V for Gel &AGM
SS5_7
 LDI CurentSS,00Eh  ;Maintain is state 14(0E hex)
 CALL SetON  ;turn cooling fan & output on
 CALL FanOff  ;turn cooling fan off
 CALL SetHiOff  ;MAX offset value->min duty cycle
SS5EXIT
 JP ExitMain
SS6
SS7
;***************************************************************************
;*       SS8-ABORT CHARGE     *
;*      *
;*Turn off all LED′s.Blink TROUBLE LED at half second interval.If*
;*battery becomes disconnected,goto BATTERY DETECT.  *
;*         *
;***************************************************************************
SS8
 SET Alert,Flags2  ;set Alert flag
;CALL ShutOff ;low & high power,fan,& crank off;min duty
 CALL SetOff  ;turn off power and set for min duty
;CALL ChrgRly  ;change E/S relay ifnecessary
 CALL BlinkAlert  ;blink red LED
 JRS BurnIn,Flags3,SS8X ;don′t check for battery if Burn-In
 CALL Check0V  ;check for disconnected battery
 JRS Batt,Flags2,SS8X ;if connected,just exit
 RES Alert,Flags2  ;...otherwise,end abort routine
SS8rst
 JP MAIN2  ;re-initialize
SS8X
 JP ExitMain
;***************************************************************************
;*            SS9-DESULFATION       *
;*Desulfation Mode is entered ifthe initial battery voltage is less *
;*than 12.2 volts and the voltage reaches 14.0 volts within five *
;*minutes.         *
;*          *
;*The charger tries to hold the voltage at 16.0volts.As the battery *
;*starts to conduct,the voltage will fall.If the voltage reaches 14.0*
;*in a reasonable time limit(10hours),we will transition to the *
;*normal charging sequence(SS5).If the voltage doesn′t fall to 14.0 *
;*volts we will transition to the ABORT sequence state(SS8).*
;***************************************************************************
SS9
 LDI Percent,15   ;set to 15%
 CALL BlnkChrg    ;blink Charging LED
 CALL CheckBatt   ;check for connected battery
 JRR Batt,Flags2,SS8rst  ;re-initialize if not connected
 CALL VoltReg
 JRR SEC,TicFlag2,SS9X ;wait 1 minute
 JRR HR,TicFlag2,SS9_1 ;maximum time out?(1 or 2 hours)
 DEC CurentSS  ;ABORT state
SS9exit
 JP SS9X  ;done
SS9_1
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CP A,Vref  ;are we there?
 JRNC SS9exit  ;ifnot,then exit
 DEC vref  ;1 count is 0.0667 volts
 DEC Vref  ;reduce Vrefby 0.133 volts
 LD A,Vref  ;see ifbatt is desulfated yet
 CPI A,Volts14  ;is Vref<14.0 Volts?
 JRC SS9_2  ;yes:skip next line
 JP SS9_3  ;no:try another hour
SS9_2
 LDI CurentSS,005h  ;prepare to go to normal charge
 RES Restore,Flags4  ;about to finish Restore mode
 LD A,Vmax  ;set MaintVolt to Vmax
 LD MaintVolt,A  ;maintain voltage for state 5
 CALL IniTime2  ;initialize timer 2
 LDI Secs2,002h ;set timer for 2 seconds(voltage settle time)
 JP SS9X  ;
SS9_3
 CALL IniTime2  ;reset timer
 LDI Hrs2,001h  ;set max time for 1hour
SS9X
 JP ExitMain
SS10
;***************************************************************************
;*dV/dt MONITOR   *
;*This state is looking for one of three conditions:  *
;*1.Maximum time is exxeded-set for check battery and turn off charger.*
;*2.No change in dV/dt for 45 minutes -battery is about 80% charged.*
;*3.MAX voltage is reached -GOTO dI/dt.  *
;*      *
;***************************************************************************
SS11
 JRR HR,TicFlag1,SS11_1 ;If not max time out,goto SS11_1
 CALL SetAbort  ;otherwise,go to abort
JP SS11X
SS11_1
 CALL ShowChgng  ;light Charging LED
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CP A,Vmax  ;is batt voltage<MAX voltage?
 JRC SS11_2  ;yes:continue loop
 SET HiEnd,Flags3  ;no: set to boost during D/C EndCharge
 JP SS11_6  ;...and prepare to GOTO dI/dt
SS11_2
 JRR MIN,TicFlag2,SS11X ;exit ifnot time for dv/dt test
 LD A,Percent  ;get Percent
 CPI A,84  ;is Percent<84?
 JRNC SS11_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_3
 LD A,BADhi  ;get battery voltage
 DEC A  ;limit for 6V batteries is 1 count
 JRS Bat6V,Flags2,SS11_3a;leave limit at 1 for 6V batteries
 DEC A  ;limit for 12V batteries is 2 counts
SS11_3a
 CP A,MaintVolt  ;test for upper limit change
 JRC SS11_4;less than 1 count up,test down change
 JP SS11_7  ;otherwise,skip ahead &update MaintVolt
SS11_4
 DEC Tries  ;decrement counter
 JRZ SS11_6  ;all done,GOTO dI/dt
 LD A,Percent  ;get Percent
 CPI A,87  ;is Percent<88?
 JRNC SS11_5  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_5
 JP SS11_8;no,reload timer
SS11_6
 INC CurentSS  ;GOTO dI/dt next
 LDI Percent,88  ;set Percent to 88-NOTE must always be even
 JRS HiEnd,Flags3,MntMx ;skip ahead if Vmax reached
 CALL GetBatt  ;get latest voltage & double if 6V mode
 LD MaintVolt,A ;save BADhias maintain voltage
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
MntMx
 LD A,Vmax  ;otherwise,set MaintVolt to Vmax
 LD MaiintVolt,A  ;MaintVolt used for di/dt
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
SS11_7;update MaintVolt
 LD A,BADhi  ;get current battery voltage
 LD MaintVolt,A  ;update MaintVolt for dV/dt & di/dt
SS11_9
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS11_8
 CALL IniTime2  ;initialize timer
 LDI Mins2,009h  ;...for 9 minutes
SS11X
 JP ExitMain
;***************************************************************************
;*    di/dt MONITOR    *
*In di/dt the OFFSET value is adjusted to hold the voltage at the dV/dt *
;*value.The OFFSET value will increase and stabilize.  *
;*This state is looking for one of two conditions:  *
;*1.Maximum time is exceded-set for check battery and turn off charger.*
;*2.No change in OFFSET value for 39 minutes-current stabilized at a *
;*low value.Battery is about 97% charged.Goto SS13(EndCharge)for *
;*1 hour.       *
;***************************************************************************
SS12
 CALL VoltReg   ;regulate battery voltage at MaintVolt
LD A,DspPcnt   ;get last %  displayed
CPI A,100   ;has %  displayed reached 100?
JRZ SS12_14   ;...if so,turn on green LED
CALL ShowYellow  ;...otherwise,turn on yellow LED
JP SS12_15   ;...and skip ahead(leave green off)
SS12_14
 CALL ShowDone  ;turn on charge complete LED
SS12_15
 JRR HR,TicFlag 1,SS 12_1 ;maximum time out?
 JRS Alert,Flags2,SS 12_0 ;If 2nd max time out,goto SS12_0
 SET Alert,Flags2  ;If 1st max time,set Alert flag
 CALL IniTime1  ;and reset timer
 LDI Hrs1,004h  ;to alow 4 more hours
SS12_10
 LD A,MaintVolt  ;and get Maintain voltage
SUBI A,007h  ;then subtract~0.5V
 LD MaintVolt,A ; andupdate Maintain voltage
 JP SS12EXIT  ;then restart di/dt
SS12_0
 CALL SetAbort  ;go to abort
 RES Alert,Flags2  ;reset Alert flag for Abort timer
 JP SS12EXIT
SS12_1
 JRR MIN,TicFlag2,SS12EXIT ;time for dI/dt test?
 LD A,Percent  ;get Percent
 CPI A,100  ;is Percent<100?
 JRNC SS12_2  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 LD A,Percent  ;get percent
 CPI A,100  ;Is percent=100?
 JRZ SS12_2  ;YES,don′t increase anymore
 INC Percent  ;No,increase by 2
SS12_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC SS12_13  ;ifso,finish di/dt
 DEC A  ;ensure carry if equal
 CP A,OldOff ;test for lower limit change
 JRC SS12_4  ;offset within 1,finish di/dt
 JP SS12_7  ;offset too high,try again
SS12_13
 JP SS12_6
SS12_4
 DEC Tries   ;decrement counter
 JRZ SS12_13   ;if 0,then prepare for EndCharge(SS13)
;JRNZ SS12_5  ;Are we done?
;JP SS12_6  ;yes,all done,cleanup and exit
;SS12_5   ;no,continue
 LD A,Percent  ;get Percent
 CPIA,99  ;is Percent<100
 JRNC SS12_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 JP SS12_8  ;reload timer & check again later
SS12_3
 LD A,Tries  ;get the current tries
 CPI A,03  ;Is tries less than 3?
 JRNC SS12_11  ;No,just exit
 CALL Set100p  ;Yes,show 100% and done
SS12_11
 JP SS12_8   ;reload timer & check again later
SS12_6
 INC CurentSS  ;GOTO EndCharge(SS13)
 CALL IniTime2  ;initialize Timer2
 LDI Hrs2,001h  ;charge for 1 more hour(EndCharge)
 LDI Mins2,00Fh  ;charge for only 15minutes(EndCharge)
 JRR BatTypeA,Flags,SS 12_9;skip if not Deep Cycle(Voyager)
 JRR HiEnd,Flags3,SS12_9;skip ifnot using higher EndCharge voltage
 INC Hrs2   ;otherwise,change Hrs2 from 1 to 2
 LD A,MaintVolt  ;also,store MaintVolt in A
 ADDI A,04h  ;increase A by 4counts ~0.267V
 LD MaintVolt,A  ;store updated value in MaintVolt
SS12_9
 JP SS12EXIT
SS12_7
 LD A,OFFSET  ;set new base offset
 LD OldOff,A  ;save in OldOff
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS12_8
 CALL IniTime2  ;initialize Timer 2
 LDI Mins2,009h  ;set Timer 2 for 9 minutes
 LD A,OFFSET  ;Get current offset
CPA,LowOff  ;Is the offset=MinOff?
JRNZ SS12EXIT  ;NO,just exit
 RES HiEnd,Flags3  ;YES,don′t boost voltage for EndCharge
 JP SS12_10  ;Current not falling,reduce voltage by 1/2V
SS12EXIT
 JP ExitMain
;***************************************************************************
;*     ENDCHARGE      *
;*Charge for desired hours after dI/dt at dV/dt voltage.  *
;***************************************************************************
SS13
 CALL Set100p  ;set Percent to 100
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRNZ SS13_2  ;...ifso,turn on green LED
 CALL ShowDone  ;rurn on charge complete LED
SS13_2
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRZ SS13_1   ;exit if max OFFSET reached
 JRR HR,TicFlag2,SS13EXIT ;exit if 1 hour time not up
SS13_1
 JP SS5_Maint  ;...otherwise,GOTO MAINTAIN
SS13EXIT
 JP ExitMain
;***************************************************************************
;*   MAINTAIN    *
;*Battery has reached full charge.Stay here and maintain battery *
;*at 13.2 volts until battery is disconnected.   *
;*         *
;***************************************************************************
SS14
 CALL Set100p  ;set Percent to 100
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has %displayed reached 100?
 JRZ SS14_1  ;...if so,tnrn on green LED
 CALL ShowYellow  ;...otherwise,turn on yellow LED
 JP SS14_2  ;...and skip ahead(leave green off)
SS14_1
 CALL ShowDone ;turn on charge complete LED
  .IFC EQ DEBUG ;assemble next line only if debugging
 RES SwOff,SwDown  ;set to check Type and Rate switches
 .ENDC
SS14_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC SS14_3  ;...if so,shutofffan
 JRS Bat6V,Flags2,SS14_5 ;skip ahead if 6V mode
 CPI A,HiOff-4  ;check for sustained output
 JP SS14_7
SS14_5
 CPI A,HiOff6-4  ;check for sustained output
SS14_7
 JRNC SS14_4  ;...if not,leave fan off
SS14_6
 CALL FanON  ;...otherwise,turn fan on
 JP SS14_4  ;...and skip ahead
SS14_3
 CALL FanOff  ;turn cooling fan off
SS14_4
 CALL CheckBatt  ;check for battery
 JRS Batt,Flags2,SS14EXIT;...connected: continue
 JP MAIN2  ;...disconnected:start over from state 0
SS14EXIT
 JP ExitMain
;***************************************************************************
;*     SS15 MANUAL    *
;*Regulate current.No voltage limit.Reset after 1 hour.  *
;***************************************************************************
SS15
 JRR Power,Flags2,SS15_2 ;power off indicates completed Burn-In
 CALL ShowRate  ;turn on the 2A or 15A LED
;NOTE:output already on,but TurnON saves code space
 CALL TurnON  ;turn output,Fan,and Charging LED on
 .IFC EQ AdjOff ;assemble next line only if debugging
  JRR BurnIn,Flags3,SS15OK;don′t regulate if not Burn-in mode
 .ENDC
 CALL IReg  ;regulate current at selected rate
;CALL Check17v  ;check for disconnected battery
;JRNZ SS15OK  ;if<>17V,then continue
;LDI CurentSS,ABORT  ;...otherwise,Abort
;RES Manua1,Flags3  ;...end Manual Mode
;JP SS15EXIT  ;...and skip rest of State 15
SS15OK
 JRS BurnIn,Flags3,SS15BI;skip ahead if Burn-in mode
  .IFC NE AdjOff ;assemble next lines only ifnot debugging
RES MtrScale,Flags  ;set for Alternator % LED off
RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
CALL ShowMeter  ;update meter LEDs
 .ENDC
 JP SS15rmp  ;jump to ramp check
SS15BI
 JRR MIN,TicFlag2,SS15b;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 CALL IniTime2  ;reset Timer2
 LDI Mins2,1  ;set timer for counter interval(1 minute)
SS15b
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL ShowNum  ;display count on digital LED
 CALL MeterOff  ;turn off all meter mode LED′s
SS15rmp
  .IFC EQ AdjOff ;assemble next lines only if debugging
 CALL CheckSw  ;check if switch is being pressed
 CALL GetMeter  ;update meter LEDs
 JP SS15_1  ;skip next three lines
  .ENDC
 CALL ShowData  ;update display
 JRR Rapid,Flags2,SS15_1 ;don′t ramp if Rapid is not set
 CALL ChkRapid  ;update Ramp timer,ifnecessary
SS15_1
 JRR HR,TicFlag 1,SS15EXIT;continue if not max manual charge time
 JRS BurnIn,Flags3,SS15_2;skip ahead if finished Burn-In
 JP RESET  ;...otherwise,reset
SS15_2
 CALL DigitsOff ;turn off 3-digit LED
 CALL ResetLEDs ;turn off all type,rate & Status LED′s
 CALL ShowGreen ;light Green LED only
 CALL SetOff ;reset Power & Cranking flags;set min.duty
SS15EXIT
 JP ExitMain
;***************************************************************************
;*    BOOST MODE   *
;*First set the charger offset value for 2amp charging.Next,wait *
;*for the voltage to stabilize.Then wait for the voltage to drop *
;*about two volts.When the voltage drops,go full on for 5 seconds.*
;*After five seconds of cranking,wait for 4 minutes and start over.*
;*         *
;*Comment the CALL and the following two LDI′s for test.Also load offset *
;*with PHASE15 instead of PHAZBOST    *
;***************************************************************************
SS16
  .IFC EQ DEBUG  ;assemble next line only ifdebugging
 RES SwOff,SwDown  ;set to check Type and Rate switches
 .ENDC
 CALL VoltMtr  ;set for volt meter and update display
 CALL CheckBatt  ;make sure batt is>1.6V
 JRR Batt,Flags2,SS16_1 ;skip ahead if not connected
 JRS SEC,TicFlag2,BattOK ;skip if>2 seconds since Boost selected
 JP SS16Exit  ;if<2 seconds,then stay off
SS16_1
 CALL TurnOff ;low &high power and fan off,min duty
 CALL ShowRed  ;turn on Alert LED
 JP SS16Exit  ;ifbatt<1.6V,then stay off
BattOK
 CALL ShowCrank  ;turn ON Crank LED & turn Alert LED off
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL SetHiOff  ;set for min duty cycle
 SET Started,Flags   ;set Flags for charge started
 CALL IniTime2  ;reset timer 2
 LDI MSecs2,MS200 ;set Timer2 for 200ms
 INC CurentSS  ;set state to 17
SS16Exit
 JP ExitMain  ;goto end of loop
;***************************************************************************
;*    DELAY FOR VOLT READING     *
;***************************************************************************
SS17
 JRS MSEC,TicFlag2,SS17_1;Is 200ms up?
 JP SS17EXIT  ;no,just return
SS17_1
 CALL GetMeter   ;update display
 CALL Check0V  ;make sure batt is connected
 JRS Batt,Flags2,SS17_2  ;skip ahead if connected
 JP MAIN2  ;disconnected,so start over
SS17_2
 SUBI A,010h  ;adjust for a one volt drop
 LD OldVolt,A  ;Save it
 LDI MaintVolt,Volts142  ;try to hold battery at 14.2(or 7.1)V
 CALL SetMinFst  ;min Fast offset value(max current)
;LDI LowOff,MinOfFst  ;min 15A offset value(max current)
;JRR Bat6V,Flags2,SS17_3  ;skip next line ifnot 6V mode
;LDI LowOff,Min6OfFst ;min 6V 15A offset value(max current)
;SS17_3
 INC CurentSS  ;wait for crank
 CALL IniTime2  ;initialize Timer 2
 LDI Mins2,15  ;set Timer 2 for 15 minutes
SS17EXIT
JP ExitMain
;***************************************************************************
;*    WAIT FOR CRANK    *
;***************************************************************************
SS18
 JRR MIN,TicFlag2,SS18_0 ;wait for crank only 15 minutes
 JP MAIN2  ;then start re-initialize
SS18_0
 CALL GetMeter  ;update display
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,FreshBV  ;get current reading
 SUBI A,010h  ;adjust for a one volt drop
 CP A,OldVolt  ;has voltage increased?
 JRC SS18_2  ;ifnot,then skip ahead
 LD OldVolt,A  ;update OldVolt
SS18x
 JP SS18EXIT  ;and exit routine
SS18_2
 LD A,FreshBV  ;get current reading
 CP A,OldVolt  ;1V drop might indicate cranking
 JRNC SS 18x  ;just exit if no drop
 ADDI A,0Ch  ;store FreshBV+0.8V in A
 CP A,BADhi  ;is latest average>FreshBV +0.8V?
 JRNC SS18EXIT  ;ifBADhi>FreshBV+0.8V,start cranking
SS18_1
 SET Power,Flags2  ;turn output on
 INC CurentSS  ;time the cranking
 SET Crnkng,Flags4  ;indicate cranking started
 CALL IniTime2
 LDI Secs2,CrankON  ;Crank for CrankON(5)seconds
SS18ECIT
 JP ExitMain
;***************************************************************************
;*    CRANK TIMING    *
;*Allow cranking for five seconds and then go back to charging.*
;***************************************************************************
SS19
LD A,Secs2  ;get remaining crank seconds
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
 JRR SEC,TicFlag2,SS19EXIT;if cranking not finished,then exit
 RES SCRs,DRBbuf  ;turn off SCR′s(inbuffer)
 CALL UpdatePB  ;update port B from buffer
 CAll ResetStatus  ;turn off Charging LED
 RES crrnkng,Flags4  ;indicate finished cranking
 RES Power,Flags2  ;tell timer to leave charger off
 INC CurentSS  ;just wait for time to expire
 CALL SetOff  ;turn offpower and set for min duty
 SET CrankWait,Flags ;indicates crank cool-down time
 CALL IniTime1  ;reset Timer1
 LDI Secs1,CCDint  ;set timer for counter interval(seconds)
 LDI CCDcnt,CrankOff ;set crank cool down counter to CrankOff secs
SS19EXIT
 JP ExitMain
;****************************************************************************
;*              INTER-CRANK DELAY                  *
;*Stay here until the 4 minute timer has expired then go back to BOOST *
;*if switch still engaged,else goto 2A auto(default)  *
;***************************************************************************
SS20
 CALL FanON  ;turn cooling fan ON
 JRR SEC,TicFlag1,SS20_0 ;skip ahead ifnot time to update counter
 DEC CCDcnt  ;decrease display count by 1
 JRNZ SS20_1  ;finish state 20 if count down to 0
 RES CrankWait,Flags ;reset CrankWait bit of Flags
  LDI CurentSS,010h  ;set state to 16 to Crank again
  SET SEC,TicFlag2  ;tell State 16that E/S already running
 JP SS20EXIT  ;and exit State 20
SS201
 CALL IniTime1  ;reset Timer1
 LDI Secs1,CCDint  ;set timer for counter interval(seconds)
SS20_0
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
;RES Rmpng,Flags3  ;clear flag for CheckBatt
RES Settle,Flags3  ;clear flag for CheckBatt
CALL BlinkCrank  ;blink the Crank LED
SS20EXIT
JP ExitMain
;***************************************************************************
;*    SUB ROUTINES START HERE   *
;***************************************************************************
;***************************************************************************
;*Initialize state(Slow charge,Regular batt,State 0)  *
;*         *
;***************************************************************************
InitState
 CLR Flags  ;0is default for all bits
 CLR Flags2  ;0is default for all bits
 CLR Flags3  ;set to indicate no Rapid to Fast change
 CLR TEMP1  ;initialize
 CLR CCDcnt  ;initialize
 RES Disable,DRBbuf  ;enable output
;SET ChMode,Flags2  ;set for Charger Mode(charger mode)
;RES ESrly,DRBbuf  ;set E/S relay for charge(not boost)
 LDI OFFSET,HiOff-1  ;set for mimimum output current
 LDI LowOff,OffRap  ;limit max rate to full 60A offset
 LDI SwData,01111101b ;Initialize switch LEDs for 2A,Reg
 LDI Vmax,Volts155  ;Vmax for Regular batteries
 LDI VltCnt,001h  ;initialize VltCnt to 1
 LDI VRcnt,001h  ;initialize VRcnt to 1
 LDI PcntL,001h  ;initialize PcntL to 1
 LDI PcntH,001h  ;initialize PcntH to 1
 LDI CurentSS,000h  ;set charger state to 0
 LDI Secs1,SecInit  ;restart TIMER1 second counter
 LDI Secs2,SecInit  ;restart TIMER2 second counter
RET
;***************************************************************************
;*    Reset Watchdog Register  *
;*This routine simiply resets the Watchdog register.RstWDR was *
;*only to save program space(LDI require 3 bytes,CALL requires only 2).*
;*         *
;***************************************************************************
RstWDR
 LDI WDR,0FEH  ;reset watch dog timer
 RET
;***************************************************************************
;*    Set Abort State   *
;*This routine simiply sets CurentSS to ABORT so that the code will go *
;*to the Abort state after the next NMI.SetAbort was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
SetAbort
 LDI CurentSS,ABORT  ;set current state to Abort
 RET
;***************************************************************************
;*Set 100 Percent   *
;*This routine simiply sets Percent to 100.Set100p was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
Set100p
LDI Percent,100  ;set Percent to 100
RET
;***************************************************************************
;*Clear Percent   *
;*This routine simiply sets Percent and DspPcnt to 0.ClrPcnt was *
;*written only to save program space(CLR require 3 bytes,CALL requires  *
;*only 2).Set0p is the second half of ClrPcnt.   *
;*        *
;*    Set 0 Percent   *
;*This routine simiply sets Percent to 0.Set0p was written only to *
;*save program space(LDI require 3 bytes,CALL requires only 2).*
;*        *
;***************************************************************************
ClrPcnt
 CLR DspPcnt  ;set Display Percent to 0
Set0p
 LDI Percent,0  ;set Percent to 0
 RET
;***************************************************************************
;*    Update Port A      *
;*This routine updates Port A with the contents of the DRA buffer.  *
;*UpdatePA was written only to save program space.  *
;*       *
;***************************************************************************
UpdatePA
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A  ;update port from Accumulator
 RET
;***************************************************************************
;*  Update Port B   *
;*This routine updates Port B with the contents of the DRB buffer. *
;*UpdatePB was written only to save program space.  *
;*       *
;***************************************************************************
UpdatePB
 LD A,DRBbuf  ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
 RET
;***************************************************************************
;*    Update Port B Options  *
;*This routine updates the Port B options with the contents of the ORB *
;*buffer.UpdateORB was written only to save program space.  *
;*        *
;***************************************************************************
UpdateORB
LD A,ORBbuf  ;update Accumulator from buffer
LD ORB,A  ;update options register from Accumulator
RET
;***************************************************************************
;*    Wait a Fifth Second   *
;*This routine causes the program to wait one fifth second by waiting *
;*for 24 interrupts.     *
;***************************************************************************
FifthSecond
CALL IniTime1
LDI MSecs1,MS200  ;set timer for 1/5second
WFS_1
WAIT
CALL RstWDR  ;reset watch dog timer
JRR MSEC,TicFlag1,WFS_1  ;wait until timer goes to 0
RET
;***************************************************************************
;*   Set Ramp Up   *
;*This rougine sets the parameters necessary to change the duty from the *
;*fast rate to the rapid rate.It is used before Burn-In and Automatic *
;*Rapid charge.           *
;*        *
;*Set Ramp    *
;*This routine sets the parameters necessary to change the duty between  *
;*the fast and rapid rates.It is actually the last part of SetRmpUp.  *
;*          *
;***************************************************************************
SetRmpUp
 LDI RmpCnt,RCinitF  ;set counter for Fast
 RES HiPwr,Flags4  ;set for low power
SetRamp
 LDI TEMP,RIinit  ;120 NMI interrupts yields 1.5 seconds
 SET RmpInt,Flags3  ;counting 1 st of two 180 cycle periods
 RET
;***************************************************************************
;*   CHECK RAPID          *
;*This routine determines whether to reduce or increase the charge rate *
;*from Rapid to Fast or vica versa,if necessary.It sets the flags *
;*used by RampOS appropriately.    *
;*        *
;***************************************************************************
ChkRapid
 JRR Rapid,Flags2,ChkRapX ;if not Rapid charge rate,then exit
 DEC TEMP  ;otherwise,update ramp timer
 JRNZ ChekRapX  ;exit if not time to update count
 LDI TEMP,RIinit  ;count 180 more cycles(1.5 sec)
 JRR RmpInt,Flags3,RmpCtr ;skip ahead if just counted 1 st half
 RES RmpInt,Flags3  ;...otherwise,start counting 2nd half
 ChekRapX
 JP ChkRapX  ;...and exit
RmpCtr
 SET RmpInt,Flags3  ;counting 1 st of two 180 cycle periods
 DEC RmpCnt  ;check if time to ramp
 JRNZ ChekRapX  ;exit if not time to ramp
 JRR HiPwr,Flags4,StRmpUp  ;skip ahead if changing to higher rate
 RES HiPwr,Flags4  ;set for not HiPwr(change to lower rate)
 LDI RmpCnt,RCinitF  ;...otherwise,set for Fast rate
;LDI OFFSET,OffRamp  ;set for between Fast & Rapid rates
 JP ChkRapR
StRmpUp
 SET HiPwr,Flags4  ;set flags for>Fast rate
 LDI RmpCnt,RCinitR  ;set counter for Rapid rate
 ChkRapR
 LDI OFFSET,OffRamp  ;set for between Fast & Rapid rates
ChkRapX
 RET
;***************************************************************************
;*   SHOW NUMBER   *
;*This routine determines what three digits to display on the digital LED *
;*to represent the number stored in LEDNum.The three digits will be *
;*displayed next time the ShowData routine is called.  *
;*        *
;***************************************************************************
ShowNum
 CLR Index   ;initialize LUT Index to 0
 CALL DigiOff  ;set registers for all segments off
 LD A,LEDnum   ;store LEDnum in accumulator
 CPI A,10   ;check for single digit number
 JRNC ChkMaxNum  ;...ifnot,check for max number
 JP Next001   ;...otherwise skip to 3rd digit
ChkMaxNum
  .IFC NE AdjOff ;assemble next lines only ifnot debugging
 CPI A,199  ;check for highest displayable number
 JRC Check100  ;ifless,check value
 LDI A,199  ;...otherwise,display 199
  .ENDC
Check100
 CPI A,100  ;check whether to show most significant 1
 JRC Check010  ;ifnot,check for 10
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,100   ;...and subtract 100 from accumulator
  .IFC EQ AdjOff ;assemble next lines only if debugging
   JP Check100  ;check whether number was greater than 200
  .ENDC
Check010
 CPIA,10  ;check if<10
 JRC Check001   ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,10  ;...and subtract 10 from Acumulator
 JP Check010  ;...and check for next higher value
Check001
 LDI DRWR,Digits0x0.w ;lookup table(LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD ATemp,A  ;save Accumulator
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for second digit
 LD DigiDat2,A  ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
Next001
 LDI DRWR,Digits00x.w ;look up table(LUT)for 3rd digit
 LDI X,Digits00x.d  ;initialize LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address oftable
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1  ;...set bits in A for segments
 LD DigiDat1,A  ;...store A into DigiDat1
ShowNumX
RET
;***************************************************************************
;*    GET VOLT DIGITS   *
;*This routine determines what three digits to display on the digital  *
;*LED to represent the battery voltage(BADhi).
;*        *
;**************************************************************************
GetVolts
 DEC VltCnt  ;decrement interval counter
 JRZ NewVolt  ;if 0,ready to update display
 JP GetVexit  ;...otherwise,just exit
NewVolt
 LDI VltCnt,MS500  ;re-initialize interval counter
 JRR ChMode,Flags2,GVT ;if Tester mode,use FreshBV
 LD A,BADhi  ;get latest avg batt voltage
 JP GV10
GVT
 LD A,FreshBV  ;Get latest average battery voltage
 GV10
 CALL DigiOff  ;set registers for all segments off
 CLR Index  ;initialize LUT Index to 0
CPI A,MaxVolts  ;check for max volt reading
 JRC GV 17  ;skip ahead if less than max
 LDI DigiDat1,DigiMV1 ;set for digit 1 of max volt display
 LDI DigiDat2,DigiMV2 ;set for digit 2 of max volt display
 JP GetVexit  ;exit GetVolts
GV17
 CPI A,Volts10  ;check for 10V
 JRC Check1V  ;if not 10V then skip ahead
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,Volts10  ;...and subtract 10V from accumulator
Check1V
 CPI A,Volts01  ;check if>1.0V
 JRC Check01V  ;...if so,skip ahead and check 3rd digit
 INC Index ;...otherwise,show next higher value
 SUBI A,Volts01  ;...and subtract 1.0V from accumulator
 JP Check1V  ;...and check for next higher value
Check01V
 LD ATemp,A  ;save Accumulator
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d ;initialize LUT
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for bottom segments
 LD DigiDat2,A  ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
ShowV001
 LDI DRWR,Digits0Vx.w ;look up table(LUT)for 3rd volts digit
 LDI X,Digits0Vx.d  ;initialize LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1;...set bits in A for bottom segments
 LD DigiDat1,A ;...store A into DigiDat1
 RES Decimal,DigiDat1  ;turn ON decimal point
GetVexit
 RET
;***************************************************************************
;*VoltMeter   *
;*This routine sets the display to show volts,then calls ShowMeter and  *
    ;*ShowData to update the display with the current battery voltage.  *
;*       *
;*   GetMeter    *
;*This routine calls ShowMeter and ShowData to display the latest  *
;*voltage or percentage (determined by MtrScale & MtrUnits)on the  *
;*3-digit LED display.GetMeter is the last section of VoltMtr.  *
;*         *
;***************************************************************************
VoltMtr
 RES MtrScale,Flags  ;set for Alternator %LED off
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
GetMeter
 CALL ShowMeter  ;update meter LEDs
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    GET PERCENT   *
;*This routine determines what value to use for the percentage of  *
;*charge before the charge state has reached the dv/dt state.The  *
;*percent is calculated by reading the battery voltage(BADhi)and  *
;*performing the following calculations;   *
;*As Tester       *
;*1.0V<BADhi<11.6V DC==>Percent=(BADhi/16)+1  *
;*11.61V<BADhi<12.8VDC==>Percent=(BADhi-175)*5+15 *
;*12.80V<BADhi==>Percent=100  *
;*As Charger     *
;*1Volt<BADhi<12Volts==>(BADhi/4)+15=Percent  *
;*12Volts<BADhi<dv/dt==>(BADhi/2)-30=Percent  *
;***************************************************************************
GetPercent
 JRR ChMode,Flags2,TstrBP;jump to Tester% if not charging
 JRS Restore,Flags4,GPend;don′t get % in Restore mode
 LD A,CurentSS ;get current program state
 CPI A,11  ;has charging reached dV/dt?
 JRC CalcPrcnt  ;...if not,calculate percentage
GPend
 JP GetPctEnd  ;...otherwise,do nothing
CalcPrcnt
 LD A,Percent  ;get Percent
 CPI A,76  ;check for highest calculated %
 JRNC GPend  ;exit if already there
 JRS HiPwr,Flags4,GPend;exit if in High Power mode
 LD A,RmpCnt  ;get Ramp interval counter
;NOTE:RmpCnt will be 0 if not set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC GPend  ;don′t update % until end of low power interval
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CPI A,Volts12  ;is the battery voltage less than 12V?
 JRNC Formula2  ;...No,goto Formula2
 CPI A,Volts01  ;Is battery>1
 JRNC GPform1  ;...if so,skip next line
 JP GPzero  ;...ifnot,set for zero %
GPform1
 CALL Divide4  ;...Yes,use first formula
 ADDI A,15  ;Add 15 and...
 JP GetPctExit ;...store into A
Formula2
 CALL Divide2  ;Divide by 2 and
 SUBI A,30  ;...subtract 30
 JP GetPctExit ;skip ahead and finish routine
TstrBP
 LD A,FreshBV  ;get latest(avg)battery voltage
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,Volts128  ;Is battery>12.8V?
 JRC Tstr100  ;...if not,skip ahead
 CALL Set100p  ;...otherwise,Percent=100
 JP GetPctEnd  ;...and end routine
Tstr100
 CPI A,BattMin  ;Is battery >BattMin
 JRNC TstrBPhi  ;...if so,jump ahead
 CPI A,Volts01  ;Is battery >1
 JRNC TstrBPmed  ;...ifso,jump ahead
GPzero
 CALL Set0p  ;...otherwise set Percent to 0
 JP GetPctEnd  ;...and end routine
TstrBPhi
 SUBI A,BattMin  ;subtract minimum high voltage
 CALL ATimes5  ;multiply by 5
 ADDI A,15  ;add 15
 JP GetPctExit  ;...store into A
TstrBPmed
 SUBI A,15  ;A=battery-15
 CALL Divide4  ;A=(battery-15)/4
 CALL Divide4  ;A=(battery-15)/16
 INC A  ;A=(battery-15)/16+1
GetPctExit
 LD Percent,A  ;store into Percent
GetPctEnd
 RET
;***************************************************************************
;*UPDATE BATTERY PERCENT    *
;*This routine controls how the battery percentage displayed is updated.*
;*UpdateBP ensures that under normal circumstances,the battery %dis- *
;*played is updated according to the following two rules.   *
;*1.The % displayed doesn′t change by more than 1% at a time *
;*2.The % displayed is not updated twice in<PCint seconds  *
;*There are a few exceptions.   *
;*1.The % displayed can jump up more than 1 ifit was 0  *
;*2.The % displayed will drop to 0 immediately for disconnected batt.*
;*3.The %displayed can change by more than 1 if the scale**changes *
;*       *
;***Scale refers to the %scale,which is either battery or alternator *
;*       *
;***************************************************************************
UpdateBP
 LD A,Percent  ;check whether % is 0
 JRNZ UBP0  ;...if not,wait for update interval
 JP UBPfinish  ;...otherwise finish routine
UBP0
 LD A,DspPcnt  ;get last % displayed
 JRZ UBP00  ;continue if 0%
 JP UBP1  ;skip ahead ifnot 0%
UBP00
 JRS MtrScale,Flags,UBP1;also skip ahead if Alternator %
 JRS Wait0P,Flags2,UBPz ;skip ahead if Wait0P flag already set
 SET Wait0P,Flags2  ;...otherwise,set flag to wait
 CALL IniTime2  ;initialize Tiner2
 LDI Secs2,3  ;set Timer2 for 3 seconds
 JRR ChMode,Flags2,UBPz ;skip ahead if in tester mode
 LDI Secs2,5  ;set Timer2 for 5 seconds in charger mode
UBPz
 JRR SEC,TicFlag2,UBPx ;skip ahead if still waiting
UBP0a
 RES Wait0P,Flags2  ;set flag to indicate not waiting
 LD A,Percent  ;...otherwise,get new %
 JP UBPfinish  ;...and don′t wait to display it
UBPx
 JP UBPexit  ;...and just exit
UBP1
 DEC PcntL  ;decrement % interrupt counter
 JRNZ UBPx   ;if not 0then just exit
 LDI PcntL,MSINIT  ;re-initialize % interupt counter
 DEC PcntH  ;decrement interval counter
 JRNZ UBPx  ;if not down to 0,then just exit
 LDI PcntH,PCint  ;re-initialize % interval counter
 LD A,DspPcnt  ;get last % displayed
 JRNZ UBP2  ;skip ahead ifnot 0%
 LD A,Percent ;get new %
 JP UBPfinish  ;and finish routine
UBP2
 CP A,Percent  ;compare to newest %
 JRZ UBPexit  ;if equal,do nothing
 JRC IncBP  ;ifless,increase display % by 1
 JRS ChMode,Flags2,UBPexit ;don′t decrease % if charging
 DEC A  ;...otherwise,decrease % by 1
 JP UBPfinish  ;...and finish
IncBP
 INC A  ;increase display % by 1
 UBPfinish
 LD DspPcnt,A  ;store updated display %
UBPexit
 RET
;***************************************************************************
;*      MeterNum      *
;*This routine calls MeterOff,ShowNum,and ShowData to turn off the *
;*display mode LED′s and display LEDnum on the 3-digit LED display. *
;*         *
;*   NumData    *
;*This routine calls ShowNum and ShowData to display LEDnum on the *
;*3-digit LED display.NumData is the last section ofMeterNum.  *
;*         *
;***************************************************************************
MeterNum
 CALL MeterOff  ;turn off all meter mode LED′s
NumData
 CALL ShowNum  ;get data to show the number
 CALL ShowData  ;show the number
RET
;***************************************************************************
;*    SHOW DATA    *
;*This routine updates the digital LED and 6 switch LEDs controlled by *
;*the serial to parallel shift registers.It sends the bits of SwData *
;*and DigiData to the registers bit by bit from LSB to MSB using *
;*SerData.After each bit is sent,ShftClk is toggled to shift the bit *
;*to the next position.After all 24 bits have been sent,LtchClk is *
;*used to update the outputs,which updates the LEDs.  *
;*        *
;***************************************************************************
ShowData
 CALL RstWDR  ;reset watch dog timer
;RES ClrData,DRAbuf  ;clear shift register
;CALL UpdatePA  ;update port A from buffer
;SET ClrData,DRAbuf ;prepare to accept data
;CALL UpdatePA  ;update port A from buffer
 LDI BitCnt,008h  ;initialize bit counter to 8
 LDI BytCnt,003h  ;initializie byte counter to 3
 LDA,DigiDatl  ;get first 8 bits of digit data
GetBit
RLC A  ;sendMSB of Acumulator to Carry
JRC SetBit  ;if Carry=1 then data bit is 1
RES SerData,DRAbuf  ;...otherwise set SerData to 0
JP SendBit  ;skip ahead to SendBit
SetBit
SET SerData,DRAbuf  ;set SerData to 1
SendBit
 LD DataBuf,A  ;store shifted data from A
 CALL UpdatePA  ;update port A from buffer
 RES ShftClk,DRBbuf  ;set Shift Clock low
 RES LtchClk,DRBbuf  ;set Latch Clock low
 CALL UpdatePB  ;update port B from buffer
 SET ShftClk,DRBbuf  ;set Shift Clock high
 CALL UpdatePB  ;update port B from buffer
 DEC BitCnt  ;update bit count
 JRZ NextData  ;if all bits sent then skip ahead
 LD A,DataBuf  ;store shifted data back in A
 JP GetBit  ;otherwise,get next bit
Next Data
 DEC BytCnt  ;update byte count
 JRNZ NextByte  ;get next byte is count is not 0
 JP LatchData  ;...otherwise,done sending bits
NextByte
 LDI BitCnt,08h  ;set bit count for 8 more bits
 LD A,BytCnt  ;which byte is next?
 CPI A,02h  ;check for 2 nd byte is next
 JRZ ScndByte  ;skip ahead if equal
 LD A,SwData  ;get 8 bits of switch LED data
 JP GetBit  ;send bits of second byte
ScndByte
 LD A,DigiDat2  ;get last 8 bits of digit data
 JP GetBit  ;send bits of second byte
LatchData
 SET LtchClk,DRBbuf  ;update latches
 CALL UpdatePB  ;update port B from buffer
 RET
;***************************************************************************
;*   Show Meter    *
;*This routine sets the digital LED to show either the current voltage *
;*or last percent based on Flags and CurentSS.During Engine start,it *
;*will count down seconds of either remaining crank time or cool down *
;*time.       *
;***************************************************************************
ShowMeter
 JRS Alert,Flags2,SMeXit ;exit if abort mode
 JRS MtrUnits,Flags,GetPrcnt ;skip ahead and set for %
 CALL GetVolts  ;...otherwise,get volts
 JRS ChMode,Flags2,SM1 ;skip ahead ifnot in Tester mode
 CALL ShowStatus ;...otherwise,update Status LEDs
SM1
 JP ShowMtrX  ;...and skip to end or routine
GetPrcnt
 JRR ChMode,Flags2,TstMtr;if in tester mode,get %
 JP ShowPrcnt  ;...otherwise,skip ahead & show %
Show0
 CALL Set0p  ;set to show 0%
ShoPer
 JP ShowPrcnt  ;and skip ahead
TstMtr
 LD A,FreshBV  ;get latest Battery voltage
 JRZ Show0  ;if 0V,show 0%
 JRR MtrScale,Flags,ShoPer;show Battery% if not set for Alt%
 CALL Double6V  ;double Battery voltage ifset for 6V
 CPI A,AltMin  ;check for<1st LUT value
 JRC Show0  ;if so,show 0%
 CPI A,AltMax  ;check for>last LUT value
 JRC AltVal  ;if not,skip ahead and check LUT
 LDI Percent,199  ;...otherwise,set to max value
 JP ShowPrcnt  ;and skip ahead
AltVal
 LDI DRWR,AltLvls.w  ;LUT for alternator %
 LDI X,AltLvls.d  ;initialize LUT
 SUBI A,AltMin  ;diffence is index in look up table
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 LD Percent,A  ;store value into Percent
ShowPrcnt
 CALL ShowPercent  ;otherwise,show percentage
 CALL ShowStatus  ;turn on appropriate status LED
ShowMtrX
 CALL ShoMtrMode  ;turn on appropriate meter LED
SMeXit
 CALL RstWDR  ;reset watch dog timer
 RET
;***************************************************************************
;*   SHOW METER MODE   *
;*This routine turns on one of the meter units LED′s based on Flags and *
;*Flags2.If the unit is in TesterMode(ChMode=0),the routine will    *
;*also light the appropriate status LED based on the voltage at the  *
;*clamps.         *
;*           *
;***************************************************************************
ShoMtrMode
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn offBattery %LED
 SET LEDalt,DRAbuf  ;turn off Alternator %LED
ShowVolts
 JRS MtrUnits,Flags,ShoPrcnt ;goto ShoPrcnt if set
 RES LEDvolt,DRAbuf  ;turn on Voltage LED
 JP ShowMMX
ShoPrcnt
 JRS MtrScale,Flags,ShowAlt ;goto ShowAlt if set
 RES LEDprcnt,DRAbuf  ;turn on Battery % LED
 JP ShowMMX
ShowAlt
 RES LEDalt,DRAbuf  ;turn on Alternator % LED
ShowMMX
 CALL UpdatePA  ;update port A from buffer
RET
;***************************************************************************
;*Hold Meter Mode LED(depending on mode)  *
;*This routine turns on the Battery%,Volts DC,or Alternator% LED based *
;*on Flags & Flags2 and keeps that LED on for one fifth second. *
;***************************************************************************
HoldMtrMd
 CALL ShoMtrMode ;turn on Meter Mode LED
 CALL FifthSecond  ;wait one fifth second
RET
;***************************************************************************
;*    SHOW STATUS   *
;*This routine turns on one of the three status LED′s based on the *
;*battery voltage.This routine is for use in the tester mode.   *
;*         *
;****************************************************************************
ShowStatus
 JRS ChMode,Flags2,ShoStatX ;exit ifnot Tester mode
 JRR Batt,Flags2,RedStat ;show red LED ifno battery
 JRR MtrUnits,Flags,ClrStat ;turn off Status LED′s if volts mode
 LD A,FreshBV  ;get latest Battery voltage
 JRS MtrScale,Flags,TestAlt ;skip ahead ifset for Alternator
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;Is it 100%?
 JRZ GrnBatt  ;...if so,show green LED
 CALL ResetStatus  ;...otherwise,turn Status LED′s off
 JP ShoStatX  ;...and skip to end
GrnBatt
 CALL ShowGreen  ;turn on Green LED
 JP ShoStatX  ;skip to end
TestAlt
 CALL Double6V  ;double Battery voltage ifset for 6V
 CPI A,Volts 15a  ;Is alternator at least 15.07V?
 JRNC RedStat  ;...if so,skip ahead and show red
 CPI A,Volts138  ;is alternator at least 13.80V?
 JRC RedStat   ;...ifnot,skip ahead and show red
 CPI A,Volts14   ;Is alternator<14.0V?
 JRC ClrStat  ;...ifso,skip ahead and show yellow
 CPI A,Volts149;is alternator at least 14.87V?
 JRNC ClrStat  ;...if so,skip ahead and show yellow
 CALL ShowGreen  ;...otherwise turn on Green LED
 JP ShoStatX  ;...and skip to end
RedStat
 CALL ShowRed  ;turn on Red LED
 JP ShoStatX  ;skip to end
ClrStat
 CALL ResetStatus  ;turn Status LED′s off
ShoStatX
 RET
;***************************************************************************
;*   METER OFF      *
;*This routine turns off the three meter mode LED′s.  *
;*         *
;***************************************************************************
MeterOff
SET LEDvolt,DRAbuf  ;turn offDC Voltage LED
SET LEDprcnt,DRAbuf  ;turn offBattery % LED
SET LEDalt,DRAbuf  ;turn off Alternator % LED
CALL UpdatePA  ;update port A from buffer
RET
;***************************************************************************
;*    DigiOff     *
;*This routine set the registers to turn off the three-digit LED. *
;*         *
;***************************************************************************
DigiOff
 LDI DigiDat1,DigiOffa ;turn off 8 of 16 digital segments
 LDI DigiDat2,DigiOffb ;turn off other 8 of 16 digital segments
 RET
;***************************************************************************
;*DIGITS OFF   *
;*This routine turns off the three-digit LED.  *
;*         *
;***************************************************************************
DigitsOff
 CALL DigiOff  ;set registers for all segments off
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   DIGITS ON   *
;*This rougine turns ON all segments of the three-digit LED.*
;*         *
;***************************************************************************
DigitsON
 LDI DigiDat1,DigiONa ;turn ON 8 of 16 digital segmennts
 LDI DigiDat2,DigiONb ;turn ON other 8 of 16 digital segments
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*   SHOW PERCENT       *
;*This routine turns ON the Battery % LED.  *
;*        *
;***************************************************************************
ShowPercent
 SET MtuUnits,Flags  ;set Flags for %(not volts)
 JRR Wait0P,Flags2,SP1 ;skip ahead ifnot waiting from 0
 LDI DigiDat1,Dashes1 ;...otherwise,show dashes while waiting
 LDI DigiDat2,Dashes2 ;...otherwise,show dashes while waiting
 JP ShowPx
SP1
 LD A,DspPcnt  ;get Percent value to display
  .IFC EQ AdjOff ;assemble next line only if debugging
   LD A,BADhi  ;set to display latest batt.volt.
  .ENDC
JRR MtrScale,Flags,SP2 ;don′t use Display% for Alternator%
LD A,Percent  ;...use actual Percent for display
 .IFC EQ ShoOff ;assemble next line only if debugging
JRR ChMode,Flags2,SP2 ;skip ahead **DEBUG**
LD A,OFFSET  ;diplay OFFSET **DEBUG**
 .ENDC
SP2
 LD LEDnum,A  ;...and store it in Accumulator
 CALL ShowNum  ;set digital LED for LEDnum
 SET Decimal,DigiDat1 ;turn OFF decimal point
ShowPx
 RET
;***************************************************************************
;*  RESET LEDS   *
;*This routine turns off the Type,Rate,and Status LED′s  *
;*         *
;***************************************************************************
ResetLEDs
CALL ResetStatus  ;turn off all three status LEDs
ClrLEDs
 LDI SwData,SwsOff ;turn off Type and Rate LED′s
 RET
;***************************************************************************
;*   Reset Status    *
;*This routine turns off the LED′s in the Status area.  *
;*         *
;***************************************************************************
ResetStatus
 SET LEDchgng,DRabuf ;turn off Charging LED
SET LEDdone,DRAbuf ;turn off Charged LED
SET LEDalert,DRAbuf ;turn off Fault(red)LED
RST
;***************************************************************************
;*   BLIN Charging LED   *
;*This routine blinks the Charging LED at a rate of once per second.*
;***************************************************************************
BlnkChrg
 LD A,MSecs1 ;get MSecs count
 CPI A,MS500 ;test for>1/2 sec
 JRNC BlinkCh1 ;if so,skip ahead
 CALL ResetStatus ;...otherwise,turn off status LEDs
 JP BlinkChX ;...and exit routine
BlinkCh1
 CALL ShowChgng ;Turn on Charging LED
BlinkChX
RET
;***************************************************************************
;*   Show Charging   *
;*This routine turns the Charging LED on and  the rest off. *
;*         *
;*   Show Yellow    *
;*This routine turns the Charging LED on and does not affect the Check *
;*and Charged LEDs. ShowYellow is actually the last part of ShowChgng *
;*        *
;***************************************************************************
ShowChgng
 CALL ResetStatus ;turn off all Status LEDs
ShowYellow
 RWS LEDchgng,DRAbuf ;turn ON Charging LED
CALL UpdatePA ;update port A from buffer
RET
;***************************************************************************
;*   BLINKAlertLED   *
;*This routine blinks the Alert LED at a rate of once per second. *
;*         *
;***************************************************************************
BlinkAlert
 LD A,MSecs1 ;get MSecs count
 CPI A,MS500 ;test for 1/2 sec
 JRNC BlnkAlrt ;if so,skip ahead
 CALL ResetLEDs ;…otherwise,turn off all LEDs
 JRS BurnIn,Flags3,BBI ;skip ahead if not Burn-In
 CALL DigitsON ;...turn on all digital LED segments
 JP BAeXit ;...and exit routine
BBI
 CALL NumData ;get data for,and show LED number
 JP BAeXit ;...and exit routine
BlnkAlrt
 CALL AlertON ;Turn on Alert LED
 CALL DigitsOff ;Turn off 3-digit LED
BAeXit
 RET
;***************************************************************************
;*   Alert LED ON   *
;*This routine turns on the Alert(red)LED and turns the other meter  *
;*LEDs off. NOTE:it does not affect the Rate and Type LEDs. *
;***************************************************************************
AlertON
 CALL MeterOff  ;Turn offMeter Mode LEDs
ShowRed
 CALL ResetStatus  ;Turn off Status LEDs
 RES LEDalert,DRAbuf ;Turn on Alert LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*   Show Done LED   *
;*This routine turns on the Done(green)LED and turns all the other  *
;*LEDs off. NOTE:it turns off the Rate and Type LEDs.  *
;***************************************************************************
ShowDone
 CALL ResetLEDs ;Turn off all LEDs
 LDI SwData,SwsOff ;set Type & Rate LED′s off
 CALL ShowType ;show Battery Type & update display
ShowGreen
 CALL ResetStatus ;turn offall three status LEDs
 RES LEDdone,DRAbuf ;Turn on Done LED
 CALL UpdatePA ;update port A from buffer
 RET
;***************************************************************************
;*   BLINK Crank LED    *
;*This routine blinks the Crank LED at a rate of once per second. *
;***************************************************************************
BlinkCrank
 LD A,MSecs2 ;get MSecs count
 CPI A,MS500 ;test for>1/2 sec
 JRNC BlinkES ;if so,skip ahead
 SET LEDboost,SwData ;...otherwise,turn off Crank LED
 JP BCeXit ;...and exit routine
BlinkES
 CALL ShowCrank ;turn on Crank LED
BCeXit
 RET
;***************************************************************************
;*   ShowCrank    *
;*This routine turns the Engine Start(Crank/Boost)LED on and turns *
;*the Type and other Rate LEDs off.   *
;*NOTE:The 6V LED will be left on if appropriate.   *
;***************************************************************************
ShowCrank
 CALL ClrLEDs  ;turn off all Rate & Type LEDs
 JRR Bat6V,Flags2,ShoES ;skip ahead if not 6V
  RES LED6V,SwData ;rurn on Regular 6V LED
ShoES
 RES LEDboost,SwData ;turn ON Crank LED
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    SetSlow    *
;*This routine sets the charger for the Slow rate by setting the appro- *
;*priate flags.     *
;***************************************************************************
SetSlow
 RES Rate,Flags  ;turn on Slow LED
 RES Rapid,Flags2 ;turn off Rapid LED
 RET
;***************************************************************************
;*   SetSlow    *
;*This routine sets the OFFSET for the correct(12 or 6V)Slow rate. *
;*         *
;***************************************************************************
StartSlow
 LDI OFFSET,OffSlow  ;set Offset for 2A
 JRR Bat6V,Flags2,StrtSloX ;skip ifnot set for 6V mode
 LDI OFFSET,Off6Slo  ;...otherwise,adjust OFFSET
StrtSloX
 RET
;***************************************************************************
;*   SetMinOff   *
;*This routine sets the OFFSET for the correct(12 or 6V)maximum Slow *
;*rate(minimum OFFSET).    *
;*        *
;***************************************************************************
SetMinOff
 LDI LowOff,MinOffSlo ;limit output to max 2A current
 JRR Bat6V,Flags2,SetMOx ;skip next line ifnot 6V mode
 LDI LowOff,Min6OffSlo ;limit output to max 6V 2a current
SetMOx
 RET
;***************************************************************************
;*   SetMinFst   *
;*This routine sets the OFFSET for the correct(12 or 6 V)maximum Fast *
;*rate(minimum OFFSET).   *
;*        *
;***************************************************************************
SetMinFst
 LDI LowOff,MinOfFst ;limit output to max Fast current
 JRR Bat6V,Flags2,SetMFx ;skip next line if not 6V mode
 LDI LowOff,Min6OfFst ;limit output to max 6V Fast current
SetMFx
 RET
;***************************************************************************
;*  Show Charge Rate LED(depending on mode)  *
;*This routine turns on the Slow,Fast,or Rapid LED,based on Flags.*
;*         *
;***************************************************************************
ShowRate
 SET LEDboost,SwData  ;turn off Boost LED
  SET LEDrap,SwData   ;turn off Rapid LED
  SET LEDfast,SwData  ;turn off Fast LED
  SET LEDslow,SwData  ;turn off Slow LED
  JRR ChMode,Flags2,ShoRateX ;exit if in Tester Mode
ShowRap
 JRR Rapid,Flags2,ShowSlow ;goro ShowSlow if not Rapid
 RES LEDrap,SwData  ;turn on Rapid LED
 JP ShoRateX
ShowSlow
 JRS Rate,Flags,ShowFast ;goto ShowFast if set
 RES LEDslow,SwData  ;turn on Slow LED
 JP ShoRateX
ShowFast
 RES LEDfast,SwData  ;turn on Fast LED
ShoRateX
 RET
;***************************************************************************
;*   Set12V     *
;*This routine sets the charger for the 12V Regular battery type by *
;*resetting the 6V,AGM/Gel,and Deep Cycle flags.   *
;*           *
;*   SetReg     *
;*This routine sets the charger for the Regular battery type by reset- *
;*ting the Deep Cycle and AGM/Gel flags.SetReg is actually part of *
;*Set12V        *
;***************************************************************************
Set12V
 RES Bat6V,Flags2 ;turn off 6V LED
SetReg
 RES BatTypeA,Flags  ;turn on Regular LED
 RES BatTypeB,Flags  ;turn off Gel/AGM LED
 RET
;***************************************************************************
;*  Show Charge Type LED(depending on mode)  *
;*This routine turns on either the Regular,Deep Cycle,Gel/AGM,or 6V *
;*LED based on Flags.The routne also sets Vmax to match.  *
;*       *
;***************************************************************************
ShowType
 SET LEDreg,SwData  ;set Regular LED to off
 SET LEDdeep,SwData  ;set Deep Cycle LED to off
  SET LEDgel,SwData  ;set Gel/AGM LED to off
  SET LED6V,SwData  ;set 6V LED to off
  JRR Bat6V,Flags2,ShowT1;skip ahead if not 6V
  RES LED6V,SwData  ;turn on Regular 6V LED
 JP ShowT2a  ;set Vmax for regular(15.5V)
ShowT1
 JRR BatTypeB,Flags,ShowT2 ;skip ahead if not Gel/AGM
  RES LEDge1,SwData  ;turn on Gel/AGM LED
 LDI Vmax,Volts144  ;Vmax=14.4V for Gel/AGM MODE
 JP ShoTypeX
ShowT2
 JRS BatTypeA,Flags,ShowT3 ;goto ShowT3 if set
  RES LEDreg,SwData  ;turn on Regular LED
ShowT2a
 LDI Vmax,Volts155  ;Vmax=15.5V for Regular MODE
 JP ShoTypeX
ShowT3
  RES LEDdeep,SwData  ;turn on Deep Cycle LED
 LDI Vmax,Volts16  ;Vmax=16V for Deep Cycle battery
ShoTypeX
 RET
;***************************************************************************
;*  Hold Charge Type LED(depending on mode)  *
;*This routine turns on the Regular,Deep Cycle,or Gel/AGM LED based on *
;*Flags and keeps it on for one Fifth second.  *
;***************************************************************************
HoldType
  CALL ShowType  ;turn on Battery Type LED
 CALL ShowData  ;update display
  CALL FifthSecond ;wait one Fifth second
 RET
;***************************************************************************
;*  Hold Charge Rate LED(depending on mode)  *
;*This routine turns on the Slow,Fast,or Rapid LED based on Flags and *
;*keeps it on for one Fifth second.     *
;***************************************************************************
HoldRate
  CALL ShowRate  ;turn on Charge Rate LED
 CALL NumData  ;get data for,and show nominal rate(amps)
  CALL FifthSecond ;wait one Fifth second
 RET
;***************************************************************************
;*   Check High Offset   *
;*This routine is used to check whether the latest OFFSET is equal to the *
;*maximum value,HiOff. When OFFSET=HiOff,the charge rate is 0. *
;***************************************************************************
ChkHiOff
 LD A,OFFSET  ;get current OFFSET
 JRS Bat6V,Flags2,CHO6 ;skip next line if not 6V mode
 CPI A,HiOff-2  ;has OFFSET reached maximum(output off)?
 JP CHOx
CHO6
 CPI A,HiOff6-2  ;has OFFSET reached max for 6V(output off)?
CHOx
 RET
;***************************************************************************
;*   Check0V     *
;*This routine checks the latest running average of the battery voltage *
;*and sets the Carry bit if it′s less than Volts0+1 DAC count.This *
;*routine is used to check whether a battery is connected.  *
;***************************************************************************
Check0V
CheckBatt
 SET Batt,Flags2 ;setflag for connected battery
;LD A,FreshBV  ;test latest average voltage
 LDI A,Volts0+1 ;check if higher than zero
 JRR Crnkng,Flags4,ChkBat;skip next line if not cranking
 LDI A,1  ;check for true 0 if cranking
ChkBat
 CP A,FreshBV  ;test latest average voltage
 JRNC NoBatt  ;If not>0,battery not connected
 JP ChkBattX  ;...otherwise,just exit
NoBatt
 RES Batt,Flags2 ;set for battery not connected
 CALL ShowRed  ;turn on Alert(Red)LED
 CALL ClrPcnt  ;clear Percent and Display Percent
 CLR BADhi  ;clear previous voltage reading
 CLR FreshBV  ;clear previous voltage reading
ChkBattX
 RET
;***************************************************************************
;*   Get Battery Voltage   *
;*This routine gets the battery voltage stored in BADhi and saved it in *
;*the accumulator.It also doubles the result if set for 6V battery. *
;*         *
;*   Double6V       *
;*This routine doubles the accumulator,A,if the Bat6V flag is set.This *
;*routine is called before the accumulator is compared to one of the *
;*constants originally assigned for 12v batteries.   *
;*           *
;*NOTE:If the Bat6V flag is set,and the accumulator is>8.5V,the  *
;*Hi6V Flag is set instetad of doubling A.   *
;***************************************************************************
GetBatt
 LD A,BADhi  ;get latest(avg)battery voltage
Double6V
 JRR Bat6V,Flags2,D6VX ;skip ahead if not set for 6V
 JRR Hi6V,Flags3,D6V ;double if 6V Batt<8.5V
 LDI A,MaxVolts ;...otherwise,set A to MaxVolts
;JRR ChMode,Flags2,D6VX ;check for Charge or Test mode
;CALL SetAbort  ;...set for Abort state if Charge mode
;SET Alert,Flags2 ;...set Alert Flag
 JP D6VX  ;...and skip to end of routine
D6V
 SLA A  ;double A
D6VX
 RET
;***************************************************************************
;*   Check Progress   *
;*This routine is used to ensure that the charger will abort if the *
;*battery voltage does not increase throughout the charge.It checks the *
;*voltage every CPint minutes for a measurable increase since the  *
;*previous check.If there isn′t,the charge is aborted.   *
;*         *
;***************************************************************************
ChkProg
 JRR MIN,TicFlag1,ChkProgX ;exit if not time to check for progress
;ChkProg0
;JRR SOC,SwDown,ChkProg1  ;skip ahead if not Start Of Charge
;RES SOC,SwDown  ;...otherwise,clear SOC flag
;CALL IniTime1  ;initialize Timer1
;LDI Mins1,5  ;...set Timer1 for 5 minutes
;CLR LastBatt  ;clear LastBatt(ensure pass 1st test)
;JP ChkProgX  ;...and exit
;ChkProg1
 LD A,BADhi  ;get latest battery reading
 SUBI A,1  ;subtract one count
 CPA,LastBatt  ;check for increase
 JRC ChkProgA  ;set to abort if no increase
 LD A,BADhi  ;set A back to BADhi
 LD LastBatt,A  ;update LastBatt
 CALL IniTime1  ;initialize Timer1
  .IFC NE FastCP  ;assemble next line only if not debugging
 LDI Mins1,CPint  ;set Timer1 for 60 minutes
  .ELSE  ;assemble next line only if debugging
 LDI Mins1,3  ;set Timer1 for 3 mins
  .ENDC
 DEC CCDcnt  ;update interval count
 JRNZ ChkProgX  ;just exit if not zero
 SET HR,TicFlag1  ;if zero,set for time expired
ChkProgA
 CALL SetAbort  ;set to start Abort mode
ChkProgX
 RET
;***************************************************************************
;*   Battery Progress   *
;*This routine is used to ensure that ChkProg and CheckBatt are called *
;*only when the charge rate is about to ramp up or isn′t set to ramp at *
;*all.That way,the battery voltage used to check charging progress *
;*won′t be affected by the higher current.BattProg works by checking *
;*RmpCnt to make sure it′s less than 5.If the start of charge flag(SOC)*
;*is set,BattProg does not check RmpCnt.     *
;*          *
;***************************************************************************
BattProg
;JRR Rmpng,Flags3,BtPrg0 ;skip ahead if not Rapid->Fast transition
;CALL RampOS  ;otherwise,gradually reduce duty cycle
;BtPrg0
 CLR A  ;set A to 0 to ensure<(9,12,or 14.2 V)
 JRS HiPwr,Flags4,BtPrgX ;exit if high power mode
;JRS SOC,SwDown,BtPrg2;skip ahead if Start Of Charge
 LD A,RmpCnt ;get Ramp interval counter
;NOTE;RmpCnt will be 0 if not set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC BtPrgX  ;if not,then exit
;BtPrg2
 CALL ChkProg  ;check for charging progress
 CALL GetBatt  ;get latest voltage & double if 6V mode
BtPrgX
 RET
;***************************************************************************
;*   Check2V    *
;*This routine checks the latest running average of the battery voltage *
;*and sets the Carry bit if if′s less than Volts016. This routine is *
;*used to check whether a battery is ready for cranking.  *
;***************************************************************************
Check2V
 LD A,FreshBV  ;test latest average voltage
 CPI A,Volts016 ;check if higher than 1.6 volts
 RET
;***************************************************************************
;*      CHECK SWITCHES    *
;*Check if switch is engaged and change modes if appropriate. *
;*         *
;***************************************************************************
CheckSw
 JRR CrankWait,Flags,ChkStart ;check switches if not during Crank wait
 JP ChkSwRET  ;don′t check switches if during Crank wait
ChkStart
 JRS Crank,Flags,ChekRate ;don′t check display mode during Boost
 JRR MeterSw,DRC,MeterDown ;If switch is being pressed,skip ahead
 RES MeterSw,SwDown  ;set for Meter switch not pressed(up)
ChekRate
 JP ChkRate  ;Meter switch not pressed,so exit CheckSw
MeterDown
 RES Idle,Flags3  ;set for not idle
 JRS MeterSw,SwDown,ChekRate ;If switch wasn′t released,don′t check it
 SET MeterSw,SwDown  ;set for mode switch pressed(down)
 JRR MtrScale,Flags,ChkPrcnt ;if not set for Alt,then skip ahead
 RES MtrScale,Flags  ;set for Alt%,so change to Batt%
 JP ChkRate
ChkPrcnt
 JRR MtrUnits,Flags,ChkAlt ;ifset for volts,then skip ahead
 RES MtrUnits,Flags ;set for Batt%,so change to volts
 JP ChkRate
ChkAlt
 SET MtrUnits,Flags  ;set for volts,so change to %
  .IFC NE ShoOff ;assemble next line orly if not debugging
 JRS ChMode,Flags2,ChkRate ;don′t set for Alt if charging
  .ENDC
 SET MtrScale,Flags  ;set for batt,so change to alt
 RES Wait0P,Flags2  ;set to stop waiting for battery %
ChkRate
 CALL ShoMtrMode  ;Meter units are set before rate
  .IFC EQ DEBUG ;assemble next line only if debugging
;JRR SwOff,SwDown,SkpSw ;skip Rate and Type swith if SwOff is set
;JP ChkSwRET  ;Otherwise,just exit
 JRS SwOff,SwDown,ChkSwX ;skip Rate and Type swith if SwOff is set
;SkpSw
  .ENDC
 JRR RateSw,DRC,RateDown ;If switch is being pressed,skip ahead
 RES RateSw,SwDown  ;set for Rate switch not pressed(up)
ChekType
 JP ChkType  ;Rate switch not pressed,so check Type
RateDown
 RES Idle,Flags3  ;set for not idle
 JRS RateSw,SwDown,ChekType ;If switch wasn′t released,don′t check it
 SET RateSw,SwDown  ;set for Rate switch pressed(down)
ChkCM
 .IFC EQ AdjOff ;assemble next lines only if debugging
 JRR Manual,Flags3,ManRate ;debug only in manual mode
 INC OFFSET  ;increase OFFSET(decrease output)
JP ChkSwRET  ;exit CheckSwitch routine
 .ENDC
ManRate
 JRR Crank,Flags,ChkSlow ;if not set for Crank,check for Slow
 CALL TurnOff  ;low & high power and fan off,min duty
 RES ChMode,Flags2;set for Tester(not Charger)Mode
 SET Disable,DRBbuf ;disable output if Rate was Boost
  JP ModeChange  ;go to end of CheckSw
ChkSlow
 JRS ChMode,Flags2,ChkFast ;skip ahead if already Charger mode
 SET ChMode,Flags2  ;set for Charger(not tester)Mode
 RES Disable,DRBbuf  ;enable output after Rate is pressed
 RES MtrScale,Flags  ;set for Batt%(not Alt%)when not tester
 RES Rate,Flags  ;was Crank,so set for Slow
  JP ModeChange  ;go to end of CheckSw
ChkFast  ;if set for Slow,then set to Fast
 JRS Rate,Flags,ChkRap ;If not Slow,then must be Fast
 SET Rate,Flags  ;set Charge rate for Fast
  JP ModeChange  ;go to end of CheckSw
ChkRap  ;if set for Fast,then change to Rapid
 JRS Rapid,Flags2,ChkES ;If not Rapid,then must be Fast
 SET Rapid,Flags2  ;set Charge rate for Rapid
  JP ModeChange  ;go to end of CheckSw
ChkES  ;was set to Rapid,change to Boost
 CALL SetSlow  ;set for Slow Rate
 SET Crank,Flags  ;set Charge rate for Boost
;CALL SetReg  ;set battery type for Regular
 CALL ShowCrank  ;turn ON Crank LED
 CALL TurnOff  ;low & high power and fan off,min duty
 LDI CurentSS,CrankSS ;set Charge state to Crank
 CALL IniTime2  ;reset timer 2
 LDI Secs2,003h  ;set Timer2 for 3 seconds
 JP ChkSwRET
ChkType  ;if Gel/AGM,then set for Regular
 JRR TypeSw,DRC,TypeDown ;If Switch is being pressed,skip ahead
 RES TypeSw,SwDown  ;set for Type switch not pressed(up)
ChkSwX
 JP ChkSwRET  ;Type switch not pressed,so exit CheckSw
 TypeDown
 RES Idle,Flags3  ;set for not idle
 JRS TypeSw,SwDown,ChkSwX ;If Switch wasn′t released,don′t check it
 SET TypeSw,SwDown  ;set for mode switch pressed(down)
  .IFC EQ AdjOff ;assemble next lines only if debugging
   JRR Manual,Flags3,ManType ;debug only in manual mode
   DEC OFFSET  ;decrease OFFSET(increase output)
 JP ChkSwRET  ;exit CheckSwitch routine
  .ENDC
ManType
;JRR Bat6V,Flags2,ChkBT1;If not set for 6V,check for Regular
ChkBT0  ;if set for 6V,change to 12V regular
;RES Hi6V,Flags3  ;clear 6V over voltage flag
;CALL Set12V  ;set for Regular,12V battery
;CALL ClrPcnt  ;clear Percent and Display Percent
;JP TypeChange  ;go to end of CheckSw
ChkBT1  ;if set for AGM/Gel,change to 6V
 JRR BatTypeB,Flags,ChkBT2 ;Ifnot set for Gel/AGM,check for Regular
;JRS Hi6V,Flags3,ChkBT0;don′t set to 6V if batt>8.5V
 CALL SetReg  ;set battery type for Regular
;SET Bat6V,Flags2;set for 6V battery
;CALL ClrPcnt  ;clear Percent and Display Percent
 JP TypeChange  ;go to end of CheckSw
ChkBT2  ;if Regular,then set for Deep Cycle
 JRS BatTypeA,Flags,ChkBT3;If not set for Regular,must be Deep Cycle
 SET BatTypeA,Flags ;set battery type for Deep Cycle
 RES BatTypeB,Flags ;set battery type for not AGM/Gel
  JP TypeChange  ;go to end of CheckSw
ChkBT3  ;must be Deep Cycle,so set for Gel/AGM
 SET BatTypeB,Flags  ;set battery type for Gel/AGM
 RES BatTypeA,Flags  ;set battery type for not Deep Cycle
TypeChange
 RES Crank,Flags  ;set charge rate for non-Boost
 CALL ShowType  ;turn on Battery Type LED
ModeChange
 RES Crank,Flags  ;clear Crank bit of Flags
 LDI CurentSS,000h  ;restart charging
ChkSwRET
 RET
;***************************************************************************
;*      FAN ON     *
;*This routine turns the cooling fan ON.FanON is called during one of *
;*the following conditions:      *
;*1.Start of charge(end of State 2)    *
;*2.Start of boost (State 16)    *
;*3.If OFFSET<HiOff-3 in Maintain(State 14)    *
;*4.Manual Mode (State 15)     *
;*5.States 4,5,11,12,and 13    *
;*         *
;***************************************************************************
FanON
 LD ATemp,A  ;save Accumulator
 LDI A,00010000b ;update Accumulator from buffer
 LD DRC,A ;update port from Accumulator
 LD A,ATemp  ;restore Accumulator
 RET
;***************************************************************************
;*      FAN Off    *
;*This routine turns the cooling fan off.FanOff is called during one of *
;*the following conditions:       *
;*1.Before start of charge(State 0)    *
;*2.Start of Abort(State 8)       *
;*3.Before start of Maintain(State 14)    *
;*4.If OFFSET=HiOff in Maintain(State 14)    *
;*        *
;***************************************************************************
FanOff
 LD ATemp,A  ;save Accumulator
 LDI A,00000000b ;update Accumulator from buffer
 LD DRC,A  ;update port from Accumulator
 LD A,ATemp  ;restore Accumulator
 RET
;***************************************************************************
;*   ShutOff    *
;*This routine sets the charger for no output by turning off the output *
;*FETs,turning off the fan,setting the PWM for minimum duty cycle *
;*(HiOFF),and setting it for non-boost mode.   *
;*         *
;*   TurnOff    *
;*This routine sets the charger for no output by turning off the output *
;*FETs,turning off the fan,and setting the PWM for minimum duty  *
;*cycle(HiOFF).TurnOff is actually part of ShutOff.  *
;*        *
;***************************************************************************
ShutOff
 RES Crank,Flags  ;set charge rate for non-Boost
 CLR RmpCnt  ;clear ramp interval counter
TurnOff
 CALL FanOff  ;turn cooling fan off
SetOff
 RES Power,Flags2 ;turn output off
 RES Crnkng,Flags4 ;indicate not cranking
SetHiOff
 LDI OFFSET,HiOff ;set for minimum duty cycle
 JRR Bat6V,Flags2,SOx ;skip next line if not 6V mode
 LDI OFFSET,HiOff6 ;set for min.6V duty cycle
SOx
 RET
;***************************************************************************
;*   TurnON     *
;*This routine sets the charger to run with the Charging LED,fan,and *
;*output on.        *
;*         *
;*   SetON     *
;*This routine sets the charger to run with the fan and output on  *
;*SetON is actually part of TurnON        *
;*         *
;***************************************************************************
TurnON
 CALL ShowChgng  ;turn Charging LED on
SetON
 CALL FanON  ;turn cooling fan on
 SET Power,Flags2  ;tell PwrCon charger is on
 RET
;***************************************************************************
;*   Charge Relay   *
;*This routine switches the relay from Start to Charge if necessary. *
;*ChrgRly waits 200mS before switching the relay.The output should  *
;*before turned off before calling ChrgRly.   *
;*          *
;***************************************************************************
;ChrgRly
;JRR ESrly,DRBbuf,ChgRlyX;skip ahead if relay already set for charge
;CALL FifthSecond ;wait 200mS
;RES ESrly,DRBbuf ;set E/S relay for charge
;ChgRlyX
;RET
;***************************************************************************
;*Update the clocks and set overflow flags as necessary.  *
;*TicFlag1(s)bit 0=hours went to zero     *
;*TicFlag1(s)bit 1=minutes went to zero      *
;*TicFlag1(s)bit 2=seconds went to zero      *
;*TicFlag1(s)bit 3=miliseconds went to zero      *
;***************************************************************************
CLOCKS
 DEC MSecs1  ;decrement millisecond counter
 JRNZ Clks1  ;skip to clock2 if MSECs<>0
Do_MSecs
 LDI A,MSINIT  ;restart millisecond counter
 LD MSecs1,A  ;
 SET MSEC,TicFlag1  ;set millisec flag
 DEC Secs1  ;decrement second counter
 JRZ Do_Mins
Clks1
 JP CLOCKS1
Do_Mins
 SET SEC,TicFlag1  ;set second expired flag
 LDI Secs1,SecInit  ;restart second counter
 DEC Mins1  ;decrement minute counter
 JRNZ CLOCKS1  ;skip HRs1 if MINs1<>down to zero
Do_Hrs
 SET MIN,TicFlag1  ;set minute expired flag
 LDI Mins1,MinInit  ;restart minute counter
 DEC Hrs1  ;decrement hour counter
 JRNZ CLOCKS1  ;check for overflow
 SET HR,TicFlag1  ;set hour expired flag
CLOCKS1
 DEC MSecs2  ;decrement millisecond counter
 JRZ DOMSecs2
ClkExit
 JP CLOCEXIT
DOMSecs2
 LDI A,MSINIT  ;restart millisecond counter;
 LD MSecs2,A  ;
 SET MSEC,TicFlag2  ;set millisec flag
 DEC Secs2  ;decrement second counter
 JRNZ ClkExit  ;exit if not down to zero
Do_Mins2
 SET SEC,TicFlag2  ;set second expired flag
 LDI Secs2,SecInit  ;restart second counter
 DEC Mins2  ;decrement minute counter
 JRNZ CLOCEXIT  ;exit if not down to zero
Do_Hrs2
 SET MIN,TicFlag2  ;set minute expired flag
 LDI Mins2,MinInit  ;restart minute counter
 DEC Hrs2  ;decrement hour counter
 JRNZ CLOCEXIT  ;check for overflow
 SET HR,TicFlag2  ;set hour expired flag
CLOCEXIT
 RET
;***************************************************************************
;*  INITIALIZE TIMER1       *
;*  Subroutine to initialize timer1  *
;****************************************************************************
IniTime1
 LDI MSecs1,MSINIT
 LDI Secs1,SecInit
 LDI Mins1,MinInit
 CLR Hrs1
 CLR TicFlag1
 RET
;***************************************************************************
;*   INITIALIZE TIMER2        *
;*   Subroutine to initialize Timer2   *
;***************************************************************************
IniTime2
 LDI MSecs2,MSINIT
 LDI Secs2,SecInit
 LDI Mins2,MinInit
 CLR Hrs2
 CLR TicFlag2
 RET
;***************************************************************************
;*   ShiftA7    *
;*Subroutine to shift the accumulator left 7 times. Used by Divide2 *
;*and Divide4. Written only to save code space.    *
;***************************************************************************
ShiftA7
 SLA A  ;shift left
 RLC A  ;rotate left through CARRY bit 6 times
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 RET
;***************************************************************************
;*   DIVIDE BY 2    *
;*Subroutine to divide the number in A by 2.The remainder,if any *
;*will be available in the carry bit upon return.  *
;***************************************************************************
Divide2
 CALL ShiftA7 ;shift left once then rotate left 7 times
 RLC A ;rotate left 7th time
 RET
;***************************************************************************
;*   DIVIDE BY 4    *
;*Subroutine to divide the number in A by 4.    *
;***************************************************************************
Divide4
 CALL ShiftA7  ;shift left once then rotate left 7 times
 ANDI A,01111111b ;drop MSB
 RET
;***************************************************************************
;*    A Times 5   *
;*Subroutine to multiply the accumulator(A)by 5.   *
;*Atimes5 multplies A by 4 by shifting left twice then adding the  *
;*original value of A:(A*4)+A=A*5    *
;***************************************************************************
ATimes5
 LD ATemp,A  ;ATemp=A
 ADD A,A  ;A=A+A=A*2
 ADD A,A  ;A =A+A =ATemp*4
 ADD A,ATemp  ;A=A+ATemp=ATemp*5
 RET
;***************************************************************************
;*   CURRENT REGULATION        *
;*This routine reduces the output current by increasing the OFFSET *
;*value when the voltage is below 14.2 volts(thru SS5).An offset into *
;*an LUT is determined based on the battery voltage.The value is loaded *
;*into OFFSET which is used to controls the offtime of the SCR′s. *
;***************************************************************************
IReg
 LD A,BADhi  ;get voltage
;LD A,FreshBV  ;get voltage
 JRS Bat6V,Flags2,IR_6V ;skip ahead if 6V mode
 JRS Rate,Flags,PH_1 ;skip ahead if 15 amp mode
 LDI DRWR,OffAdjSlo.w ;look up table for 12V 2 amp
 LDI X,OffAdjSlo.d  ;initialize look up table
 LDI TempOff,OffLowSlo ;highest 2A offset-lowest current
 SUBI A,BatLoSlo  ;sub mininum 12V 2 amp table entry(10V)
 JRNC P_A14  ;done
P_A15
 LD A,TempOff
 JP P_A12
P_A14
 LDI TempOff,OffHiSlo  ;lowest 12V 2A offset-highest current
 CPI A,040h  ;last table entry-highest index
JRNC P_A15  ;done
JP PH_2  ;done with 12V 2 amp
PH_1
 JRS Rapid,Flags2,IR_rap ;skip ahead if Rapid rate
IR_1
 LDI DRWR,OffAdjFst.w ;look up table for 12V 15 amp
 LDI X,OffAdjFst.d  ;initialize look up table
 LDI TempOff,OffLowFst ;highest 15A offset-lowest current
 SUBI A,BatLoFst  ;sub minium 15 amp table entry
 JRNC P_A17  ;done
P_A16
 JP P_A15
P_A17
 LDI TempOff,OffHiFst ;lowest 12V 15A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC P_A16  ;done
 JP PH_2  ;done with 12V 15 amp
IR_rap
 JRR HiPwr,Flags4,IR_1 ;use 12V 15A table if low power mode
 LDI DRWR,OffAdjRap.w ;look up table for 60 amp
 LDI X,OffAdjRap.d ;initialize look up table
 LDI TempOff,OffLowRap;highest 60A offset-lowest current
 SUBI A,BatLoRap  ;sub mininum 60 amp table entry
JRNC IR_rp2  ;done
IR_rp1
 JP P_A15
IR_rp2
 LDI TempOff,OffHiRap  ;lowest 60A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC IR_rp1  ;done
PH_2
 ANDI A,03Fh  ;limit to 64 byte window
 ADD A,X  ;add table base address
 LD X,A  ;
 LD A,(X)  ;get value from table
 JP P_A12  ;skip ahead and update offet value
IR_6V
 JRS Rate,Flags,IR6_3;skip ahead if 15 amp mode
 LDI DRWR,OfAd6Slo.w  ;look up table for 6V 2 amp
 LDI X,OfAd6Slo.d  ;initialize look up table
 LDI TempOff,Off6LoSlo  ;highest 2A offset-lowest current
 SUBI A,Bat6LoSlo  ;sub mininum 6V 2 amp table entry(5V)
 JRNC IR6_2  ;done
IR6_1
 LD A,TempOff
 JP P_A12
IR6_2
 LDI TempOff,Off6HiSlo ;lowest 6V 2A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_1  ;done
 JP IR6_10  ;done with 6V 2 amp
IR6_3
 JRS Rapid,Flags2,IR6_7;skip ahead if Rapid rate
IR6_4
 LDI DRWR,OfAd6Fst.w ;look up table for 6V 15 amp
 LDI X,Of Ad6Fstd  ;initialize look up table
 LDI TempOff,Off6LoFst ;highest 15A offset-lowest current
 SUBI A,Bat6LoFst  ;sub mininum 6V 15 amp table entry
 JRNC IR6_6  ;done
IR6_5
 JP IR6_1
IR6_6
 LDI TempOff,Off6HiFst ;lowest 6V 15A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_5  ;done
 JP IR6_10  ;done with 6V 15 amp
IR6_7
 JRR HiPwr,Flags4,IR6_4 ;use 6V 15A table if low power mode
 LDI DRWR,OfAd6Rap.w ;look up table for 60 amp
 LDI X,OfAd6Rap.d  ;initialize look up table
 LDI TempOff,Off6LoRap ;highest 6V 60A offset-lowest current
 SUBI A,Bat6LoRap  ;sub mininum 6V 60 amp table entry
 JRNC IR6_9  ;done
IR6_8
 JP IR6_1
IR6_9
 LDI TempOff,Off6HiRap ;lowest 6V 60A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_8  ;done
IR6_10
 ANDI A,01Fh  ;limit to 32 byte window
 ADD A,X  ;add table base address
 LD X,A  ;
 LD A,(X)  ;get value from table
P_A12
;ADD A,FUDGE  ;debug fudge factor
 LD OFFSET,A  ;save new offset value
P_A13
 RET
;***************************************************************************
;*   VOLTAGE REGULATION       *
;*This subroutine will adjust the value of OFFSET once per second to *
;*control the current and maintain the voltage determined by MaintVolt.*
;*         *
;***************************************************************************
VoltReg
;LD A,MSecs2  ;MSec2=MSInit once per second
;CPI A,MSINIT  ;Is MSEC1=MSINIT?
;JRZ VReg_0  ;Yes:then time to adjust
;VReg_X
;JP VReg_3  ;No:then not time to adjust
;VReg_0  ;adjust offset
 DEC VRcnt  ;decrement interval counter
 JRZ VReg_0  ;Yes:then time to adjust
 JP VoltRegX  ;No:then not time to adjust
VReg_0  ;adjust offset
 LDI VRcnt,MSINIT ;re-initialize initerval counter(1 sec)
 LD A,FreshBV  ;get battery voltage
 CALL Double6V  ;double Battery voltage if set for 6V
 DEC A
 CP A,MaintVolt ;compare with set value+1
 JRNC VReg_6  ;greater than,increase OFFSET
 JP VReg_1  ;not greater than,test if less than
VReg_6
 LD A,OFFSET  ;greater than,get phase delay value
 INC A  ;
 JRS Bat6V,Flags2,VReg_2
 CPI A,HiOff  ;test if at high limit
 JP VReg_5
VReg_2
 CPI A,HiOff6
VReg_5
 JRNC VReg_3  ;at the limit,don′t change OFFSET
VReg_4
 LD OFFSET,A  ;update OFFSET
VReg_3
 JP VoltRegX  ;done for this pass
VReg_1
 INC A
 CP A,MaintVolt ;compare with set value
 JRNC VoltRegX  ;not less than,just exit
 LD A,OFFSET ;less than,get phase delay value
 DEC A  ;
 CP A,LowOff  ;test if at low limit
 JRNC VReg_4  ;not at the limit,update OFFSET
VoltRegX
 RET
;***************************************************************************
;*  TIMER INTERRUPT HANDLER   *
;*This routine turns the SCRs on if the power flags are non-zero and *
;* inhibits the timer.     *
;***************************************************************************
PwrCon
 LD ATemp,A  ;save A register
 JRS Power,Flags2,PCon ;charger on,turn on SCRs
 JP PWREXIT  ;not charging,just exit
PCon
 SET SCRs,DRBbuf ;turn on the SCRs(in buffer)
 CALL UpdatePB  ;update port B from buffer
PWREXIT
;LDI TSCR,015h  ;inhibit timer
 CALL RstWDR  ;reset watch dog timer
 LDI A,FULLTIME  ;TCR is reloaded here for 1 full cycle
 LD TCR,A  ;
 LDI TSCR,05dh  ;reload prescaler and start timer
 JRR Crnkng,Flags4,PC_Norm
PC_Crank
 CALL CLOCKS  ;update clocks
 RES NMInt,Flags2  ;tell ExitMain this was NMI interupt
 JP PCexit  ;leave SCRs on during Crank
;turn off SCR drive so that only a pulse is generated (SCR′s latch on)
PC_Norm
 SET NMInt,Flags2  ;tell ExitMain this was timer interupt
;RES SCRs,DRBbuf ;otherwise,turn offSCR′s(in buffer)
;CALL UpdatePB  ;update port B from buffer
PCexit
 LD A,ATemp  ;restore A register
 RETI
;***************************************************************************
;*           NON-MASKABLE INTERRUPT HANDLER   *
;*This is the NMI interrupt routine. The NMI is generated on the falling *
;*edge of the full wave rectified AC line voltage. An interrupt is  *
;*generated 120 times per second,once every 8.333ms.After each NMI,*
;*this routine performs the following steps.  *
;*1.Reset the watchdog timer and save the registers.  *
;*2.Turn off the SCRs(unless during CrankON state).    *
;*3.Set the interrupt timer according to OFFSET.   *
;*4.Reset NMInt so ExitMain knows it′s an NMI(not timer int). *
;*5.Update the clocks.    *
;*6.Restore the registers.   *
;*If turned off,the SCRs will remain off for a period determined by *
;*OFFSET.The Timer will then trigger an interrupt which tells PwrCon *
;*to turn the SCRs back on if necessary.  *
;*            *
;***************************************************************************
IT_TIMER
 CALL RstWDR  ;reset watch dog timer
 LD ATemp,A  ;save A register
 LD A,X  ;get X register
 LD XTEMP,A  ;save X register
 JRS Crnkng,Flags4,IT_X
IT_Norm
 NOP
;LDI X,2Ah  ;delay for true zero cross
 LDI X,03h  ;delay for true zero cross
IT_T
 DEC X
 JRNZ IT_T
 NOP  ;adjust zero cross delay
 LD A,OFFSET  ;get current offset
 LD TCR,A  ;load the counter with current offset
 LDI TSCR,01011101b ;reload prescaler(32)and start timer
 RES SCRs,DRBbuf ;turn off SCR′s(in buffer)
 CALL UpdatePB ;update port B from buffer
IT_TMR
 RES NMInt,Flags2  ;tell ExitMain this was NMI interupt
 CALL CLOCKS  ;update clocks
IT_X
 LD A,XTEMP  ;restore registers
 LD X,A
 LD A,ATemp
RETI
;***************************************************************************
;*  A/D INTERRUPT HANDLER   *
;* This is the A to D interrupt service routine.The only thing it does is *
;* clear the interrupt bit and wakes the processor up from its wait mode. *
;***************************************************************************
ADINT
 RES 7,ADCR
 LD A,ADR
 RETI
;***************************************************************************
;*  ROM DATA WINDOW for THIRD VOLTS LED DIGIT  *
;* The following bit patterns are used to display the indicated numbers as  *
;* the third(least significant)digit of the voltage display.  *
;***************************************************************************
.block 16-$%16
Digits0Vx
;patterns for DigiDat1-Digit 1(LSD) & decimal point
.byte 00010010b ;display_0 for 00h
.byte 01111110b ;display_1 for 01h
.byte 01111110b ;display_1 for 02h
.byte 00110001b ;display_2 for 03h
.byte 00111000b ;display_3 for 04h
.byte 00111000b ;display_3 for 05h
.byte 01011100b ;display_4 for 06h
.byte 10011000b ;display_5 for 07h
.byte 10011000b ;display_5 for 08h
.byte 10010000b ;display_6 for 09h
.byte 00111110b ;display_7 for 0Ah
.byte 00111110b ;display_7 for 0Bh
.byte 00010000b ;display_8 for 0Ch
.byte 00011000b ;display_9 for 0Dh
.byte 00011000b ;display_9 for 0Eh
;***************************************************************************
;*  ROM DATA WINDOW for THIRD LED DIGIT  *
;* The following bit patterns are used to display the indicated numbers as *
;* the third(least significant)digit on the LED.  *
;***************************************************************************
.block 16-$%16
Digits00x
;patterns for DigiDat1-Digit 1(LSD) & decimal point
;segment bafpedgc
.byte 00010010b ;bit pattern to display_0
.byte 01111110b ;bit pattern to display_1
.byte 00110001b ;bit pattern to display_2
.byte 00111000b ;bit pattern to display_3
.byte 01011100b ;bit pattern to display_4
.byte 10011000b ;bit pattern to display_5
.byte 10010000b ;bit pattern to display_6
.byte 00111110b ;bit pattern to display_7
.byte 00010000b ;bit pattern to display_8
.byte 00011000b ;bit pattern to display_9
;***************************************************************************
;*  ROM DATA WINDOW for SECOND LED DIGIT  *
;* The following bit patterns are used to display the indicated numbers as *
;* the second(middle significant)digit on the LED.   *
;***************************************************************************
.block 16-$%16
Digits0x0
;patterns for DigiDat2-Digit 2(middle digit) and MS 1
.byte 00000101b ;bit pattern to display_0_
.byte 11001111b ;bit pattern to display_1_
.byte 00100011b ;bit pattern to display_2_
.byte 10000011b ;bit pattern to display_3_
.byte 11001001b ;bit pattern to display_4_
.byte 10010001b ;bit pattern to display_5_
.byte 00010001b ;bit pattern to display_6_
.byte 11000111b ;bit pattern to display_7_
.byte 00000001b ;bit pattern to display_8_
.byte 10000001b ;bit pattern to display_9_
;***************************************************************************
;*  ROM DATA WINDOW for Alternator Charge in Percent  *
;* The following values are the Percent values for the alternator voltages *
;* listed below.These numbers are only used when the charger is in  *
;* Tester mode.Voltages lower than the first entry are displayed as 0%  *
;* charged.Voltages above the last entry are displayed as 199%charged.  *
;***************************************************************************
.block 32-$%32
AltLvls
;% Volts Hex
.byte 0 ;13.53 CB red
.byte 12 ;13.60 CC |
.byte 25 ;13.67 CD |
.byte 38 ;13.73 CE red
.byte 50 ;13.80 CF yellow
.byte 62 ;13.87 D0 |
.byte 75 ;13.93 D1 yellow
.byte 85 ;14.00 D2 green
.byte 92 ;14.07 D3 |
.byte 97 ;14.13 D4 |
.byte 100 ;14.20 D5 |
.byte 100 ;14.27 D6 |
.byte 100 ;14.33 D7 |
.byte 100 ;14.40 D8 |
.byte 100 ;14.47 D9 |
.byte 100 ;14.53 DA |
.byte 100 ;14.60 DB |
.byte 103 ;14.67 DC |
.byte 110 ;14.73 DD |
.byte 120 ;14.80 DE green
.byte 130 ;14.87 DF yellow
.byte 140 ;14.93 E0 |
.byte 150 ;15.00 E1 yellow
.byte 160 ;15.07 E2 red
.byte 170 ;15.13 E3 |
.byte 180 ;15.20 E4 |
.byte 190 ;15.27 E5 |
.byte 196 ;15.33 E6 red
.byte 199 ;15.40 E7 red
;***************************************************************************
;*  ROM DATA WINDOW FOR Slow mode  *
;* These are the offsets to control the current output.  *
;***************************************************************************
.block 64-$%64
OffAdjSlo
;Offset  BADhi
;Dec Hex  Index Volts Hex Dec
.byte 132 ;84 0 10.00 96 150
.byte 132 ;84 1 10.07 97 151
.byte 132 ;84 2 10.13 98 152
.byte 132 ;84 3 10.20 99 153
.byte 132 ;84 4 10.27 9A 154
.byte 131 ;83 5 10.33 9B 155
.byte 131 ;83 6 10.40 9C 156
.byte 131 ;83 7 10.47 9D 157
.byte 131 ;83 8 10.53 9E 158
.byte 131 ;83 9 10.60 9F 159
.byte 130 ;82 10 10.67 A0 160
.byte 130 ;82 11 10.73 A1 161
.byte 130 ;82 12 10.80 A2 162
.byte 130 ;82 13 10.87 A3 163
.byte 130 ;82 14 10.93 A4 164
.byte 129 ;81 15 11.00 A5 165
.byte 129 ;81 16 11.07 A6 166
.byte 129 ;81 17 11.13 A7 167
.byte 129 ;81 18 11.20 A8 168
.byte 129 ;81 19 11.27 A9 169
.byte 128 ;80 20 11.33 AA 170
.byte 128 ;80 21 11.40 AB 171
.byte 128 ;80 22 11.47 AC 172
.byte 128 ;80 23 11.53 AD 173
.byte 128 ;80 24 11.60 AE 174
.byte 128 ;80 25 11.67 AF 175
.byte 127 ;7F 26 11.73 B0 176
.byte 127 ;7F 27 11.80 B1 177
.byte 127 ;7F 28 11.87 B2 178
.byte 127 ;7F 29 11.93 B3 179
.byte 127 ;7F 30 12.00 B4 180
.byte 127 ;7F 31 12.07 B5 181
.byte 126 ;7E 32 12.13 B6 182
.byte 126 ;7E 33 12.20 B7 183
.byte 126 ;7E 34 12.27 B8 184
.byte 126 ;7E 35 12.33 B9 185
.byte 126 ;7E 36 12.40 BA 186
.byte 125 ;7D 37 12.47 BB 187
.byte 125 ;7D 38 12.53 BC 188
.byte 125 ;7D 39 12.60 BD 189
.byte 125 ;7D 40 12.67 BE 190
.byte 124 ;7C 41 12.73 BF 191
.byte 124 ;7C 42 12.80 C0 192
.byte 124 ;7C 43 12.87 C1 193
.byte 124 ;7C 44 12.93 C2 194
.byte 124 ;7C 45 13.00 C3 195
.byte 124 ;7C 46 13.07 C4 196
.byte 123 ;7B 47 13.13 C5 197
.byte 123 ;7B 48 13.20 C6 198
.byte 122 ;7A 49 13.27 C7 199
.byte 122 ;7A 50 13.33 C8 200
.byte 122 ;7A 51 13.40 C9 201
.byte 122 ;7A 52 13.47 CA 202
.byte 122 ;7A 53 13.53 CB 203
.byte 122 ;7A 54 13.60 CC 204
.byte 121 ;79 55 13.67 CD 205
.byte 121 ;79 56 13.73 CE 206
.byte 121 ;79 57 13.80 CF 207
.byte 121 ;79 58 13.87 D0 208
.byte 120 ;78 59 13.93 D1 209
.byte 120 ;78 60 14.00 D2 210
.byte 120 ;78 61 14.07 D3 211
.byte 120 ;78 62 14.13 D4 212
.byte 119 ;77 63 14.20 D5 213
;***************************************************************************
;*  ROM DATA WINDOW FOR Fast mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 64-$%64
OffAdjFst
;Offset   BADhi
;Dec Hex   Index Volts Hex Dec
.byte 107 ;6D 0 10.00 96 150
.byte 107 ;6D 1 10.07 97 151
.byte 107 ;6D 2 10.13 98 152
.byte 107 ;6D 3 10.20 99 153
.byte 107 ;6D 4 10.27 9A 154
.byte 107 ;6D 5 10.33 9B 155
.byte 107 ;6D 6 10.40 9C 156
.byte 107 ;6D 7 10.47 9D 157
.byte 107 ;6D 8 10.53 9E 158
.byte 107 ;6D 9 10.60 9F 159
.byte 107 ;6D 10 10.67 A0 160
.byte 106 ;6C 11 10.73 A1 161
.byte 106 ;6C 12 10.80 A2 162
.byte 106 ;6C 13 10.87 A3 163
.byte 106 ;6C 14 10.93 A4 164
.byte 105 ;6B 15 11.00 A5 165
.byte 105 ;6B 16 11.07 A6 166
.byte 105 ;6B 17 11.13 A7 167
.byte 104 ;6A 18 11.20 A8 168
.byte 104 ;6A 19 11.27 A9 169
.byte 103 ;69 20 11.33 AA 170
.byte 103 ;69 21 11.40 AB 171
.byte 103 ;69 22 11.47 AC 172
.byte 103 ;69 23 11.53 AD 173
.byte 102 ;68 24 11.60 AE 174
.byte 102 ;68 25 11.67 AF 175
.byte 102 ;68 26 11.73 B0 176
.byte 101 ;67 27 11.80 B1 177
.byte 101 ;67 28 11.87 B2 178
.byte 101 ;67 29 11.93 B3 179
.byte 101 ;67 30 12.00 B4 180
.byte 101 ;67 31 12.07 B5 181
.byte 100 ;66 32 12.13 B6 182
.byte 100 ;66 33 12.20 B7 183
.byte 100 ;66 34 12.27 B8 184
.byte 99 ;65 35 12.33 B9 185
.byte 99 ;65 36 12.40 BA 186
.byte 99 ;65 37 12.47 BB 187
.byte 98 ;64 38 12.53 BC 188
.byte 98 ;64 39 12.60 BD 189
.byte 98 ;64 40 12.67 BE 190
.byte 98 ;64 41 12.73 BF 191
.byte 97 ;63 42 12.80 C0 192
.byte 97 ;63 43 12.87 C1 193
.byte 97 ;63 44 12.93 C2 194
.byte 96 ;62 45 13.00 C3 195
.byte 96 ;62 46 13.07 C4 196
.byte 96 ;62 47 13.13 C5 197
.byte 95 ;61 48 13.20 C6 198
.byte 95 ;61 49 13.27 C7 199
.byte 95 ;61 50 13.33 C8 200
.byte 95 ;61 51 13.40 C9 201
.byte 94 ;60 52 13.47 CA 202
.byte 94 ;60 53 13.53 CB 203
.byte 94 ;60 54 13.60 CC 204
.byte 93 ;5F 55 13.67 CD 205
.byte 93 ;5F 56 13.73 CE 206
.byte 93 ;5F 57 13.80 CF 207
.byte 92 ;5E 58 13.87 D0 208
.byte 92 ;5E 59 13.93 D1 209
.byte 92 ;5E 60 14.00 D2 210
.byte 91 ;5D 61 14.07 D3 211
.byte 91 ;5D 62 14.13 D4 212
.byte 90 ;5C 63 14.20 D5 213
;***************************************************************************
;*  ROM DATA WINDOW FOR Rapid mode  *
;* These are the offsets to control the current output.  *
;***************************************************************************
;.block 64-$%64
OffAdjRap
;Offset   BADhi
;Dec Hex   Index Volts Hex Dec
.byte 80 ;50 0 10.00 96 150
.byte 80 ;50 1 10.07 97 151
.byte 80 ;50 2 10.13 98 152
.byte 80 ;50 3 10.20 99 153
.byte 80 ;50 4 10.27 9A 154
.byte 80 ;50 5 10.33 9B 155
.byte 79 ;4F 6 10.40 9C 156
.byte 79 ;4F 7 10.47 9D 157
.byte 78 ;4E 8 10.53 9E 158
.byte 78 ;4E 9 10.60 9F 159
.byte 77 ;4D 10 10.67 A0 160
.byte 77 ;4D 11 10.73 A1 161
.byte 77 ;4D 12 10.80 A2 162
.byte 77 ;4D 13 10.87 A3 163
.byte 77 ;4D 14 10.93 A4 164
.byte 76 ;4C 15 11.00 A5 165
.byte 76 ;4C 16 11.07 A6 166
.byte 76 ;4C 17 11.13 A7 167
.byte 75 ;4B 18 11.20 A8 168
.byte 75 ;4B 19 11.27 A9 169
.byte 74 ;4A 20 11.33 AA 170
.byte 73 ;49 21 11.40 AB 171
.byte 73 ;49 22 11.47 AC 172
.byte 73 ;49 23 11.53 AD 173
.byte 72 ;48 24 11.60 AE 174
.byte 71 ;47 25 11.67 AF 175
.byte 70 ;46 26 11.73 B0 176
.byte 69 ;45 27 11.80 B1 177
.byte 68 ;44 28 11.87 B2 178
.byte 67 ;43 29 11.93 B3 179
.byte 67 ;43 30 12.00 B4 180
.byte 66 ;42 31 12.07 B5 181
.byte 65 ;41 32 12.13 B6 182
.byte 65 ;41 33 12.20 B7 183
.byte 64 ;40 34 12.27 B8 184
.byte 63 ;3F 35 12.33 B9 185
.byte 63 ;3F 36 12.40 BA 186
.byte 62 ;3E 37 12.47 BB 187
.byte 61 ;3D 38 12.53 BC 188
.byte 61 ;3D 39 12.60 BD 189
.byte 60 ;3C 40 12.67 BE 190
.byte 59 ;3B 41 12.73 BF 191
.byte 58 ;3A 42 12.80 C0 192
.byte 57 ;39 43 12.87 C1 193
.byte 55 ;37 44 12.93 C2 194
.byte 53 ;35 45 13.00 C3 195
.byte 51 ;33 46 13.07 C4 196
.byte 49 ;31 47 13.13 C5 197
.byte 47 ;2F 48 13.20 C6 198
.byte 45 ;2D 49 13.27 C7 199
.byte 44 ;2C 50 13.33 C8 200
.byte 42 ;2A 51 13.40 C9 201
.byte 41 ;29 52 13.47 CA 202
.byte 40 ;28 53 13.53 CB 203
.byte 39 ;27 54 13.60 CC 204
.byte 38 ;26 55 13.67 CD 205
.byte 37 ;25 56 13.73 CE 206
.byte 36 ;24 57 13.80 CF 207
.byte 35 ;23 58 13.87 D0 208
.byte 34 ;22 59 13.93 D1 209
.byte 33 ;21 60 14.00 D2 210
.byte 32 ;20 61 14.07 D3 211
.byte 31 ;1F 62 14.13 D4 212
.byte 30 ;1E 63 14.20 D5 213
;***************************************************************************
;*  ROM DATA WINDOW FOR 6V 2 amp mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 32-$%32
OfAd6Slo
; Offset   Volts
;Dec Hex   Index Dec Hex
.byte 135 ;8A 0 5.00 4B
.byte 140 ;8A 1 5.07 4C
.byte 140 ;89 2 5.13 4D
.byte 140 ;89 3 5.20 4E
.byte 140 ;89 4 5.27 4F
.byte 140 ;88 5 5.33 50
.byte 140 ;88 6 5.40 51
.byte 140 ;88 7 5.47 52
.byte 140 ;87 8 5.53 53
.byte 140 ;87 9 5.60 54
.byte 140 ;87 10 5.67 55
.byte 140 ;86 11 5.73 56
.byte 140 ;86 12 5.80 57
.byte 139 ;86 13 5.87 58
.byte 139 ;85 14 5.93 59
.byte 139 ;85 15 6.00 5A
.byte 139 ;85 16 6.07 5B
.byte 139 ;84 17 6.13 5C
.byte 139 ;84 18 6.20 5D
.byte 139 ;84 19 6.27 5E
.byte 138 ;83 20 6.33 5F
.byte 138 ;83 21 6.40 60
.byte 138 ;83 22 6.47 61
.byte 138 ;82 23 6.53 62
.byte 137 ;82 24 6.60 63
.byte 137 ;82 25 6.67 64
.byte 137 ;81 26 6.73 65
.byte 137 ;81 27 6.80 66
.byte 137 ;81 28 6.87 67
.byte 136 ;80 29 6.93 68
.byte 136 ;80 30 7.00 69
.byte 136 ;80 31 7.07 6A
;***************************************************************************
;*  ROM DATA WINDOW FOR 6V 15 amp mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 32-$%32
OfAd6Fst
; Offset   Volts
;Dec Hex   Index Dec Hex
.byte 121 ;0 4.47 43 7B
.byte 120 ;1 4.54 44 70
.byte 120 ;2 4.60 45 6A
.byte 120 ;3 4.67 46 67
.byte 119 ;4 4.74 47 67
.byte 119 ;5 4.80 48 67
.byte 119 ;6 4.87 49 66
.byte 119 ;7 4.94 4A 66
.byte 119 ;8 5.00 4B 66
.byte 119 ;9 5.07 4C 65
.byte 119 ;10 5.14 4D 65
.byte 118 ;11 5.20 4E 64
.byte 118 ;12 5.27 4F 64
.byte 118 ;13 5.34 50 64
.byte 118 ;14 5.40 51 63
.byte 118 ;15 5.47 52 63
.byte 118 ;16 5.54 53 63
.byte 118 ;17 5.60 54 62
.byte 118 ;18 5.67 55 62
.byte 118 ;19 5.74 56 62
.byte 118 ;20 5.80 57 61
.byte 118 ;21 5.87 58 61
.byte 118 ;22 5.94 59 61
.byte 117 ;23 6.00 5A 60
.byte 117 ;24 6.07 5B 60
.byte 117 ;25 6.14 5C 5F
.byte 117 ;26 6.20 5D 5F
.byte 117 ;27 6.27 5E 5F
.byte 117 ;28 6.34 5F 5E
.byte 117 ;29 6.40 60 5E
.byte 117 ;30 6.47 61 5E
.byte 117 ;31 6.54 62 5E
;***************************************************************************
;*  ROM DATA WINDOW FOR 6V 60 amp mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 32-$%32
OfAd6Rap
; Offset   Volts
;Dec Hex   Index Dec Hex
.byte 88 ;8A 0 4.87 49
.byte 88 ;8A 1 4.94 4A
.byte 87 ;8A 2 5.00 4B
.byte 87 ;8A 3 5.07 4C
.byte 87 ;89 4 5.13 4D
.byte 86 ;89 5 5.20 4E
.byte 86 ;89 6 5.27 4F
.byte 86 ;88 7 5.33 50
.byte 85 ;88 8 5.40 51
.byte 85 ;88 9 5.47 52
.byte 85 ;87 10 5.53 53
.byte 85 ;87 11 5.60 54
.byte 85 ;87 12 5.67 55
.byte 85 ;86 13 5.73 56
.byte 85 ;86 14 5.80 57
.byte 85 ;86 15 5.87 58
.byte 85 ;85 16 5.93 59
.byte 84 ;85 17 6.00 5A
.byte 84 ;85 18 6.07 5B
.byte 84 ;84 19 6.13 5C
.byte 84 ;84 20 6.20 5D
.byte 84 ;84 21 6.27 5E
.byte 84 ;83 22 6.33 5F
.byte 84 ;83 23 6.40 60
.byte 83 ;83 24 6.47 61
.byte 83 ;82 25 6.53 62
.byte 83 ;82 26 6.60 63
.byte 83 ;82 27 6.67 64
.byte 83 ;81 28 6.73 65
.byte 83 ;81 29 6.80 66
.byte 83 ;81 30 6.87 67
.byte 82 ;80 31 6.93 68
;***************************************************************************
;*              Interrupt vectors           *
;***************************************************************************
.org 0FF0h
ADC
 JP ADINT
TIMER
 JP PwrCon
INT2
 NOP
 RETI
INT1
 NOP
 RETI
.org 0FFCh
NMI
 JP IT_TIMER
RST
 JP RESET
 .END
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------
30060.asm
;Checksum
;Raw Code:  70A45
;With Info:  70A45
;***************************************************************************
;*   COPYRIGHT 2004 SCHUMACHER ELECTRIC   *
;*    ALL RIGHTS RESERVED  *
;*     WRITTEN BY   *
;*   THOMAS F.JOHNSON   *
;*      *
;* Linear PSW-30060A Charger/Starter/Tester  *
;* This code is for the SGS-THOMPSON micro-controler  *
;* Part number ST62T25/ST62E25     *
;*        *
;*;***************************************************************************
 .title ″ProSeries 300-60-15-2A Wheeled Linear Charger Ver.0.21″
 .LINESIZE 131
 .vers ″ST6225″
 .romsize 4
 .w_on
ShoOff .SET 0;1->norma1,0->Show OFFSET in Alt% mode during charging
FastCP .SET 1;1->norma1,0->3 min ChkProg interval instead of 60 min
ShoADC .SET 1;1->norma1,0->Use PB2 to indicate A/D activity
;***************************************************************************
;*  Define the port hardware locations  *
;***************************************************************************
;*  At times,the .def statement is followed by a value and ″!m″.The !m *
;*is used by the simulator/emulator for debugging.This symbol tells the *
;*equipment what registers the user wants to monitor during debuging.   *
;***************************************************************************
X .def 80h!m       ;Index register
Y .def 81h        ;Index register
V .def 82h        ;Short direct register
W .def 83h        ;Short direct register
A .def 0ffh!m     ;Accumulator
DRA .def 0c0h!m      ;Port a data register
DRB .def 0c1h!m      ;Port b data register
DRC .def 0c2h       ;Port c data register
DDRA .def 0c4h        ;Port a direction register
DDRB .def 0c5h        ;Port b direction register
DDRC .def 0c6h        ;Port c direction register
ORA .def 0cch       ;Port a option register
ORB .def 0cdh       ;Port b option register
ORC .def 0ceh       ;Port c option register
ADR .def 0d0h!m      ;A/D data register
ADCR .def 0d1h      ;A/D control register
PSC .def 0d2h      ;Timer prescaler register
TCR .def 0d3h!m     ;Timer counter register
TSCR .def 0d4h       ;Timer status control register
WDR .def 0d8h        ;Watchdog register
IOR .def 0c8h!m     ;Interrupt option register
DRWR .def 0c9h        ;Data rom window register
;****************************************************************************
;*     These are the ram equates used by the battery charger.    *
;****************************************************************************
DRAbuf .def 084h ;shadow ram for port A data register
DRBbuf .def 085h ;shadow ram for port B data register
DRCbuf .def 086h ;shadow ram for port C data register
ATemp .def 087h ;Accumulator temporary storage
XTEMP .def 088h ;X register temporary storage
MSecs1 .def 089h ;storage for 8.333ms tics-count of 120=1 sec
Secs1 .def 08Ah ;storage for timer1 seconds
Mins1 .def 08Bh ;storage for timer1 minutes
Hrs1 .def 08Ch ;storage for timer1 hours
TicFlag1 .def 08Dh ;overflow flags for Secs1,Mins1,and hours
MSecs2 .def 08Eh ;millisecond one counter
Secs2 .def 08Fh ;storage for timer2 seconds
Mins2 .def 090h ;storage for timer2 minutes
Hrs2 .def 091h ;storage for timer2 hours
TicFlag2 .def 092h ;overflow flags for Secs1,Mins2,and hours1
Tries .def 093h ;used by battery detect routines
TEMP  .def 094h ;scratch pad area
TEMP1 .def 095h ;scratch pad area
Temp2  .def 096h ;count used for FreshBV
CurVolt  .def097h ;current battery voltage
MaintVolt .def 098h ;storage for MAINTAIN voltage level
OldVolt  .def 099h ;previous battery voltage.used for dv/dt
CCDcnt  .def 09Ah ;display countdown during crank cool down
OldOff .def 09Bh ;old value of OFFSET used in dI/dt
BADlo .def 09Ch ;low bits battery voltage average
BADhi .def 09Dh ;hi bits battery voltage average
Vmax  .def 09Eh ;maximum battery voltage(per Battery Type)
Vref  .def 09Fh ;ref voltage for desulfation
OFFSET .def 0A0h ;storage for phase delay value
FreshBV .def 0A1h ;avg batt volt used for di/dt ref
FBVTotLo .def 0A2h ;low byte of total used for FreshBV
FBVTotHi .def 0A3h ;high byte of total used for FreshBV
CurentSS .def 0A4h ;stores current charger state
Flags .def 0A5h ;charger configuration states
  ;bit 0(BatTypeA): 0 for Reg,1 for D/C
  ;bit 1(BatTypeB): 0 for Norm,1 for AGM/GEL
  ;bit 2(Rate):  0 for Slow,1 for Fast
  ;bit 3(Crank):  1 ifin Boost mode
  ;bit 4(CrankWait): 1 during E/S cool down
  ;bit 5(Started):  1 if charging started
  ;bit 6(MtrUnits): 0 for Volts,1 for %
  ;bit 7(MtrScale): 0 for Batt,1 for Alt
Flags2.def 0A6h ;stores the following Flags
  ;bit 0(Batt):  1 ifbattery connected
  ;bit 1(Rapid):  1 if set for Rapid charge rate
  ;bit 2(Bat6V):  1 if set for 6V battery
  ;bit3(Power):  1 if outputis on
  ;bit 4(NMInt):  1 ifNMI interrupt,0 if Timer
  ;bit 5(ChMode): 1 if in Charger Mode
  ;bit 6(Wait0P): 1 if waiting for %to change from 0
  ;bit 7(Alert): 1 indicates Alert condition
Flags3.def 0A7h ;stores the following Flags
  ;bit 0(RmpInt): 1 during 1st halfofeach Ramp interval
  ;bit 1(Settle): 1 during voltage settle time
  ;bit 2(HiEnd):  1 ifhigher voltage for EndCharge
  ;bit 3(Idle):  1 until a button is pressed
  ;bit 4(Hi6V):  1 if battery>8.5V
  ;bit 5(NxtCnt): 1->lst second of count
  ;bit 6(Manual): 1 if in Manual Mode
  ;bit 7(BurnIn): 1 if in Burn-in Mode
SwDown.def 0A8h ;Indicates state of switches(1->pressed)
  ;bit 4=SwOff flag(debugging)
  ;bit 5=Type switch
  ;bit 6=Rate switch
  ;bit 7=Meter switch
DigiDat2 .def0A9h ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 3 segments B & C
  ;bit 1=digit 2 segment F
  ;bit 2=digit 2 segment G
  ;bit 3=digit 2 segment A
  ;bit 4=digit 2 segment B
  ;bit 5=digit 2 segment C
  ;bit 6=digit 2 segment D
  ;bit 7=digit 2 segment E
DigiDat1 .def 0AAh ;data for 8 of 16 segments of digital LED(0->ON,1->off)
  ;bit 0=digit 1 segment C
  ;bit 1=digit 1 segment G
  ;bit 2=digit 1 segment D
  ;bit 3=digit 1 segment E
  ;bit 4=digit 2 decimal point
  ;bit 5=digit 1 segment F
  ;bit 6=digit 1 segment A
  ;bit 7=digit 1 segment B
SwData def 0ABh ;data for the 3 Rate and 3 Type LEDs(0->ON,1->off)
  ;bit 0=6V battery type LED
  ;bit 1=Reg battery type LED
  ;bit 2=D/C battery type LED
  ;bit 3=AGM battery type LED
  ;bit 4=60A charge rate LED
  ;bit 5=15A charge rate LED
  ;bit 6=300A charge rate LED
  ;bit 7=2A charge rate LED
BitCnt .def 0ACh ;Index of bit sent to display
BytCnt .def 0ADh ;Index of word sent to display
DataBuf .def 0AEh ;Temp storage for Data bits
VltCnt .def 0AFh ;Counter for voltage display interval
TempOff.def 0B0h ;temp offset value
RmpCnt .def 0B1h ;counts ramp intervals until next ramp
LEDnum .def 0B2h ;stores number to be shown on digital LED
Percent .def 0B3h ;stores percent to be shown on digital LED
Index .def 0B4h ;used for look up table access
LowOff.def 0B5h ;min offset value for di/dt(highest current)
VRcnt .def 0B6h ;Counter for voltage regulation interval
PcntL .def 0B7h ;NMI counter for percent display update
PcntH .def 0B8h ;Interval counter for percent display update
DspPcnt .def 0B9h ;storage for last percent displayed
Flags4.def 0BAh ;stores the following Flags
  ;bit 0(IdleSet): 1 if 10 minute Idle timer was started
  ;bit 1(NoRamp): 1 during Manual Fast charge
  ;bit 2(SOC): 1 if at start of charge(1st 5s)
  ;bit 3(Crnkng): 1 if cranking(State 19)
  ;bit4(HiPwr): 1 if charge rate>Fast
LastBatt .def 0BBh ;stores battery reading used to monitor progress
;free .def 0BCh ;free
ORBbuf .def0BDh ;shadow RAM for ORB register
;free .def 0BEh ;free
;free .def 0BFh ;free
;0BFh=last RAM location
;***************************************************************************
;*These are the constants used by the battery charger.  *
;***************************************************************************
Volts005  .equ 008h ;0.5 VOLTS
Volts0  .equ 00Ah ;0.7 VOLTS
Volts01  .equ 00Fh ;1.0 VOLTS
Volts016  .equ 017h ;miminum voltage for engine start,1.5V
Volts02  .equ 01Eh ;2.0 VOLTS
Volts05  .equ 04Bh ;5.0 VOLTS
Volts06  .equ 05Ah ;6.0 VOLTS
Volts066  .equ 061h ;6.6 VOLTS
Volts075  .equ 071h ;7.5 VOLTS
Volts09  .equ 087h ;very discharged battery voltage
Volts10  .equ 096h ;10.0 VOLTS
BattMin .equ 0AFh ;lowest value in Battery % LUT
Volts12  .equ 0B4h ;low battery voltage
Volts122  .equ 0B7h
Volts125  .equ 0BCh
BattMax  .equ 0BDh ;highest value in Battery % LUT
Volts 127  .equ 0BEh
Volts 128  .equ 0C0h ;good battery test voltage
Volts13  .equ 0C3h
Volts132  .equ 0C6h
Volts135  .equ 0CAh
AltMin  .equ 0CBh ;lowest value in Alternator % LUT
Volts138  .equ 0CFh
Volts14  .equ 0D2h
Volts142  .equ 0D5h ;start monitoring dv/dt voltage
Volts1435  .equ 0D7h
Volts144  .equ 0D8h
Volts146  .equ 0DAh ;maximum allowed voltage for reg/gel mode
Volts147  .equ 0DCh ;start trickle timer voltage
Volts149  .equ 0E0h ;14.87V
Volts15  .equ 0E1h ;maximum allowed voltage for RV/DC Marine
Volts15a  .equ 0E2h ;15.07V
AltMax  .equ 0E7h ;highest value in Alternator %LUT
Volts155  .equ 0E9h ;maximum allowed voltage for Auto/Marine Starting
Volts16  .equ 0F0h ;maximum allowed voltage
Volts165  .equ 0F7h ;maximum allowed voltage for deep cycle 2
Volts17  .equ 0FCh ;maximum allowed voltage
MaxVolts  .equ 0FFh ;maximum voltage reading -17.0V
RCinit  .equ 180 ;180 1-second intervals yields 180 seconds
RCinitX2  .equ 180 ;180 1-second intervals yields 180 seconds
RIinit  .equ 60 ;60 NMI interrupts yields 0.5 seconds
MSINIT  .equ 078h ;millisecond initialization value(120)
MS500  .equ 03Ch ;millisecond counter value for 500mS(60)
MS200  .equ 018h ;millisecond counter value for 200mS(24)
SecInit  .equ 03Ch ;second initialization value(60)
MinInit  .equ 03Ch ;minute initialization value(60)
MaxHrs  .equ 25 ;maximum allowed charge hours+1
CPint  .equ 60 ;minutes per charge progress interval
HR  .equ 000h ;hours bit of TicFlag1 and TicFlag2
MIN  .equ 001h ;minutes bit of TicFlag1 and TicFlag2
SEC  .equ 002h ;seconds bit of TicFlag1 and TicFlag2
MSEC  .equ 003h ;milliseconds
VLO  .equ 0C0h ;low line limit -100 VAC
VHI  .equ 0EEh ;high line voltage limit-130 VAC
BatLo2  .equ 096h ;low battery voltage current adjust -10.0 Vdc
BatLo15  .equ 087h ;low battery voltage current adjust -9.0 Vdc
BatLo60  .equ 093h ;low battery voltage current adjust -9.8 Vdc
Bat6Lo2  .equ 04Bh ;low battery voltage current adjust -5.0 Vdc
Bat6Lo15  .equ 043h ;low battery voltage current adjust -4.5 Vdc
Bat6Lo60  .equ 049h ;low battery voltage current adjust -4.9 Vdc
;BatHi2  .equ 0D5h
;BatHi15  .equ 0C6h
PCint  .equ 00Ah ;number of 1-second intervals between % updates
FULLTIME  .equ 0ADh ;half second when AC power is OFF
SlowAmps  .equ 2 ;Nominal amps out at Slow rate
FastAmps  .equ 15 ;Nominal amps out at Fast rate
RapAmps  .equ 60 ;Nominal amps out at Rapid rate
CmkAmps  .equ 103 ;Nominal amps out at Crank rate
CodeRev  .equ 0 ;software revision level
OffLow2  .equ 128  ;Lowest current in 12V 2A offset table
OffSlow  .equ 117  ;Nominal offset for slow charge(~20%)
OffHi2  .equ 117  ;Current in 12V 2A offset table for 14.0V
MinOff2  .equ 115  ;Max Current for 12V 2A rate during di/dt
OffLow15  .equ 112  ;Lowest current in 12V 15A offset table
OffFast  .equ 99  ;Nominal offset for fast charge(15A)
OFF15AMP  .equ 99 ;offset value for 12V 15 amp mode
OffHi15  .equ 99 ;Highest current in 12V 15A offset table
MinOff15  .equ 97 ;Max Current for 12V 15A rate during di/dt
OffRap   .equ 77  ;Nominal offset for rapid charge(~90%)
OffLow60  .equ 77  ;Lowest current in 12V 60A offset table
OffHi60  .equ 48 ;Highest current in 12V 60A offset table
OffCrank  .equ 95 ;OFFSET for Crank standby
Off6Lo2  .equ 135  ;First entry in 6V 2A offset table
Off6Slo  .equ 136  ;Nominal offset for 6V slow charge(2A)
Off6Hi2  .equ 136  ;Current in 6V 2A offset table for 7.0V
Min6Off2  .equ 134  ;Max Current for 6V 2A rate during di/dt
Off6Lo15  .equ 121  ;Lowest current in 6V 15A offset table
Off6Fst  .equ 117  ;Nominal offset for 6V fast charge(15A)
Off6Hi15  .equ 117 ;Highest current in 6V 15A offset table
Min6Off15  .equ 115 ;Max Current for 6V 15A rate during di/dt
Off6Rap  .equ 88  ;Nominal offset for 6V rapid charge(60A)
Off6Lo60  .equ 88  ;Lowest current in 6V 60A offset table
Off6Hi60  .equ 82 ;Highest current in 6V 60A offset table
Off6Crnk  .equ 105 ;OFFSET for 6V Crank standby
HiOff  .equ 140 ;high limit for OFFSET variable
HiOff6  .equ 150 ;high limit for OFFSET variable(6V mode)
ABORT  .equ 008h ;abort state
LEDslow  .equ 007h ;Slow LED -bit of SwData
LEDboost  .equ 006h ;Crank LED -bit of SwData
LEDfast  .equ 005h ;Fast LED -bit of SwData
LEDrap  .equ 004h ;Rapid LED -bit of SwData
LEDgel  .equ 003h ;AGM/Gel LED -bit of SwData
LEDdeep  .equ 002h ;Dp Cycl LED -bit of SwData
LEDreg  .equ 001h ;Regular LED -bit of SwData
LED6V  .equ 000h ;6V Reg LED -bit of SwData
LEDdone  .equ 000h ;Charged LED -PORT A
LEDchgng  .equ 001h ;Charging LED -PORT A
LEDalert  .equ 002h ;Fault LED  -PORT A
LEDprcnt  .equ 003h ;Percent LED -PORT A
LEDvolt  .equ 004h ;Voltage LED -PORT A
LEDalt  .equ 005h ;Altrntr LED -PORT A
SerData  .equ 006h ;Serial Data -PORT A
ClrData  .equ 007h  ;Data Clear -PORT A
ShftClk  .equ 000h ;Shift Clock -PORT B
LtchClk  .equ 001h ;Latch Clock -PORT B
ESrly  .equ 003h ;E/S relay  -PORT B
Disable  .equ 006h ;Disable ctrl -PORT B
SCRs  .equ 007h ;SCR control -PORT B
FanCtl  .equ 004h ;Fan control -PORT C
TypeSw  .equ 005h ;Type switch -PORT C
RateSw  .equ 006h ;Rate switch -PORT C
MeterSw  .equ 007h ;Meter switch -PORT C
BatTypeA  .equ 000h ;bit in Flags for battery type:0=Reg,1=D/C
BatTypeB  .equ 001h ;bit in Flags for battery type:1=AGM/Gel Cell
Rate  .equ 002h ;bit in Flags for charge rate:0=Slow,1=Fast
Crank  .equ 003h ;bit in Flags that indicates engine start
CrankWait  .equ 004h ;bit in Flags that indicates cool down between cranks
Started  .equ 005h ;bit in Flags that indicates charge started
MtrUnits  .equ 006h ;bit in Flags for meter units:0=volts,1=%
MtrScale  .equ 007h ;bit in Flags for meter scale:0=batt,1=altrntr
Batt  .equ 000h ;bit in Flags2:1 if battery is connected
Rapid  .equ 001h ;bit in Flags2:1 if charge rate is Rapid
Bat6V  .equ 002h ;bit in Flags2:1 if output is>10A
Power  .equ 003h ;bit in Flags2:1 if output is on
NMInt  .equ 004h ;bit in Flags2:1 if NMI interrupt,0 if Timer
ChMode  .equ 005h ;bit in Flags2:1 if in Charger mode(not Tester)
Wait0P  .equ 006h ;bit in Flags2:1 if battery>10V
Alert  .equ 007h ;bit in Flags2:1 indicates trouble
RmpInt  .equ 000h ;bit in Flags3:1 during 1st half each Ramp interval
Settle  .equ 001h ;bit in Flags3:1 during voltage settle time
HiEnd  .equ 002h ;bit in Flags3:1 if higher voltage for EndCharge
Idle  .equ 003h ;bit in Flags3:1 until a button is pressed
Hi6V  .equ 004h ;bit in Flags3:1 if battery>8.5V
NxtCnt  .equ 005h ;bit in Flags3:0 during last half of CCDcnt interval
Manual  .equ 006h ;bit in Flags3:1 during Manual modes
BurnIn  .equ 007h ;bit in Flags3:1 during Burn-In mode
IdleSet  .equ 000h ;bit in Flags4:1 if 10minute Idle timer was started
NoRamp  .equ 001h ;bit in Flags4:1 during manual fast charge
SOC  .equ 002h ;bit in Flags4:1 during Start Of Charge(1st 5sec)
Crnkng  .equ 003h ;bit in Flags4:1 during cranking(State19)
HiPwr  .equ 004h ;bit in Flags4:1 if charge rate>Fast
CrankOff  .equ 180 ;crank off time in seconds
CrankON  .equ 5 ;crank on time in seconds
CCDint  .equ 001h ;crank cool down display counter interval(seconds)
CrankSS  .equ 010h ;crank SS is state 16=10hex
Decimal  .equ 004h ;bit in DigiDat1 for decimal point
Digit1  .equ 000h ;bit in DigiDat2 for most significant 1
SwsOff  .equ 11111111b ;bit pattern for all switches off
DigiOffa  .equ 11111111b ;bit pattern for all segements off
DigiOffb  .equ 11111111b ;bit pattern for all segements off
DigiONa  .equ 00000000b ;bit pattern for all segements ON
DigiONb  .equ 00000000b ;bit pattern for all segements ON
Dashes1  .equ 11111101b ;bit pattern to display__-
Dashes2  .equ 11111011b ;bit pattern to display_-_
DigiRev1  .equ 00010010b ;bit pattern to display__0
DigiRev2  .equ 01100001b ;bit pattern to display_P_
DigiMV1  .equ 00001000b ;bit pattern to display_.9
DigiMV2  .equ 10000000b ;bit pattern to display 19_
;***************************************************************************
;*                 COLD START                 *
;***************************************************************************
;.org 0880h ;for ST6210/15
 .org 0100h ;for ST6220/25
RESET
 CALL RstWDR ;reset watch dog timer
;***************************************************************************
;*              Clear The Ram Area               *
;***************************************************************************
RAMCLR
 LDI X,084h  ;point X to 1st RAM Location
RAMCLR1
CLR A  ;clear A
LD (X),A  ;store A at location pointed to by X
INC X  ;increment X
LD A,X  ;get pointer in A
CPI A,0C0h  ;test for end of RAM
JRNZ RAMCLR1  ;do again if not finished
;***************************************************************************
;*           Now Set Up The Hardware I/O Ports          *
;***************************************************************************
PORTA
 ;Bit 0=LED-Done  (Output,0=ON)
 ;Bit 1=LED-Charging(Output,0=ON)
 ;Bit 2=LED-Alert  (Output,0=ON)
 ;Bit 3=LED-Battery%(Output,0=ON)
 ;Bit 4=LED-Volts DC(Output,0=ON)
 ;Bit 5=LED-Altrntr%(Output,0=ON)
 ;Bit 6=Serial Data  (Output,0=ON)
 ;Bit 7=Display Clear (Output,0=clear)
 ;Bit#76543210
 LDI DDRA, 11111111b ;Set all bits as outputs
 LDI ORA, 11000000b ;open-drain outputs 0-5;6-7 push-pull
 LDIDRA, 11111111b ;Set initial values to 1(off)
 LDI DRAbuf,11111111b ;store settings in shadow RAM
PORTB
 ;Bit 0=Shift clock(Output,0->1=Shift)
 ;Bit 1=Latch clock(Output,0->1=Latch)
 ;Bit 2=LED -Amps (not used)
 ;Bit 3=E/S relay (Output,0=Charge,1=Start)
 ;Bit 4=Batt sense (not used)
 ;Bit 5=Batt Voltage (Input,Analog)
 ;Bit 6=Disable out(Output,1=disabled)
 ;Bit 7=SCR drive (Output,0=ON)
 ;Bit#76543210
 LDI DDRB, 11011111b ;bits 5 is input,others are outputs
 LDI ORB, 11111011b ;PB5 analog;PB2 open drain;others push-pull
  LDI DRB, 11100111b ;initialize high except 2-5
 LDI DRBbuf,11100111b ;store settings in shadow RAM
PORTC
 ;Bit 4=Fan Control (Output,0=off,1=ON)
 ;Bit 5=Type switch (Input,0=IN/change)
 ;Bit 6=Rate switch (Input,0=IN/change)
 ;Bit 7=Meter switch (Input,0=IN/change)
 ;Bit#76543210
 LDI DDRC, 00011111b ;bit 4 is output,others are inputs
 LDI ORC, 00011111b ;non-interrupt inputs,push-pull output
 LDI DRC, 00001111b ;Set internal pull-ups for bits 5-7
 LDI DRCbuf,00001111b ;store settings in shadow RAM
TSCRINIT
 LDI TSCR,00010101b ;reset TSCR and inhibit interupt
 SET 4,IOR      ;enable interupts
 RETI
 CALL InitState  ;initialize to slow (2A)auto mode
;The next three lines are to set the maximum idle tester time
 CALL IniTimel  ;initialize timer 1
 LDIMins1,0Ah  ;set timer 1 for 10minutes
 SET Idle,Flags3  ;indicates no buttons pressed yet
;The next three lines set the unit for Tester(not Charger)mode
 RES ChMode,Flags2  ;set for Tester Mode
 CALL ShowData  ;initialize display
INIT_01
;JP MAIN  ;debug
;***************************************************************************
;*    Test Routines   *
;*This routine checks the switches at power up to determine whether to *
;*enter one of the test modes.The possible test modes and the switch *
;*combinations that trigger them are as follows.  *
;*        *
;*Meter Rate Type Test Mode      *
;*Y x N Power On Self Test (POST):LED′s light in sequence *
;*N Y N Manual Slow Charge(1 hour max for all manual mode)*
;*N N  Y Manual Medium Charge(Fast for boost models)*
;*N Y  Y Manual Fast Charge(Fast-Rapid for boost models)*
;*Y x Y Burn-In Mode:Fast/Rapid Charge for 60minutes *
;*       *
;*Y->pressed,N->not pressed,x->either(not checked)*
;*        *
;***************************************************************************
TEST
 JRS MeterSw,DRC,NoPOST ;Skip ahead if Meter Mode button not pressed
 JRS TypeSw,DRC,POST ;Skip to POST if Type button not pressed
 JP TestBI  ;...otherwise,skip ahead to Burn-In setup
NoPOST
 JRR RateSw,DRC,TEST1 ;Check Type switch if Rate switch is pressed
 JRS TypeSw,DRC,NoTest ;go to MAIN if no switch is pressed
  ;Set for Manual Fast Charge
SET Rate,Flags  ;turn on Fast LED,turn off Slow LED
RES Rapid,Flags2  ;turn off Rapid LED
 RES HiPwr,Flags4  ;turn off high power mode
;SET NoRamp,Flags4  ;set for Fast rate w/o ramp up to Rapid
LDI OFFSET,OffFast ;set for Fast rate
 JP TestMM1  ;set for Manual charge
NoTest
 JP MAIN  ;skip test and go to MAIN
TEST1  ;Set for manual Slow Charge
 JRR TypeSw,DRC,TEST2 ;if Type switch is pressed,set for Fast Test
 CALL SetSlow  ;set for Slow Rate
 CALL StartSlow  ;set OFFSET for Slow rate
;LDI OFFSET,OffSlow ;set Offset for 2A
 JP TestMM1  ;set for Manual charge
TestBI  ;Set for 60minute Burn-In
 SET BurnIn,Flags3  ;Set for Burn-In mode
 LDI OFFSET,OffFast ;set for Fast rate
 RES HiPwr,Flags4  ;turn off high power
 CALL SetRmpUp  ;prepare to ramp from Fast to Rapid
TEST2  ;set for Manual Rapid Charge
;SET Manual,Flags3  ;set for Manual mode
 SET Rate,Flags  ;set for non-Slow rate
 SET Rapid,Flags2  ;turn on Rapid LED
;RES NoRamp,Flags4  ;set for ramping
 JRS BurnIn,Flags3,TestRap ;don′t set for ramp down if Burn-In
 SET HiPwr,Flags4  ;turn on high power
 LDI RmpCnt,RCinit  ;100 0.75-second intervals yields 75secs
;RES RampUp,Flags3  ;set for ramp down
 LDI OFFSET,OffRap  ;set Offset for Rapid Charge
 CALL SetRamp  ;set ramping parameters
TestRap
 JP TestMM1  ;set for Manual charge
POST
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL MeterOff  ;turn off all meter mode LED′s
 CALL DigitsOff  ;turn off 3-digit LED
 RES Power,Flags2  ;make sure output will be off
 CALL Set12V  ;set for Regular,12V battery
  CALL HoldType  ;show Type and wait a Fifth second
 SET BatTypeA,Flags  ;turn on Deep Cycle & turn off Regular LED
  CALL HoldType  ;show Type and wait a Fifth second
 SET BatTypeB,Flags  ;turn on Gel/AGM LED
 RES BatTypeA,Flags  ;turn off Deep Cycle LED
  CALL HoldType  ;show Type and wait a fifth second
 RES BatTypeB,Flags  ;turn off Gel/AGM LED
 SET Bat6V,Flags2  ;turn ON 6V LED
  CALL HoldType  ;show Type and wait a Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 RES Bat6V,Flags2  ;set for 12V battery(not 6V)
 SET ChMode,Flags2  ;must set flag to show rate LED′s
 RES Crank,Flags  ;turn off Crank LED
 CALL SetSlow  ;set for Slow Rate
 LDI LEDnum,SlowAmps ;set digital LED to show Slow rate
  CALL HoldRate  ;show Rate and wait a Fifth second
 SET Rate,Flags  ;turn on Fast LED
 LDI LEDnum,FastAmps ;set digital LED to show Fast rate
  CALL HoldRate  ;show Rate and wait a Fifth second
 SET Rapid,Flags2  ;turn on Rapid LED
 LDI LEDnum,RapAmps  ;set digital LED to show Rapid rate
  CALL HoldRate  ;show Rate and wait a Fifth second
 RES ChMode,Flags2  ;clear flag to disable output
 LDI LEDnum,CrnkAmps ;set digital LED to show Crank rate
 CALL ShowNum  ;get data to show the LED number
  CALL ShowCrank  ;turn on Crank(Boost)LED
  CALL FifthSecond  ;wait one Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowData  ;update display
 SET MtrUnits,Flags  ;set for % LEDs ON,volts LED off
 RES MtrScale,Flags  ;set for Alternator % LED off
 LDI DigiDat1,DigiRev1 ;set digital LED to show Code Revision
 LDI DigiDat2,DigiRev2 ;set digital LED to show Code Revision
 CALL ShowData  ;update display
 CALL HoldMtrMd  ;show meter mode and wait one fifth second
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
 CALL HoldMtrMd  ;show meter mode and wait one fifth second
 SET MtrUnits,Flags  ;set for % LEDs ON,volts LED off
 SET MtrScale,Flags  ;set for Alternator % LED ON
 CALL HoldMtrMd  ;show meter mode and wait one fifth second
 CALL MeterOff  ;turn off all meter mode LED′s
 CALL AlertON  ;turn on Alert(Red)LED
 CALL FifthSecond  ;wait one Fifth second
 CALL ShowChgng  ;light Charging LED
 CALL FifthSecond  ;wait one Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL FifthSecond  ;wait one Fifth second
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 LDI LEDnum,5  ;initialize to 5 to show 4 1st
POST2
 DEC LEDnum  ;the next number will be 1 less
 CALL NumData  ;get data for,and show LED number
 CALL FifthSecond  ;wait one fifth second
 LD A,LEDnum  ;check for last number
 JRNZ POST2  ;loop back and repeat if not there
POST3
 ADDI A,20  ;adding 20 changes 2nd digit
 LD LEDnum,A  ;prepare to show new number
 CALL NumData  ;get data for,and show LED number
 CALL FifthSecond  ;wait one fifth second
 LD A,LEDnum  ;check latest number
 CPI A,100  ;compare to last number
 JRNZ POST3  ;loop back and repeat if not there
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL InitState  ;reset to Slow,TypeA charge mode
 RES ChMode,Flags2  ;set for Tester mode
 JP TEST  ;repeat POST if necessary
TestMM1  ;Set for manual charge
 SET Manual,Flags3  ;set for Manual mode
 SET ChMode,Flags2  ;set for Charger Mode(output enabled)
 RES Disable,DRBbuf  ;ehable output
 LDI CurentSS,15  ;State 15 is Manual charge
 SET Started,Flags  ;set Flags for charge started
 SET Power,Flags2  ;tell PwrCon charger is on
 CALL IniTime1  ;initialize Timer1
 LDI Hrs1,1  ;set Timer1 for 1 hour
 JRR BurnIn,Flags3,MAIN ;skip next 2 lines if not Burn-in
TestMM2
 CALL IniTime2  ;reset Timer2
 LDI Mins2,1  ;set timer for counter interval(1 minute)
 LDI CCDcnt,60  ;set Burn-in minute counter to 60
;***************************************************************************
;*                MAIN                   *
;***************************************************************************
;***************************************************************************
;*Because the A/D voltage is being averaged,it would take considerable  *
;*time to notice that a battery has become disconnected.To overcome this *
;*DELAY the program will monitor the instantaneous voltage each time thru *
;*the loop to detect this condition.This check will be made only if the  *
;*unit is in a charging mode.                            *
;***************************************************************************
MAIN
 CALL RstWDR  ;reset watch dog timer
 LD A,CurentSS  ;get current state
 CPI A,ABORT  ;check for abort
 JRNZ MainMore  ;continue Main if not Abort
 JP MAIN3  ;don′t continue Main if Abort
MainMore
 JRR Manual,Flags3,MainAuto ;continue Main if not Manual Mode
 JP SS15   ;otherwise,goto Manual charge
MainAuto
 JRS CrankWait,Flags,MAIN1 ;don′t check switches during Crank wait
 CALL CheckSw  ;check if switch is being pressed
MAIN4
 JRS Crank,Flags,MAIN0 ;skip ahead if during Crank
 CALL GetPercent  ;update the percentage reading
 CALL UpdateBP  ;update % to display
 CALL GetMeter  ;update display
 JRR Idle,Flags3,MAIN0  ;skip ahead if not idle
 JRR Batt,Flags2,MAIN0 ;don′t check idle time limit if no battery
 JRS IdleSet,Flags4,MAIN5 ;don′t set idle timer if already set
 CALL IniTime1  ;...otherwise initialize timer 1
 LDI Mins1,0Ah  ;set timer 1 for 10minutes
 SET IdleSet,Flags4  ;Idle timer started,set flag
MAIN5
 JRR MIN,TicFlag1,MAIN0  ;...otherwise,check idle time limit
 RES Disable,DRBbuf  ;...enable output after idle time limit
 JP MAIN2  ;...and re-initialize if reached
MAIN0  ;not Crank,check for 0 or 1
 JRS Power,Flags2,MAIN1  ;charger is ON,goto 0V check
 JRS LEDchgng,DRAbuf,MAIN3 ;charger not almost on,skip 0V check
MAIN1  ;Check for disconnected battery
 CALL CheckBatt  ;check for disconnected battery
 JRS Batt,Flags2,MAIN3  ;skip ahead if connected
MAIN2  ;0V detected,prepare to start over from state 0
 LDI DspPcnt,0  ;initialize display Percent to 0
 CALL InitState  ;initialize to Slow Regular Charge mode
MAIN3
;***************************************************************************
;*            SEQUENCE STATE JUMP TABLE             *
;*Determine what routine to execute on this pass through the the loop.Only*
;*one routine is executed each time through the loop.              *
;***************************************************************************
NSS0
 LD A,CurentSS
 JRNZ NSS1
 JP SS0 ;* SS0 - BATTERY DETECT *
NSS1
 CPI A,001h
 JRNZ NSS2
 JP SS1;* SS1 - BATTERY DETECT DELAY *
NSS2
 CPI A,002h
 JRNZ NSS3
 JP SS2 ;* SS2 - AUTOMATIC CHARGE START *
NSS3
 CPI A,003h
 JRNZ NSS4
 JP SS3 ;* SS3 - BELOW 9 Volts *
NSS4
 CPI A,004h
 JRNZ NSS5
 JP SS4 ;* SS4 - BELOW 12 Volts *
NSS5
 CPI A,005h
 JRNZ NSS8
 JP SS5 ;* SS5 - NORMAL CHARGE *
NSS6
;CPI A,006h
;JRNZ NSS7
;JP SS6 ;* SS6-dv/dt MONITOR * NOT USED
NSS7
;CPI A,007h
;JRNZ NSS8
;JP SS7 ;* SS7 - CHARGE COMPLETE * NOT USED
NSS8
 CPI A,008h
 JRNZ NSS9
 JP SS8 ;* SS8 - ABORT CHARGE *
NSS9
 CPI A,009h
 JRNZ NSS11
 JP SS9 ;* SS9 - DESULFATION *
NSS10
;CPI A,00Ah
;JRNZ NSS11
;JP SS10 ;* SS10 - RESTORE CHARGE *
NSS11
 CPI A,00Bh
 JRNZ NSS12
 JP SS11 ;* SS11 - dV/dt MONITOR *
NSS12
 CPI A,00Ch
 JRNZ NSS13
 JP SS12 ;* SS12 - dI/dt MONITOR *
NSS13
 CPI A,00Dh
 JRNZ NSS14
 JP SS13 ;* SS13 - ENDCHARGE *
NSS14
 CPI A,00Eh
 JRNZ NSS15
 JP SS14 ;* SS14 - MAINTAIN *
NSS15
 CPI A,00Fh
 JRNZNSS16
 JP SS15 ;* SS15 - Manual *
NSS16
 CPI A,010h
 JRNZ NSS17
 JP SS16 ;* SS16 - CRANK *
NSS17
 CPI A,011h
 JRNZ NSS18
 JP SS17 ;* SS17 - CRANK *
NSS18
 CPI A,012h
 JRNZ NSS19
 JP SS18 ;* SS18 - CRANK *
NSS19
 CPI A,013h
 JRNZ NSS20
 JP SS19 ;* SS19 - CRANK *
NSS20
 CPI A,014h
 JRNZ NSS21
 JP SS20 ;* SS20 - CRANK *
NSS21
 LDI WDR,001h       ;invalid sequence state,reset
;***************************************************************************
;*                END OF MAIN   *
;*Wait for NMI,which indicates end of FET on period,before measuring *
;*battery voltage.                           *
;***************************************************************************
ExitMain
XMain
 WAIT   ;wait for interupt
 JRS NMInt,Flags2,XMain ;timer interupt???
;***************************************************************************
;*             READ BATTERY VOLTAGE               *
;*  This routine is executed at or near zero cross.The current voltage *
;*is stored in CurVolt and the reading is added to BADhi(two locations).*
;*BADhi will contain a running average of the last 256 readings.     *
;***************************************************************************
BADREAD
 .IFC EQ ShoADC ;assemble next 2 lines only if debugging
 SET 2,DRBbuf  ;set PB2 when A/D sampling starts
 CALL UpdatePB  ;update port B from buffer
 .ENDC
 LD A,BADlo  ;get average reading
 SUB A,BADhi  ;subtract one reading from the running total
 JRNC BADREAD1  ;no carry,go on
 DEC BADhi  ;adjust high order bits
BADREAD1
 LD BADlo,A  ;store new value
 LDI ADCR,0B0h  ;start A/D conversion
 LDI ADCR,0B0h  ;do again to insure a valid start
 WAIT  ;let the interupt notify us when data is ready
 LD CurVolt,A  ;save current reading
 ADD A,BADlo  ;add into running average
 JRNC BADREAD2  ;no carry,go on
 INC BADhi  ;increment high bits
BADREAD2
 LD BADlo,A  ;store new low bits
 .IFC EQ ShoADC ;assemble next 2 lines only if debugging
 RES 2,DRBbuf  ;set PB2 when A/D sampling starts
 CALL UpdatePB  ;update port B from buffer
  .ENDC
;LDI ORB,01Fh
;LDI ORB,09Fh
;***************************************************************************
;*            di/dt AVERAGE CALCULATION            *
;* For use by the di/dt,about four times every second the average of the *
;* previous 32 curvolt readings is stored in FreshBV for comparison to a *
;* reading taken once every second.       *
;***************************************************************************
DIDTAVG
 LD A,Temp2  ;if Temp2=0 then first reading
 JRNZ DIDTAVG1  ;skip init if not 1st reading
 LDI Temp2,020h ;initialize Temp2 to 32
DIDTAVG1
 LD A,FBVTotLo ;
 ADD A,CurVolt ;add current voltage to total
 JRNC DIDTAVG2  ;don′t inc high byts if no carry
 INC FBVTotHi  ;inc high byte
DIDTAVG2
 LD FBVTotLo,A ;update total
 DEC Temp2  ;update Temp2
 JRZ DIDTAVG3  ;compute avg
 JP DIDTAVGX  ;exit to Main
DIDTAVG3
 LDI Temp2,003h ;prepare to shift 3times
DIDTAVG6
 LD A,FBVTotHi ;load high byte of total into accumulator
 SLA A  ;shift accumulator left
 LD FBVTotHi,A ;update high byte of total
 LD A,FBVTotLo ;load low byte of total into accumulator
 SLA A  ;shift accumulator
 LD FBVTotLo,A ;update low byte of total
 JRNC DIDTAVG4 ;msb was zero,skip next line
 INC FBVTotHi ;
DIDTAVG4
 DEC Temp2 ;dec loop counter
 JRZ DIDTAVG5  ;if zero,finish average
 JP DIDTAVG6  ;not zero,shift again
DIDTAVG5
 LD A,FBVTotHi ;store average in FreshBV
 LD FreshBV,A
 CLR FBVTotHi
 CLR FBVTotLo
 JRS 7,FreshBV,DA7 ;skip ahead if>8.5V
 RES Hi6V,Flags3 ;clear Hi6V flag
 JP DIDTAVGX  ;and skip to end of routine
DA7
 SET Hi6V,Flags3 ;set Hi6V flag
DIDTAVGX
 JP MAIN
;***************************************************************************
;* This is where the sequence states are defined.The number of a given  *
;* sequence state has no relevance to the order in which it is actually  *
;* executed.Any given state can give control to any other state.    *
;***************************************************************************
;***************************************************************************
;*              BATTERY DETECT                *
;* This is the charger idle state.The program remains here until a battery *
;* is detected.Dectection is determined by finding a positive voltage   *
;* greater than one volt.                               *
;***************************************************************************
SS0
;RES Crank,Flags   ;clear Crank bit of Flags
 CALL ShutOff  ;low & high power,fan,& crank off;min duty
 CALL ShowRate  ;turn on charge rate LED(Slow or Fast)
 CALL ShowType  ;turn on battery type LED(Reg,D/C or Gel)
 CALL ChrgRly  ;change E/S relay if necessary
 JRS ChMode,Flags2,Ready ;continue routine if in Charger Mode
 CALL CheckBatt  ;...otherwise,check if tester should show 0′s
 JP SS0EXIT  ;...and exit
Ready
 JRR Started,Flags,SS00 ;skip if output hasn′t been on
 RES Started,Flags ;set Flags for charge not started
SS00
 LD A,FreshBV  ;check latest average voltage
 JRNZ RvrsBatt  ;Is it 0(exactly)?
 CALL ShowRed  ;turn on Red LED until battery is detected
 JP SS0EXIT  ;...Yes:must be rev.batt,so stop
RvrsBatt
 CPI A,Volts0+1  ;No:otherwise,check if>~0.7V
 JRC Pulse  ;no:try pulsing the output
 JP SS0_1  ;yes:setup for no spark delay
Pulse  ;turn on charger for 1 cycle each second
 LD A,MSecs1  ;pulse once per second
 CPI A,MSINIT ;time to pulse?
 JRZ PulseON  ;yes,goto to pulse code
 RES Power,Flags2  ;otherwse,tell timer to leave charger off
 JP SS0EXIT  ;and keep waiting(until next second starts)
PulseON   ;pulse charger on once per second
 SET Power,Flags2  ;tell PwrCon charger is on
;CALL ShowGreen  ;turn on Green LED ***test***
 JP SS0EXIT  ;no battery,just exit
SS0_1
 CALL IniTime1  ;set up timer
 LDI Secs1,002h  ;adjust for 2seconds
 LDI Tries,005h  ;5 Tries for debounce
 SET 0,CurentSS  ;go on to BATTERY DETECT DELAY
SS0EXIT
 JP ExitMain
;***************************************************************************
;*   BATTERY DETECT DELAY   *
;* This state checks that a voltage is present for two seconds.If the *
;* voltage drops below 1 Vdc,the timer is restarted and the ″try″counter *
;* is decremented.If after 5 Tries the voltage has not been above 1 Vdc *
;* for 2seconds,go back to battery detect.This delay has the effect of *
;* debouncing the leads being connected to the battery.   *
;***************************************************************************
SS1
 CALL Check Batt  ;check for connected battery
 JRR Batt,Flags2,SS1_2 ;subtract a try if not connected
 CALL ShowChgng  ;turn Charging LED on
 JRR 2,TicFlag1,SS1EXIT ;go on if time is up,otherwise exit
 LDI OldVolt,000h  ;clear OldVolt before entering SS2
 LDI TEMP1,000h  ;clear Temp1 before entering SS2
 INC CurentSS  ;go on to start charge
 JP SS1_3  ;set timer for 2seconds
SS1_2  ;NOTE:Tries set to 5 in SS0
 DEC Tries  ;subtract a try
 JRNZ SS1_3  ;try again if not too many Tries
 DEC CurentSS  ;...otherwise,go back to idle(state 0)
 JP SS1EXIT  ;...and exit routine
SS1_3
 CALL IniTime1  ;reset timer and try again
 LDI Secs1,002h  ;adjust for 2seconds
SS1EXIT
 JP ExitMain
;***************************************************************************
;*    AUTOMATIC CHARGE START   *
;* This state gets the battery voltage and decides how to continue the *
;* the charge.The maximum allowed charge time is also started. *
;***************************************************************************
SS2
;NOTES:OldVolt SET TO 0 IN SS1
;TEMP1 SET TO 0 AT RESET
FASTAVG
 DEC TEMP1  ;decrease Temp1 one count(starts at 0)
  ;have we counted down to 0?
 JRZ FASTDONE ;yes,jump to FASTDONE
 LD A,TEMP  ;no,load previous TEMP value
 ADD A,CurVolt  ;add CURVOLT,Did we overflow the counter?
 JRNC OVER  ;no,jump to OVER
 INC OldVolt  ;yes,bump up the running average
OVER
 LD TEMP,A  ;store the latest value in TEMP
 JP SS2EXIT  ;exit and go update CurVolt
FASTDONE
 LD A,TEMP  ;load previous TEMP value
 ADD A,CurVolt  ;Did we overflow the counter one last time?
 JRNC OVER2  ;no,jump to OVER2
 INC OldVolt  ;yes,bump up the running average one last time
OVER2
 CALL CheckBatt  ;Check to see if battery was removed during FastAvg
 JRS Batt,Flags2,SS2_0c ;Still connected-continue
 LDI CurentSS,0  ;not connected - go back to state 0
 JP SS2EXIT  ;...and exit State 2
SS2_0c
 LD A,OldVolt  ;get OldVolt(initial battery voltage)
 LD BADhi,A  ;initialize BADhi to OldVolt
;LD A,Percent  ;get updated %
 LD A,DspPcnt  ;compare to last % displayed
 JRNZ SS2_GP  ;if % previously shown,skip ahead
 CALL GetPercent  ;update Percent for initial voltage
 LD A,Percent  ;get latest %
 LD DspPcnt,A  ;store latest % in Display Percent
 RES Wait0P,Flags2  ;set flag to indicate not waiting
 JP SS2_BP  ;skip ahead
SS2_GP
 CPI A,100  ;check for 100%
 JRNZ SS2_BP  ;continue State 2 if not 100%
 CALL SetMinOff  ;limit output to max 2A current
;LDI LowOff,MinOff2  ;limit output to max 2A current
;JRR Bat6V,Flags2,SS2_6S ;skip next line if not 6V mode
;LDI LowOff,Min6Off2 ;limit output to max 6V 2a current
;SS2_6S
 JP SS5_Maint  ;...otherwise,go to Maintain
SS2_BP
 CALL ShowChgng  ;turn Charging LED on
 CALL IniTime1  ;initialize timer 1
 LDI Mins1,5  ;set timer 1 for 5 minutes
;LDI Secs1,005h  ;set timer 1 for 5 seconds
 LDI CCDcnt,MaxHrs  ;set interval counter to MaxHrs
 CLR LastBatt  ;clear LastBatt(ensure pass 1st test)
;SET SOC,Flags4  ;set Start Of Charge flag
 CALL IniTime2  ;initialize timer 2
 LDI Secs2,001h  ;set timer for 1 second
 LDI MSecs2,MS500  ;set timer for 500 milliseconds(0.5secs)
 LDI Mins2,006h  ;set timer for 5 minutes and 2 seconds
 LDI Hrs2,005h  ;set timer for 4 hours,5 minutes & 2 seconds
 JRS Rate,Flags,SS2Fast  ;skip ahead if not set for Slow
  ;...otherwise,set for Slow charge
 CALL StartSlow  ;set OFFSET for Slow rate
;LDI OFFSET,OffSlow  ;set Offset for 2A
;JRR Bat6V,Flags2,SS2Slo ;skip ifnot set for 6V mode
;LDI OFFSET,Off6Slo ;...otherwise,adjust OFFSET
;SS2Slo
 JP SS2_0a  ;skip ahead and read voltage
SS2Fast  ;set for Fast charge
 LDI OFFSET,OffFast  ;set Offset for Fast rate
 JRR Bat6V,Flags2,SS2Fst ;skip if not set for 6V mode
 LDI OFFSET,Off6Fst ;...otherwise,adjust OFFSET
SS2Fst
 JRR Rapid,Flags2,SS2Rap ;skip ahead if rate is not Rapid
 CALL SetRmpUp  ;prepare to ramp from Fast to Rapid
SS2Rap  ;set for Rapid charge rate
 JP SS2_0a  ;...otherwise skip ahead and read voltage
SS2_0a
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CPI A,Volts09  ;very low battery?
 JRNC SS2_2  ;no,try next limit
SS2_1  ;Battery<9V
 LDI A,003h  ;yes,service it,below 9 VOLT SS
 JP SS2_5
SS2_2;Battery>9V
 CPI A,Volts12  ;low battery state?
 JRNC SS2_4  ;no,goto SS5
SS2_3  ;9V<Battery<12V
 LDI A,004h   ;yes,service it,below 12 VOLT SS
 JP SS2_5
SS2_4  ;Battery>12V
;JRS Alert,Flags2,SS2EXIT;don′t start charge if Alert set by Double6V
 LDI A,005h  ;normal charge SS
SS2_5
 LD CurentSS,A  ;prepare to go to the correct state(3,4 or 5)
 SET Started,Flags  ;set Flags for charge started
 CALL TurnON  ;turn output,Fan,and Charging LED on
 SET Settle,Flags3  ;initial charge voltage settle mode
SS2EXIT
 JP ExitMain
;***************************************************************************
;*              BELOW 9 Volts   *
;*  Battery is extremely discharged and may be bad.Charge for a maximum *
;* of five minutes.If voltage does not come above 9 Volts in this time *
;* period,abort charge.Otherwise,go to below 12 Volts.  *
;***************************************************************************
SS3
 CALL ChkRapid   ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS3EXIT;exit if voltage settle time not expired
 RES Settle,Flags3  ;clear settle flag
 CALL IReg  ;regulate current till we get to dV/dt
 JRR MIN,TicFlag2,SS3_1 ;check if time has expired
 CALL SetAbort  ;yes,time to abort
 JP SS3EXIT
SS3_1
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts09  ;is battery up to 9V?
 JRC SS3EXIT           ;continue state 3 if<9V
 INC CurentSS  ;...otherwise,go to state 4
SS3EXIT
 JP ExitMain
;***************************************************************************
;*              BELOW 12 Volts               *
;*  Battery is very low.Allow a maximum of 2 hours for the voltage to  *
;* rise above 12 volts under charge.If voltage does not come up,go to  *
;* abort charge.Otherwise go to normal charge.                    *
;***************************************************************************
SS4
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS4EXIT;exit if voltage settle time not expired
 RES Settle,Flags3  ;...otherwise,clear settle flag
 CALL IReg  ;regulate current till we get to dV/dt
 JRR HR,TicFlag2,SS4_1 ;check if time(4 hours)has expired
 CALL SetAbort  ;yes,time to abort
 JP SS4EXIT  ;exit routine
SS4_1
 CALL BattProg  ;check battery voltage for charge progress
 CPI A,Volts12  ;is battery up to 12V?
 JRC SS4EXIT     ;...if not,just exit
 INC CurentSS  ;...otherwise,go to state 5
SS4EXIT
 JP ExitMain
;***************************************************************************
;*   NORMAL CHARGE    *
;* Program stays here until the voltage reaches 14.2 volts or the maximum *
;* charge time is exceded.If the voltage limit is reached the program *
;* will transfer to:    *
;* A.SSB(dV/dt)if the the battery has been charging more than 5  *
;*  minutes or         *
;* B.SS9(Desulfation)if the OCV was less than 12.2 volts or  *
;* C.SS14(Maintain)if the OCV was more than 12.2 volts  *
;*       *
;* If the maximum change time is exceded the program will abog  *
;*          *
;***************************************************************************
SS5
 CALL ShowChgng  ;turn Charging LED on
 CALL ChkRapid  ;update Ramp timer,if necessary
 JRR SEC,TicFlag2,SS5x ;exit if voltage settle time not expired
 RES Settle,Flags3  ;...otherwise,clear settle flag
 CALL BattProg  ;check battery voltage for charge progress
 JRR HR,TicFlag1,SS5_0 ;skip next line if max time not expired
;  NOTE:CurentSS set to ABORT by BattProg.ChkProg
SS5x
 JP SS5EXIT  ;exit(and abort)if max time expired
SS5_0
 JRS Rate,Flags,SS5_0b ;change delta if slow rate
 CPI A,Volts142+1  ;check if over 14.2 volts yet
 JP SS5_1
SS5_0b
 CPI A,Volts142+3  ;check if over 14.2 volts yet
SS5_1
 JRNC SS5_2  ;yes,check if>5minutes
 CALL IReg  ;no,regulate current till we get to dV/dt
 JP SS5EXIT  ;...and just return
SS5_2
 LD A,CCDcnt  ;get CCDcnt(set by BattPRog w/minutes)
 LD Hrs1,A  ;set Timer1 hours to CCDcnt
 RES HiPwr,Flags4  ;set for low power mode
 RES RmpInt,Flags3  ;clear flag before moving on
;RES Settle,Flags3  ;clear flag before moving on
 JRS MIN,TicFlag2,SS5_3 ;if>5min,go to dV/dt
 LD A,OldVolt  ;otherwise,check initial voltage
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,Volts122  ;initial voltage<12.2V?
 JRC SS5_5  ;Yes:then desulfate
 JP SS5_Maint  ;No:goto Maintain
SS5_5
 LDI CurentSS,009h  ;battery is sulfated
 LDI MaintVolt,Volts16 ;try to hold battery at 16V
 LDI Vref,Volts15  ;and see if it drops to 15V
 CALL IniTime2  ;
 LDI Hrs2,002h  ;in less than 2hours
 JP SS5EXIT  ;
SS5_3
 CALL SetMinOff  ;min 2A offset value(max current)
;LDI LowOff,MinOff2  ;min 2A offset value(max current)
;JRR Bat6V,Flags2,SS5_6V ;skip next line if not 6V mode
;LDI LowOff,Min6Off2 ;min 6V 2A offset value(max current)
;SS5_6V
 JRR Rate,Flags,SS5_6 ;check for 15A charge rate
 LDI LowOff,MinOff15 ;min 15A offset value(max current)
 JRR Bat6V,Flags2,SS5_6 ;skip next line if not 6V mode
 LDI LowOff,Min6Off15 ;min 6V 15A offset value(max current)
SS5_6
 LD A,LowOff  ;Load LowOff into A for next step
 LD OldOff,A  ;initialize OldOff for di/dt to LowOff
 LDI CurentSS,00Bh  ;goto wait for dy/dt trip voltage
 LDI Percent,77  ;set Percent to 77
 CALL IniTime2
 LDI Mins2,13  ;set to 13minutes for dV/dt
 LD A,BADhi  ;get latest battery voltage
 SUBI A,4  ;prevent match @ 1st dV/dt check
 LD MaintVolt,A  ;store as maintain voltage for di/dt
 LDI Tries,004h  ;initialize dV/dt for 4 Tries(3 intervals)
 JP SS5EXIT  ;
SS5_Maint  ;goto MAINTAIN,battery is already charged???
 CALL Set100p  ;set Percent to 100
 LDI MaintVolt,Volts132 ;set maintain voltage to 13.2V
;CALL FanOff  ;turn cooling fan off
 JRR BatTypeB,Flags,SS5_7;skip ahead if not Gel/AGM
 LDI MaintVolt,Volts135 ;set maintain voltage to 13.5V for Gel &AGM
SS5_7
 LDI CurentSS,00Eh  ;Maintain is state 14(0E hex)
 CALL SetON  ;turn cooling fan & output on
 CALL FanOff  ;turn cooling fan off
 CALL SetHiOff  ;MAX offset value ->min duty cycle
SS5EXIT
 JP ExitMain
SS6
SS7
;***************************************************************************
;*         SS8-ABORT CHARGE   *
;*        *
;* Turn off all LED′s.Blink TROUBLE LED at half second interval.If*
;* battery becomes disconnected,goto BATTERY DETECT.  *
;*          *
;***************************************************************************
SS8
 SET Alert,Flags2  ;set Alert flag
;CALL ShutOff  ;low & high power,fan,& crank off;min duty
 CALL SetOff  ;turn off power and set for min duty
 CALL ChrgRly  ;change E/S relay if necessary
 CALL BlinkAlert  ;blink red LED
 JRS BurnIn,Flags3,SS8X ;don′t check for battery if Burn-In
 CALL Check0V  ;check for disconnected battery
 JRS Batt,Flags2,SS8X ;if connected,just exit
 RES Alert,Flags2  ;...otherwise,end abort routine
SS8rst
 JP MAIN2  ;re-initialize
SS8X
 JP ExitMain
;***************************************************************************
;*            SS9-DESULFATION   *
;* Desulfation Mode is entered if the initial battery voltage is less *
;* than 12.2 volts and the voltage reaches 14.0 volts within five *
;* minutes.         *
;*         *
;* The charger tries to hold the voltage at 16.0 volts.As the battery *
;* starts to conduct,the voltage will fall.If the voltage reaches 14.0 *
;* in a reasonable time limit(10hours),we will transition to the *
;* normal charging sequence(SS5).If the voltage doesn′t fall to 14.0 *
;* volts we will transition to the ABORT sequence state(SS8). *
;***************************************************************************
SS9
 LDI Percent,15  ;set to 15%
 CALL BlnkChrg  ;blink Charging LED
 CALL CheckBatt  ;check for connected battery
 JRR Batt,Flags2,SS8rst ;re-initialize if not connected
 CALL VoltReg
 JRR SEC,TicFlag2,SS9X ;wait 1minute
 JRR HR,TicFlag2,SS9_1 ;maximum time out?(1 or 2hours)
 DEC CurentSS  ;ABORT state
SS9exit
 JP SS9X  ;done
SS9_1
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CPA,Vref  ;are we there?
 JRNC SS9exit  ;if not,then exit
 DEC Vref  ;1 count is 0.0667 volts
 DEC Vref  ;reduce Vrefby 0.133 volts
 LD A,Vref  ;see if batt is desulfated yet
 CPI A,Volts14  ;is Vref<14.0 Volts?
 JRNC SS9_3  ;no:try another hour
 LDI CurentSS,005h  ;yes:prepare to go to normal charge
 LD A,Vmax  ;set MaintVolt to Vmax
 LD MaintVolt,A  ;maintain voltage for state 5
 CALL IniTime2  ;initialize timer 2
 LDI Secs2,002h  ;set timer for 2 seconds(voltage settle time)
 JP SS9X  ;
SS9_3
 CALL IniTime2  ;reset timer
 LDI Hrs2,001h  ;set max time for 1hour
SS9X
 JP ExitMain
SS10
;***************************************************************************
;*   dV/dt MONITOR    *
;*  This state is looking for one of three conditions:  *
;* 1.Maximum time is exceded - set for check battery and turn off charger.*
;* 2.No change in dV/dt for 45minutes -battery is about 80% charged.*
;* 3.MAX voltage is reached -GOTO dI/dt.    *
;*       *
;***************************************************************************
SS11
 JRR HR,TicFlag1,SS11_1 ;If not max time out,goto SS11_1
 CALL SetAbort  ;otherwise,go to abort
 JP SS11X
SS11_1
 CALL ShowChgng  ;light Charging LED
 CALL GetBatt  ;get latest voltage & double if 6V mode
 CP A,Vmax  ;is batt voltage<MAX voltage?
 JRC SS11_2  ;yes:continue loop
 SET HiEnd,Flags3  ;no:set to boost during D/C EndCharge
 JP SS11_6  ;...and prepare to GOTO dI/dt
SS11_2
 JRR MIN,TicFlag2,SS11X  ;exit if not time for dv/dt test
 LD A,Percent  ;get Percent
 CPI A,84  ;is Percent<84?
 JRNC SS11_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_3
 LD A,BADhi  ;get battery voltage
 DEC A  ;limit for 6V batteries is 1 count
 JRS Bat6V,Flags2,SS11_3a;leave limit at 1 for 6V batteries
 DEC A  ;limit for 12V batteries is 2 counts
SS11_3a
 CP A,MaintVolt  ;test for upper limit change
 JRC SS114  ;less than 1 count up,test down change
 JP SS11_7  ;otherwise,skip ahead & update MaintVolt
SS11_4
 DEC Tries  ;decrement counter
 JRZ SS11_6  ;all done,GOTO dI/dt
 LD A,Percent  ;get Percent
 CPI A,87  ;is Percent<88?
 JRNC SS11_5  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
SS11_5
 JP SS11_8  ;no,reload timer
SS11_6
 INC CurentSS  ;GOTO dI/dt next
 LDI Percent,88  ;set Percent to 88 - NOTE must always be even
 JRS HiEnd,Flags3,MntMx ;skip ahead if Vmax reached
 CALL GetBatt  ;get latest voltage & double if 6V mode
 LD MaintVolt,A  ;save BADhi as maintain voltage
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
MntMx
 LD A,Vmax  ;otherwise,set MaintVolt to Vmax
 LD MaintVolt,A  ;MaintVolt used for di/dt
 JP SS11_9  ;initialize Tries and Timer2 for di/dt
SS11_7  ;update MaintVolt
 LD A,BADhi  ;get current battery voltage
 LD MaintVolt,A  ;update MaintVolt for dV/dt & di/dt
SS11_9
 LDI Tries,004h  ;reset counter(4 matches=3 intervals)
SS11_8
 CALL IniTime2  ;initialize timer
 LDI Mins2,009h  ;...for 9minutes
SS11X
 JP ExitMain
;***************************************************************************
;*    di/dt MONITOR    *
;* In di/dt the OFFSET value is adjusted to hold the voltage at the dV/dt *
;* value.The OFFSET value will increase and stabilize.  *
;*  This state is looking for one of two conditions:  *
;* 1.Maximum time is exceded - set for check battery and turn off charger.*
;* 2.No change in OFFSET value for 39minutes - current stabilized at a *
;* low value.Battery is about 97% charged.Goto SS13(EndCharge)for *
;* 1hour.        *
;***************************************************************************
SS12
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS12_14  ;...if so,turn on green LED
 CALL ShowYellow  ;...otherwise,turn on yellow LED
 JP SS12_15  ;...and skip ahead(leave green off)
SS12_14
 CALL ShowDone  ;turn on charge complete LED
SS12_15
 JRR HR,TicFlag1,SS12_1 ;maximum time out?
 JRS Alert,Flags2,SS12_0 ;If 2nd max time out,goto SS12_0
 SET Alert,Flags2  ;If 1st max time,set Alert flag
 CALL IniTime1  ;and reset timer
 LDI Hrs1,004h  ;to alow 4 more hours
SS12_10
 LD A,MaintVolt  ;and get Maintain voltage
 SUBI A,007h  ; then subtract~0.5V
 LD MaintVolt,A  ;and update Maintain voltage
 JP SS12EXIT  ;then restart di/dt
SS12_0
 CALL SetAbort  ;go to abort
 RES Alert,Flags2  ;reset Alert flag for Abort timer
 JP SS12EXIT
SS12_1
 JRR MIN,TicFlag2,SS12EXIT ;time for dI/dt test?
 LD A,Percent  ;get Percent
 CPIA,100  ;is Percent<100?
 JRNC SS12_2  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 LD A,Percent  ;get percent
 CPI A,100  ;Is percent=100?
 JRZ SS12_2  ;YES,don′t increase anymore
 INC Percent  ;No,increase by 2
SS12_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC SS12_13;if so,finish di/dt
 DEC A  ;ensure carry if equal
 CPA,OldOff  ;test for lower limit change
 JRC SS12_4  ;offset within 1,finish di/dt
 JP SS12_7  ;offset too high,try again
SS12_13
 JP SS12_6
SS12_4
 DEC Tries  ;decrement counter
 JRZ SS12_13  ;if 0,then prepare for EndCharge(SS13)
;JRNZ SS12_5  ;Are we done?
;JP SS12_6  ;yes,all done,cleanup and exit
;SS12_5  ;no,continue
 LD A,Percent  ;get Percent
 CPI A,99  ;is Percent<100
 JRNC SS12_3  ;...if not,skip ahead
 INC Percent  ;...otherwise,increase Percent
 JP SS12_8  ;reload timer & check again later
SS12_3
 LD A,Tries  ;get the current tries
 CPI A,03  ;Is tries less than 3?
 JRNC SS12_11  ;No,just exit
 CALL Set100p  ;Yes,show 100% and done
SS12_11
 JP SS12_8  ;reload timer & check again later
SS12_6
 INC CurentSS  ;GOTO EndCharge(SS13)
 CALL IniTime2  ;initialize Timer2
 LDI Hrs2,001h  ;charge for 1 more hour(EndCharge)
 LDI Mins2,00Fh  ;charge for only 15minutes(EndCharge)
 JRR BatTypeA,Flags,SS12_9 ;skip ifnot Deep Cycle(Voyager)
 JRR HiEnd,Flags3,SS12_9 ;skip if not using higher EndCharge voltage
 INC rs2  ;otherwise,change Hrs2 from 1 to 2
 LD A,MaintVolt  ;also,store MaintVolt in A
 ADDI A,04h  ;increase A by 4counts ~0.267V
 LD MaintVolt,A  ;store updated value in MaintVolt
SS12_9
 JP SS12EXIT
SS12_7
 LD A,OFFSET  ;set new base offset
 LD OldOff,A  ;save in OldOff
 LDI Tries,004h  ;reset counter(4matches=3intervals)
SS12_8
 CALL IniTime2  ;initialize Timer 2
 LDI Mins2,009h  ;set Timer 2 for 9minutes
 LD A,OFFSET  ;Get current offset
 CP A,LowOff  ;Is the offset=MinOff?
 JRNZ SS12EXIT  ;NO,just exit
 RES HiEnd,Flags3  ;YES,don′t boost voltage for EndCharge
 JP SS12_10  ;Current not falling,reduce voltage by 1/2V
SS12EXIT
 JP ExitMain
;***************************************************************************
;*      ENDCHARGE    *
;* Charge for desired hours after dI/dt at dV/dt voltage.  *
;***************************************************************************
SS13
 CALL Set100p  ;set Percent to 100
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS13_2  ;...if so,turn on green LED
 CALL ShowDone  ;turn on charge complete LED
SS13_2
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRZ SS13_1  ;exit if max OFFSET reached
 JRR HR,TicFlag2,SS13EXIT ;exit if 1hour time not up
SS13_1
 JP SS5_Maint  ;...otherwise,GOTO MAINTAIN
SS13EXIT
 JP ExitMain
;***************************************************************************
;*   MAINTAIN    *
;* Battery has reached full charge.Stay here and maintain battery *
;* at 13.2 volts until battery is disconnected.  *
;*          *
;***************************************************************************
SS14
 CALL Set100p  ;setPercent to 100
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;has % displayed reached 100?
 JRZ SS14_1  ;...if so,turn on green LED
 CALL ShowYellow  ;...otherwise,turn on yellow LED
 JP SS14_2  ;...and skip ahead(leave green off)
SS14_1
 CALL ShowDone  ;turn on charge complete LED
SS14_2
 CALL ChkHiOff  ;check for max OFFSET(PWM full off)
 JRNC SS14_3  ;...if so,shut off fan
 JRS Bat6V,Flags2,SS14_5 ;skip ahead if 6V mode
 CPI A,HiOff-4  ;check for sustained output
 JP SS14_7
SS14_5
 CPI A,HiOff6-4  ;check for sustained output
SS14_7
 JRNC SS14_4  ;...if not,leave fan off
SS14_6
 CALL FanON  ;...otherwise,turn fan on
 JP SS14_4  ;...and skip ahead
SS14_3
 CALL FanOff  ;turn cooling fan off
SS14_4
 CALL CheckBatt  ;check for battery
 JRS Batt,Flags2,SS14EXIT;...connected:continue
 JP MAIN2  ;...disconnected:start over from state 0
SS14EXIT
 JP ExitMain
;***************************************************************************
;*   SS15MANUAL    *
;* Regulate current.No voltage limit.Reset after 1 hour.  *
;***************************************************************************
SS15
 JRR Power,Flags2,SS15_2 ;power off indicates completed Burn-In
 CALL ShowRate  ;turn on the 2A or 15A LED
;  NOTE:output already on,but TurnON saves code space
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL IReg  ;regulate current at selected rate
;CALL Check17v  ;check for disconnected battery
;JRNZ SS15OK  ;if>>17V,then continue
;LDI CurentSS,ABORT  ;...otherwise,Abort
;RES Manual,Flags3  ;...end Manual Mode
;JP SS15EXIT  ;...and skip rest of State 15
SS15OK
 JRS BurnIn,Flags3,SS15BI;skip ahead if Burn-in mode
 RES MtrScale,Flags  ;set for Alternator % LED off
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
 CALL ShowMeter  ;update meter LEDs
 JP SS15rmp  ;jump to ramp check
SS15BI
 JRR MIN,TicFlag2,SS15b ;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 CALL IniTime2  ;reset Timer2
 LDI Mins2,1  ;set timer for counter interval(1minute)
SS15b
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL ShowNum  ;display count on digital LED
 CALL MeterOff  ;turn off all meter mode LED′s
SS15rmp
 CALL ShowData  ;update display
 JRR Rapid,Flags2,SS15_1 ;don′t ramp if Rapid is not set
 CALL ChkRapid  ;update Ramp timer,if necessary
SS15_1
 JRR HR,TicFlag 1,SS15EXIT;continue if not max manual charge time
 JRS BurnIn,Flags3,SS15_2;skip ahead if finished Burn-In
 JP RESET  ;...otherwise,reset
SS15_2
 CALL DigitsOff  ;turn off 3-digit LED
 CALL ResetLEDs  ;turn off all type,rate & Status LED′s
 CALL ShowGreen  ;light Green LED only
 CALL SetOff  ;reset Power & Cranking flags;set min.duty
SS15EXIT
 JP ExitMain
;***************************************************************************
;*    BOOST MODE   *
;* First set the charger offset value for 2 amp charging.Next,wait *
;* for the voltage to stabilize.Then wait for the voltage to drop *
;* about two volts.When the voltage drops,go full on for 5seconds.*
;* After five seconds of cranking,wait for 4minutes and start over.*
;*          *
;* Comment the CALL and the following two LDI′s for test.Also load offset *
;* with PHASE15 instead of PHAZBOST       *
;***************************************************************************
SS16
 CALL VoltMtr  ;set for volt meter and update display
 JRS ESrly,DRBbuf,SS16_0 ;skip ahead if relay already set for E/S
 CALL FifthSecond  ;wait 200mS
 SET ESrly,DRBbuf  ;set E/S relay for start
SS16_0
 CALL CheckBatt  ;make sure batt is>1.6V
 JRR Batt,Flags2,SS16_1 ;skip ahead if not connected
 JRS SEC,TicFlag2,BattOK  ;skip if>2seconds since Boost selected
 JP SS16Exit  ;if<2seconds,then stay off
SS16_1
 CALL TurnOff  ;low & high power and fan off,min duty
 CALL ShowRed  ;turn on Alert LED
 JP SS16Exit  ;if batt<1.6V,then stay off
BattOK
 CALL ShowCrank  ;turn ON Crank LED & turn Alert LED off
 CALL TurnON  ;turn output,Fan,and Charging LED on
 CALL SetHiOff  ;set for min duty cycle
 SET Started,Flags  ;set Flags for charge started
 CALL IniTime2  ;reset timer 2
 LDI MSecs2,MS200  ;set Timer2 for 200ms
 INC CurentSS  ;set state to 17
SS16Exit
 JP ExitMain  ;goto end of loop
;***************************************************************************
;*    DELAY FOR VOLT READING    *
;***************************************************************************
SS17
 JRS MSEC,TicFlag2,SS 17_1 ;Is 200ms up?
 JP SS17EXIT  ;no,just return
SS17_1
 CALL GetMeter  ;update display
 CALL Check0V  ;make sure batt is connected
 JRS Batt,Flags2,SS17_2  ;skip ahead if connected
 JP MAIN2  ;disconnected,so start over
SS17_2
 SUBIA,010h  ;adjust for a one volt drop
 LD OldVolt,A  ;save it
 LDI MaintVolt,Volts142;try to hold battery at 14.2(or 7.1)V
 LDI LowOff,OffCrank  ;limit rate to Crank offset
 JRR Bat6V,Flags2,SS17_3  ;skip next line if not 6V mode
 LDI LowOff,Off6Crnk  ;limit rate to 6V Crank offset
SS17_3
 INC CurentSS  ;wait for crank
 CALL IniTime2  ;initialize Timer 2
 LDI Mins2,15  ;set Timer 2 for 15 minutes
SS17EXIT
 JP ExitMain
;***************************************************************************
;*    WAIT FOR CRANK    *
;***************************************************************************
SS18
 JRR MIN,TicFlag2,SS 18_0 ;wait for crank only 15 minutes
 JP MAIN2  ;then start re-initialize
SS18_0
 CALL GetMeter  ;update display
 CALL VoltReg  ;regulate battery voltage at MaintVolt
 LD A,FreshBV  ;get current reading
 SUBI A,010h  ;adjust for a one volt drop
 CP A,OldVolt  ;has voltage increased?
 JRC SS18_2  ;if not,then skip ahead
 LD OldVolt,A  ;update OldVolt
SS18x
 JP SS18EXIT  ;and exit routine
SS18_2
 LD A,FreshBV  ;get current reading
 CP A,OldVolt  ;1V drop might indicate cranking
 JRNC SS 18x  ;just exit if no drop
 ADDI A,0Ch  ;store FreshBV+0.8V in A
 CP A,BADhi  ;is latest average>FreshBV+0.8V?
 JRNC SS18EXIT  ;if BADhi>FreshBV+0.8V,start cranking
SS18_1
 SET Power,Flags2  ;turn output on
 INC CurentSS  ;time the cranking
 SET Crnkng,Flags4  ;indicate cranking started
 CALL IniTime2
 LDI Secs2,CrankON  ;crank for CrankON(5)seconds
SS18EXIT
 JP ExitMain
;***************************************************************************
;*    CRANK TIMING    *
;* Allow cranking for five seconds and then go back to charging. *
;***************************************************************************
SS19
 LD A,Secs2  ;get remaining crank seconds
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
 JRR SEC,TicFlag2,SS19EXIT;if cranking not finished,then exit
 RES SCRs,DRBbuf ;turn off SCR′s(in buffer)
 CALL UpdatePB  ;update port B from buffer
 CAll ResetStatus  ;turn off Charging LED
 RES Crnkng,Flags4  ;indicate finished cranking
 RES Power,Flags2  ;tell timer to leave charger off
 INC CurentSS  ;just wait for time to expire
 CALL SetOff  ;turn offpower and set for min duty
 SET CrankWait,Flags  ;indicates crank cool-down time
 CALL IniTime1  ;reset Timer1
 LDI Secsl,CCDint  ;set timer for counter interval(seconds)
 LDI CCDcnt,CrankOff ;set crank cool down counter to CrankOffsecs
SS19EXIT
 JP ExitMain
;***************************************************************************
;*              INTER-CRANK DELAY              *
;* Stay here until the 4minute timer has expired then go back to BOOST *
;* ifswitch still engaged,else goto 2A auto(default)  *
;***************************************************************************
SS20
 CALL FanON  ;turn cooling fan ON
 JRR SEC,TicFlag1,SS20_0 ;skip ahead if not time to update counter
 DEC CCDcnt  ;decrease display count by 1
 JRNZ SS20_1  ;finish state 20 if count down to 0
 RES CrankWait,Flags ;reset CrankWait bit of Flags
 LDI CurentSS,010h  ;set state to 16 to Crank again
 SET SEC,TicFlag2  ;tell State 16 that E/S already running
 JP SS20EXIT  ;and exit State 20
SS20_1
 CALL IniTime1  ;reset Timer1
 LDI Secs1,CCDint  ;set timer for counter interval(seconds)
SS20_0
 LD A,CCDcnt  ;get latest countdown value
 LD LEDnum,A  ;store in LEDnum
 CALL MeterNum  ;show LEDnum and turn off meter mode LED′s
;RES Rmpng,Flags3  ;clear flag for CheckBatt
 RES Settle,Flags3  ;clear flag for CheckBatt
 CALL BlinkCrank  ;blink the Crank LED
SS20EXIT
 JP ExitMain
;***************************************************************************
;*    SUB ROUTINES START HERE   *
;***************************************************************************
;***************************************************************************
;* Initialize state(Slow charge,Regular batt,State 0)  *
;*          *
;***************************************************************************
InitState
 CLR Flags  ;0 is default for all bits
 CLR Flags2  ;0 is default for all bits
 CLR Flags3  ;set to indicate no Rapid to Fast change
 CLR TEMP1  ;initialize
 CLR CCDcnt  ;initialize
 RES Disable,DRBbuf  ;enable output
;SET ChMode,Flags2  ;set for Charger Mode(charger mode)
 RES ESrly,DRBbuf  ;set E/S relay for charge(not boost)
 LDI OFFSET,HiOff-I  ;set for mimimum output current
 LDI LowOff,OffRap  ;limit max rate to full 60A offset
 LDI SwData,01111101b ;Initialize switch LEDs for 2A,Reg
 LDI Vmax,Volts155  ;Vmax for Regular batteries
 LDI VltCnt,001h  ;initialize VltCnt to 1
 LDI VRcnt,001h  ;initialize VRcnt to 1
 LDI PcntL,001h  ;initialize PcntL to 1
 LDI PcntH,001h  ;initialize PcntH to 1
 LDI CurentSS,000h  ;set charger state to 0
 LDI Secs1,SecInit  ;restart TIMER1 second counter
 LDI Secs2,SecInit  ;restart TIMER2 second counter
 RET
;***************************************************************************
;*    Reset Watchdog Register   *
;* This routine simiply resets the Watchdog register.RstWDR was *
;* only to save program space(LDI require 3bytes,CALL requires only 2).*
;*        *
;***************************************************************************
RstWDR
 LDI WDR,0FEH  ;reset watch dog timer
 RET
;***************************************************************************
;*    Set Abort State   *
;* This routine simiply sets CurentSS to ABORT so that the code will go *
;* to the Abort state after the next NMI.SetAbort was written only to *
;* save program space(LDI require 3bytes,CALL requires only 2). *
;*         *
;***************************************************************************
SetAbort
 LDI CurentSS,ABORT  ;set current state to Abort
 RET
;***************************************************************************
;*    Set 100 Percent   *
;* This routine simiply sets Percent to 100.Set100p was written only to *
;* save program space(LDI require 3bytes,CSLL requires only 2). *
;*         *
;***************************************************************************
Set100p
 LDI Percent,100  ;set Percent to 100
 RET
;***************************************************************************
;*    Clear Percent    *
;* This routine simiply sets Percent and DspPcnt to 0.ClrPcnt was  *
;* written only to save program space(CLR require 3bytes,CALL requires  *
;* only 2).Set0p is the second half of ClrPcnt.    *
;*         *
;*    Set 0 Percent    *
;* This routine simply sets Percent to 0.Set0p was written only to  *
;* save program space(LDI require 3bytes,CALL requires only 2). *
;*         *
;***************************************************************************
ClrPcnt
 CLR DspPcnt  ;set Display Percent to 0
Set0p
 LDI Percent,0  ;set Percent to 0
 RET
;***************************************************************************
;*    Update PortA    *
;* This routine updates Port A with the contents of the DRA buffer. *
;* UpdatePA was written only to save program space.    *
;*        *
;***************************************************************************
UpdatePA
 LD A,DRAbuf  ;update Accumulator from buffer
 LD DRA,A   ;update port from Accumulator
RET
;***************************************************************************
;*    Update Port B    *
;* This routine updates Port B with the contents of the DRB buffer. *
;* UpdatePB was written only to save program space.    *
;*        *
;***************************************************************************
UpdatePB
 LD A,DRBbuf  ;update Accumulator from buffer
 LD DRB,A  ;update port from Accumulator
 RET
;***************************************************************************
;*    Update Port B Options    *
;* This routine updates the Port B options with the contents of the ORB *
;* buffer.UpdateORB was written only to save program space.    *
;*        *
;***************************************************************************
UpdateORB
 LD A,ORBbuf  ;update Accumulator from buffer
 LD ORB,A  ;update options register from Accumulator
 RET
;***************************************************************************
;*    Wait a Fifth Second    *
;* This routine causes the program to wait one fifth second by waiting *
;* for 24 interrupts.      *
;***************************************************************************
FifthSecond
 CALL IniTime1
 LDI MSecs1,MS200  ;set timer for 1/5second
WFS_1
 WAIT
 CALL RstWDR  ;reset watch dog timer
 JRR MSEC,TicFlag1,WFS_1  ;wait until timer goes to 0
 RET
;***************************************************************************
;*    Set Ramp Up    *
;* This routine sets the parameters necessary to change the duty from the *
;* fast rate to the rapid rate.It is used before Burn-In and Automatic *
;* Rapid charge.           *
;*         *
;*    Set Ramp    *
;* This routine sets the parameters necessary to change the duty between *
;* the fast and rapid rates.It is actually the last part of SetRmp Up. *
;*           *
;***************************************************************************
SetRmpUp
 LDI RmpCnt,RCinitX2  ;180 1-second intervals yields 180seconds
 RES HiPwr,Flags4  ;set for low power
SetRamp
 LDI TEMP,RIinit  ;120 NMI interrupts yields 1.5seconds
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 RET
;***************************************************************************
;*    CHECK RAPID    *
;* This routine determines whether to reduce or increase the charge rate *
;* from Rapid to Fast or vica versa,if necessary.It sets the flags *
;* used by RampOS appropriately.    *
;*         *
;***************************************************************************
ChkRapid
 JRR Rapid,Flags2,ChkRapX ;if not Rapid charge rate,then exit
 DEC TEMP  ;otherwise,update ramp timer
 JRNZ ChekRapX  ;exit if not time to update count
 LDI TEMP,RIinit  ;count 180 more cycles(1.5sec)
 JRR RmpInt,Flags3,RmpCtr ;skip ahead if just counted 1st half
 RES RmpInt,Flags3  ;...otherwise,start counting 2nd half
ChekRapX
 JP ChkRapX  ;...and exit
RmpCtr
 SET RmpInt,Flags3  ;counting 1st of two 180 cycle periods
 DEC RmpCnt  ;check if time to ramp
 JRNZ ChekRapX  ;exit if not time to ramp
 JRR HiPwr,Flags4,StRmpUp  ;skip ahead if changing to higher rate
 RES HiPwr,Flags4  ;set for not HiPwr(change to lower rate)
 LDI OFFSET,OffFast  ;set for Fast rate
 LDI RmpCnt,RCinitX2  ;...otherwise,double inter-ramp time
 JP ChkRapX
StRmpUp
 SET HiPwr,Flags4  ;set flags for>Fast rate
 LDI OFFSET,OffRap  ;set Offset for Rapid Charge
 LDI RmpCnt,RCinit  ;100 3-second intervals yields 5minutes
ChkRapX
 RET
;***************************************************************************
;*    SHOW NUMBER   *
;* This routine determines what three digits to display on the digital LED *
;* to represent the number stored in LEDNum.The three digits will be *
;* displayed next time the ShowData routine is called.    *
;*         *
;***************************************************************************
ShowNum
 CLR Index  ;initialize LUT Index to 0
 CALL DigiOff  ;set registers for all segments off
 LD A,LEDnum  ;store LEDnum in accumulator
 CPI A,10  ;check for single digit number
 JRNC ChkMaxNum  ;...if not,check for max number
 JP Next001  ;...otherwise skip to 3rd digit
ChkMaxNum
 CPI A,199  ;check for highest displayable number
 JRC Check100  ;if less,check value
 LDI A,199  ;...otherwise,displaly 199
Check100
 CPI A,100  ;check whehter to show most significant 1
 JRC Check010  ;if not,check for 10
 RES Digit1,DigiDat2  ;otherwise,turn ON most significant 1
 SUBI A,100  ;...and subtract 100 from accumulator
Check010
 CPI A,10  ;check if<10
 JRC Check001  ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,10  ;...and subtract 10 from Acumulator
 JP Check010  ;...and check for next higher value
Check001
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d  ;initialize LUT
 LD ATemp,A  ;save Accumulator
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for second digit
 LD DigiDat2,A  ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
Next001
 LDI DRWR,Digits00x.w ;look up table(LUT)for 3rd digit
 LDI X,Digits00x.d  ;initialize LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1  ;...set bits in A for segments
 LD DigiDat1,A  ;...store A into DigiDat1
ShowNumX
 RET
;***************************************************************************
;*    GET VOLT DIGITS   *
;* This routine determines what three digits to display on the digital *
;* LED to represent the battery voltage(BADhi).
;*         *
;***************************************************************************
GetVolts
 DEC VltCnt  ;decrement interval counter
 JRZ NewVolt  ;if 0,ready to update display
 JP GetVexit  ;...otherwise,just exit
NewVolt
 LDI VltCnt,MS500  ;re-initialize interval counter
 JRR ChMode,Flags2,GVT ;if Tester mode,use FreshBV
 LD A,BADhi  ;get latest avg batt voltage
 JP GV10
GVT
 LD A,FreshBV  ;Get latest average battery voltage
GV10
 CALL DigiOff  ;set registers for all segments off
 CLR Index  ;initialize LUT Index to 0
 CPI A,MaxVolts  ;check for max volt reading
 JRC GV17  ;skip ahead if less than max
 LDI DigiDat1,DigiMV1 ;set for digit 1 of max volt display
 LDI DigiDat2,DigiMV2 ;set for digit 2 of max volt display
 JP GetVexit  ;exit GetVolts
GV17
 CPI A,Volts10  ;check for 10V
 JRC Check1V  ;ifnot 10V then skip ahead
 RES Digit1,DigiDat2 ;otherwise,turn ON most significant 1
 SUBI A,Volts10  ;...and subtract 10V from accumulator
Check1V
 CPI A,Volts01  ;check if>1.0V
 JRC Check01V  ;...if so,skip ahead and check 3rd digit
 INC Index  ;...otherwise,show next higher value
 SUBI A,Volts01  ;...and subtract 1.0V from accumulator
 JP Check1V  ;...and check for next higher value
Check01V
 LD ATemp,A  ;save Accumulator
 LDI DRWR,Digits0x0.w ;look up table(LUT)for 2nd digit
 LDI X,Digits0x0.d  ;initialize LUT
 LD A,Index  ;get index from start of LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat2  ;...set bits in A for bottom segments
 LD DigiDat2,A  ;...store A into DigiDat2
 LD A,ATemp  ;restore Accumulator to remainder of LEDnum
ShowV001
 LDI DRWR,Digits0Vx.w ;look up table(LUT)for 3rd volts digit
 LDI X,Digits0Vx.d  ;initialize LUT
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 AND A,DigiDat1  ;...set bits in A for bottom segments
 LD DigiDat1,A  ;...store A into DigiDat1
 RES Decimal,DigiDat1  ;turn ON decimal point
GetVexit
 RET
;***************************************************************************
;*    VoltMeter   *
;* This routine sets the display to show volts,then calls ShowMeter and  *
;* ShowData to update the display with the current battery voltage.  *
;*        *
;*    GetMeter    *
;* This routine calls ShowMeter and ShowData to display the latest  *
;* voltage or percentage(determined by MtrScale & MtrUnits)on the  *
;* 3-digit LED display.GetMeter is the last section of VoltMtr.  *
;*          *
;****************************************************************************
VoltMtr
 RES MtrScale,Flags  ;set for Alternator % LED off
 RES MtrUnits,Flags  ;set for Volts LED ON,batt% LED off
GetMeter
 CALL ShowMeter  ;update meter LEDs
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    GET PERCENT   *
;* This routine determines what value to use for the percentage of *
;* charge before the charge state has reached the dv/dt state.The *
;* percent is calculated by reading the battery voltage(BADhi)and *
;* performing the following calculations:   *
;*  As Tester        *
;*  1.0V<BADhi<11.6V DC==>Percent=(BADhi/16)+1 *
;*  11.61V<BADhi<12.8VDC==>Percent=(BADhi-175)*5+15 *
;*  12.80V<BADhi==>Percent=100  *
;*  As Charger   *
;*  1Volt<BADhi<12Volts==>(BADhi/4)+15=Percent *
;*  12Volts<BADhi<dy/dt==>(BADhi/2)-30=Percent *
;******************************************************************************
GetPercent
 JRR ChMode,Flags2,TstrBP;jump to Tester% if not charging
 LD A,CurentSS ;get current program state
 CPI A,11  ;has charging reached dV/dt?
 JRC CalcPrcnt ;...if not,calculate percentage
GPend
 JP GetPctEnd ;...otherwise,do nothing
CalcPrcnt
 LD A,Percent ;get Percent
 CPI A,76  ;check for highest calculated %
 JRNC GPend ;exit if already there
 JRS HiPwr,Flags4,GPend;exit if in High Power mode
 LD A,RmpCnt ;get Ramp interval counter
;NOTE:RmpCnt will be 0 if not set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC GPend ;don′t update % until end of low power interval
 CALL GetBatt ;get latest voltage & double if 6V mode
 CPI A,Volts12 ;is the battery voltage less than 12V?
 JRNC Formula2 ;...No,goto Formula2
 CPI A,Volts01 ;Is battery>1
 JRNC GPform1 ;...if so,skip next line
 JP GPzero ;...if not,set for zero %
GPform1
 CALL Divide4;...Yes,use first formula
 ADDI A,15  ;Add 15 and...
 JP GetPctExit ;...store into A
Formula2
 CALL Divide2 ;Divide by 2 and
 SUBI A,30  ;...subtract 30
 JP GetPctExit ;skip ahead and finish routine
TstrBP
 LD A,FreshBV ;get latest(avg)battery voltage
 CALL Double6V ;double Battery voltage if set for 6V
 CPI A,Volts128 ;Is battery>12.8V?
 JRC Tstr100 ;...ifnot,skip ahead
 CALL Set100p ;...otherwise,Percent=100
 JP GetPctEnd ;...and end routine
Tstr100
 CPI A,BattMin ;Is battery>BattMin
 JRNC TstrBPhi ;...if so,jump ahead
 CPI A,Volts01  ;Is battery>1
 JRNC TstrBPmed  ;...if so,jump ahead
GPzero
 CALL Set0p ;...otherwise set Percent to 0
 JP GetPctEnd ;...and end routine
TstrBPhi
 SUBI A,BattMin ;subtract minimum high voltage
 CALL ATimes5 ;multiply by 5
 ADDIA,15  ;add 15
 JP GetPctExit ;...store into A
TstrBPmed
 SUBI A,15  ;A=battery-15
 CALL Divide4 ;A=(battery-15)/4
 CALL Divide4 ;A=(battery-15)/16
 INC A ;A=(battery-15)/16+1
GetPctExit
 LD Percent,A ;store into Percent
GetPctEnd
 RET
;***************************************************************************
;*   UPDATE BATTERY PERCENT   *
;* This routine controls how the battery percentage displayed is updated.*
;* UpdateBP ensures that under normal circumstances,the battery % dis-*
;* played is updated according to the following two rules.   *
;* 1.The % displayed doesn′t change by more than 1% at a time  *
;* 2.The % displayed is not updated twice in <PCint seconds  *
;* There are a few exceptions.      *
;* 1.The %displayed can jump up more than 1 if it was 0   *
;* 2.The % displayed will drop to 0 immediately for disconnected batt.*
;* 3.The % displayed can change by more than 1 if the scale** changes *
;*         *
;* **Scale refers to the % scale,which is either battery or alternator *
;*         *
;***********************************************************************************
UpdateBP
 LD A,Percent  ;check whether % is 0
 JRNZ UBP0  ;...if not,wait for update interval
 JP UBPfinish  ;...otherwise finish routine
UBP0
 LD A,DspPcnt  ;get last % displayed
 JRZ UBP00  ;continue if 0%
 JP UBP1  ;skip ahead if not 0%
UBP00
 JRS MtrScale,Flags,UBP1 ;also skip ahead if Alternator %
 JRS Wait0P,Flags2,UBPz ;skip ahead if Wait0P flag already set
 SET Wait0P,Flags2 ;...otherwise,set flag to wait
 CALL IniTime2  ;initialize Timer2
 LDI Secs2,3  ;set Timer2 for 3 seconds
 JRR ChMode,Flags2,UBPz ;skip ahead if in tester mode
 LDI Secs2,5  ;set Timer2 for 5 seconds in charger mode
UBPz
 JRR SEC,TicFlag2,UBPx ;skip ahead if still waiting
UBP0a
 RES Wait0P,Flags2 ;set flag to indicate not waiting
 LD A,Percent  ;...otherwise,get new %
 JP UBPfinish  ;...and don′t wait to display it
UBPx
 JP UBPexit  ;...and just exit
UBP1
 DEC PcntL  ;decrement % interrupt counter
 JRNZ UBPx   ;if not 0 then just exit
 LDI PcntL,MSINIT  ;re-initialize % interupt counter
 DEC PcntH  ;decrement interval counter
 JRNZ UBPx  ;if not down to 0,then just exit
 LDI PcntH,PCint ;re-initialize % interval counter
 LD A,DspPcnt  ;get last % displayed
 JRNZ UBP2   ;skip ahead if not 0%
 LD A,Percent  ;get new %
 JP UBPfinish  ;and finish routine
UBP2
 CP A,Percent  ;compare to newest %
 JRZ UBPexit  ;if equal,do nothing
 JRC IncBP  ;if less,increase display % by 1
 JRS ChMode,Flags2,UBPexit ;don′t decrease % if charging
 DEC A   ;...otherwise,decrease % by 1
 JP UBPfinish  ;...and finish
IncBP
 INC A   ;increase display % by 1
UBPfinish
 LD DspPcnt,A  ;store updated display %
UBPexit
 RET
;***************************************************************************
;*   MeterNum    *
;* This routine calls MeterOff,ShowNum,and ShowData to turn off the *
;* display mode LED′s and display LEDnum on the 3-digit LED display.  *
;*         *
;*    NumData    *
;* This routine calls ShowNum and ShowData to display LEDnum on the  *
;* 3-digit LED display.NumData is the last section of MeterNum. *
;*          *
;****************************************************************************
MeterNum
 CALL MeterOff  ;turn off all meter mode LED′s
NumData
 CALL ShowNum  ;get data to show the number
 CALL ShowData  ;show the number
 RET
;***************************************************************************
;*    SHOW DATA   *
;* This routine updates the digital LED and 6 switch LEDs controlled by *
;* the serial to parallel shift registers.It sends the bits of SwData *
;* and DigiData to the registers bit by bit from LSB to MSB using  *
;* SerData. After each bit is sent,ShftClk is toggled to shift the bit *
;* to the next position. After all 24 bits have been sent,LtchClk is *
;* used to update the outputs,which updates the LEDs.  *
;*         *
;***************************************************************************
ShowData
 CALL RstWDR  ;reset watch dog timer
;RES ClrData,DRAbuf ;clear shift register
;CALL UpdatePA  ;update port A from buffer
;SET ClrData,DRAbuf ;prepare to accept data
;CALL UpdatePA  ;update port A from buffer
 LDI BitCnt,008h ;initialize bit counter to 8
 LDI BytCnt,003h ;initializie byte counter to 3
 LD A,DigiDat1  ;get first 8 bits of digit data
GetBit
 RLC A  ;send MSB of Acumulator to Carry
 JRC SetBit  ;if Carry=1 then data bit is 1
 RES SerData,DRAbuf ;...otherwise set SerData to 0
 JP SendBit  ;skip ahead to SendBit
SetBit
 SET SerData,DRAbuf ;set SerData to 1
SendBit
 LD DataBuf,A  ;store shifted data from A
 CALL UpdatePA  ;update port A from buffer
 RES ShftClk,DRBbuf ;set Shift Clock low
 RES LtchClk,DRBbuf ;set Latch Clock low
 CALL UpdatePB  ;update port B from buffer
 SET ShftClk,DRBbuf ;set Shift Clock high
 CALL UpdatePB  ;update port B from buffer
 DEC BitCnt  ;update bit count
 JRZ NextData  ;if all bits sent then skip ahead
 LD A,DataBuf  ;store shifted data back in A
 JP GetBit  ;otherwise,get next bit
Next Data
 DEC BytCnt  ;update byte count
 JRNZ NextByte  ;get next byte is count is not 0
 JP LatchData  ;...otherwise,done sending bits
NextByte
 LDI BitCnt,08h ;set bit count for 8 more bits
 LD A,BytCnt  ;which byte is next?
 CPI A,02h  ;check for 2nd byte is next
 JRZ ScndByte  ;skip ahead if equal
 LD A,SwData  ;get 8 bits of switch LED data
 JP GetBit  ;send bits of second byte
ScndByte
 LD A,DigiDat2 ;get last 8 bits of digit data
 JP GetBit  ;send bits of second byte
LatchData
 SET LtchClk,DRBbuf ;update latches
 CALL UpdatePB  ;update port B from buffer
 RET
;************************************************************************************
;*    Show Meter    *
;* This routine sets the digital LED to show either the current voltage *
;* or last percent based on Flags and CurentSS. During Engine start,it *
;* will count down seconds of either remaining crank time or cool down *
;* time.       *
;***************************************************************************
ShowMeter
 JRS Alert,Flags2,SMeXit ;exit if abort mode
 JRS MtrUnits,Flags,GetPrcnt ;skip ahead and set for %
 CALL GetVolts  ;...otherwise,get volts
 JRS ChMode,Flags2,SM1 ;skip ahead if not in Tester mode
 CALL ShowStatus ;...otherwise,update Status LEDs
SM1
 JP ShowMtrX  ;...and skip to end or routime
GetPrcnt
 JRR ChMode,Flags2,TstMtr;if in tester mode,get %
 JR ShowPrcnt  ;...otherwise,skip ahead & show %
Show0
 CALL Set0p  ;set to show 0%
ShoPer
 JP ShowPrcnt  ;and skip ahead
TstMtr
 LD A,FreshBV  ;get latest Battery voltage
 JRZ Show0  ;if 0V,show 0%
 JRR MtrScale,Flags,ShoPer;show Battery% if not set for Alt%
 CALL Double6V  ;double Battery voltage if set for 6V
 CPI A,AltMin  ;check for<1st LUT value
 JRC Show0  ;if so,show 0%
 CPI A,AltMax  ;check for>last LUT value
 JRC AltVal  ;if not,skip ahead and check LUT
 LDI Percent,199 ;...otherwise,set to max value
 JP ShowPrcnt  ;and skip ahead
AltVal
 LDI DRWR,AltLvls.w ;LUT for alternator %
 LDI X,AltLvls.d ;initialize LUT
 SUBI A,AltMin  ;diffence is index in look up table
 ANDI A,03Fh  ;limit to window
 ADD A,X  ;add base address of table
 LD X,A  ;store address of value in X
 LD A,(X)  ;store value at X into A
 LD Percent,A  ;store value into Percent
ShowPrcnt
 CALL ShowPercent ;otherwise,show percentage
 CALL ShowStatus ;turn on appropriate status LED
ShowMtrX
 CALL ShoMtrMode ;turn on appropriate meter LED
SMeXit
 CALL RstWDR  ;reset watch dog timer
 RET
;***************************************************************************
;*    SHOW METER MODE   *
;* This routine turns on one of the meter units LED′s based on Flags and *
;* Flags2.If the unit is in TesterMode(ChMode=0),the routine will *
;* also light the appropriate status LED based on the voltage at the *
;* clamps.        *
;*        *
;****************************************************************************
ShoMtrMode
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
ShowVolts
 JRS MtrUnits,Flags,ShoPrcnt ;goto ShoPrcnt if set
 RES LEDvolt,DRAbuf  ;turn on Voltage LED
 JP ShowMMX
ShoPrcnt
 JRS MtrScale,Flags,ShowAlt ;goto ShowAlt if set
 RES LEDprcnt,DRAbuf  ;turn on Battery % LED
 JP ShowMMX
ShowAlt
 RES LEDalt,DRAbuf  ;turn on Alternator % LED
ShowMMX
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*  Hold Meter Mode LED(depending on mode)  *
;* This routine turns on the Battery%,Volts DC,or Alternator% LED based *
;* on Flags & Flags2 and keeps that LED on for one fifth second. *
;***************************************************************************
HoldMtrMd
 CALL ShoMtrMode ;turn on Meter Mode LED
 CALL FifthSecond ;wait one fifth second
RET
;***************************************************************************
;*    SHOW STATUS    *
;* This routine turns on one of the three status LED′s based on the *
;* battery voltage. This routine is for use in the tester mode. *
;*          *
;***************************************************************************
ShowStatus
 JRS ChMode,Flags2,ShoStatX ;exit if not Tester mode
 JRR Batt,Flags2,RedStat  ;show red LED if no battery
 JRR MtrUnits,Flags,ClrStat ;turn off Status LED′s if volts mode
 LD A,FreshBV   ;get latest Battery voltage
 JRS MtrScale,Flags,TestAlt ;skip ahead if set for Alternator
 LD A,DspPcnt  ;get last % displayed
 CPI A,100  ;Is it 100%?
 JRZ GrnBatt  ;...if so,show green LED
 CALL ResetStatus  ;...otherwise,turn Status LED′s off
 JP ShoStatX   ;...and skip to end
GrnBatt
 CALL ShowGreen  ;thru on Green LED
 JP ShoStatX   ;skip to end
TestAlt
 CALL Double6V   ;double Battery voltage if set for 6V
 CPI A,Volts15a  ;Is alternator at least 15.07V?
 JRNC RedStat  ;...if so,skip ahead and show red
 CPI A,Volts138  ;is alternator at least 13.80V?
 JRC RedStat  ;...if not,skip ahead and show red
 CPI A,Volts14  ;Is alternator<14.0V?
 JRC ClrStat  ;...if so,skip ahead and show yellow
 CPI A,Volts149  ;is alternator at least 14.87V?
 JRNC ClrStat  ;...if so,skip ahead and show yellow
 CALL ShowGreen  ;...otherwise turn on Green LED
 JP ShoStatX   ;...and skip to end
RedStat
 CALL ShowRed  ;turn on Red LED
 JP ShoStatX   ;skip to end
ClrStat
 CALL ResetStatus  ;turn Status LED′s off
ShoStatX
 RET
;***************************************************************************
;*    METER OFF   *
;* This routine turns off the three meter mode LED′s.  *
;*       *
;***************************************************************************
MeterOff
 SET LEDvolt,DRAbuf  ;turn off DC Voltage LED
 SET LEDprcnt,DRAbuf  ;turn off Battery % LED
 SET LEDalt,DRAbuf  ;turn off Alternator % LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*    DigiOff    *
;* This routine set the registers to turn off the three-digit LED. *
;*        *
;***************************************************************************
DigiOff
 LDI DigiDat1,DigiOffa ;turn off 8 of 16 digital segments
 LDI DigiDat2,DigiOffb;turn off other 8 of 16 digital segments
 RET
;***************************************************************************
;*    DIGITS OFF    *
;* This routine turns off the three-digit LED.   *
;*       *
;***************************************************************************
DigitsOff
 CALL DigiOff  ;set registers for all segments off
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    DIGITS ON    *
;* This routine turns ON all segments of the three-digit LED. *
;*          *
;***************************************************************************
DigitsON
 LDI DigiDat1,DigiONa ;turn ON 8 of 16 digital segments
 LDI DigiDat2,DigiONb ;turn ON other 8 of 16 digital segments
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    SHOW PERCENT   *
;* This routine turns ON the Battery % LED.   *
;*       *
;***************************************************************************
ShowPercent
 SET MtrUnits,Flags  ;set Flags for %(not volts)
 JRR Wait0P,Flags2,SP1 ;skip ahead if not waiting from 0
 LDI DigiDat1,Dashes1 ;...otherwise,show dashes while waiting
 LDI DigiDat2,Dashes2 ;...otherwise,show dashes while waiting
 JP ShowPx
SP1
 LD A,DspPcnt  ;get Percent value to display
 JRR MtrScale,Flags,SP2 ;don′t use Display% for Alternator%
 LD A,Percent  ;...use actual Percent for display
 .IFC EQ ShoOff ;assemble next line only if debugging
 JRR ChMode,Flags2,SP2 ;skip ahead **DEBUG**
 LD A,OFFSET  ;diplay OFFSET **DEBUG**
;JRR Rapid,Flags2,SP2 ;**DEBUG**
;LD A,RmpCnt  ;display Ramp Count **DEBUG**
 .ENDC
SP2
 LD LEDnum,A  ;...and store it in Accumulator
 CALL ShowNum  ;set digital LED for LEDnum
 SET Decimal,DigiDat1 ;turn OFF decimal point
ShowPx
 RET
;***************************************************************************
;*    RESET LEDS    *
;* This routine turns off the Type,Rate,and Status LED′s   *
;*       *
;***************************************************************************
ResetLEDs
 CALL ResetStatus ;turn off all three status LEDs
ClrLEDs
 LDI SwData,SwsOff ;turn off Type and Rate LED′s
 RET
;***************************************************************************
;*    Reset Status      *
;* This routine turns off the LED′s in the Status area.  *
;*          *
;***************************************************************************
ResetStatus
 SET LEDchgng,DRAbuf ;turn off Charging LED
 SET LEDdone,DRAbuf ;turn off Charged LED
 SET LEDalert,DRAbuf ;turn off Fault(red)LED
 RET
;***************************************************************************
;*    BLINK Charging LED    *
;* This routine blinks the Charging LED at a rate of once per second.*
;***************************************************************************
BlnkChrg
 LD A,MSecs1 ;get MSecs count
 CPI A,MS500 ;test for>1/2 sec
 JRNC BlinkCh1 ;if so,skip ahead
 CALL ResetStatys ;...otherwise,turn off status LEDs
 JP BlinkChX  ;...and exit routine
BlinkCh1
 CALL ShowChgng ;Turn on Charging LED
BlinkChX
 RET
;***************************************************************************
;*    Show Charging    *
;* This routine turns the Charging LED on and the rest off.  *
;*       *
;*    Show Yellow      *
;* This routine turns the Charging LED on and does not affect the Check *
;* and Charged LEDs. ShowYellow is actually the last part of ShowChgng *
;*         *
;***************************************************************************
ShowChgng
 CALL ResetStatus  ;turn off all Status LEDs
ShowYellow
 RES LEDchgng,DRAbuf ;turn ON Charging LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*    BLINK Alert LED   *
;* This routine bliuks the Alert LED at a rate of once per second. *
;*        *
;***************************************************************************
BlinkAlert
 LD A,MSecs1 ;get MSecs count
 CPI A,MS500 ;test for 1/2 sec
 JRNC BlnkAlrt ;if so,skip ahead
 CALL ResetLEDs ;...otherwise,turn off all LEDs
 JRS BurnIn,Flags3,BBI ;skip ahead if not Burn-In
 CALL DigitsON ;...turn on all digital LED segments
 JP BAeXit ;...and exit routine
BBI
 CALL NumData ;get data for,and show LED number
 JP BAeXit ;...and exit routine
BlnkAlrt
 CALL AlertON ;Turn on Alert LED
 CALL DigitsOff ;Turn off 3-digit LED
BAeXit
 RET
;***************************************************************************
;*    Alert LED ON     *
;* This routine turns on the Alert(red)LED and turns the other meter  *
;* LEDs off.NOTE:it does not affect the Rate and Type LEDs.  *
;***************************************************************************
AlertON
 CALL MeterOff ;Turn off Meter Mode LEDs
ShowRed
 CALL ResetStatus  ;Turn off Status LEDs
 RES LEDalert,DRAbuf ;Turn on Alert LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*    Show Done LED    *
;* This routine turns on the Done (green)LED and turns all the other   *
;* LEDs off. NOTE:it turns off the Rate and Type LEDs.  *
;***************************************************************************
ShowDone
 CALL ResetLEDs  ;Turn off all LEDs
 LDI SwData,SwsOff ;set Type & Rate LED′s off
 CALL ShowType  ;show Battery Type & update display
ShowGreen
 CALL ResetStatus ;turn off all three status LEDs
 RES LEDdone,DRAbuf ;Turn on Done LED
 CALL UpdatePA  ;update port A from buffer
 RET
;***************************************************************************
;*    BLINK Crank LED    *
;* This routine blinks the Crank LED at a rate of once per second. *
;***************************************************************************
BlinkCrank
 LD A,MSecs2  ;get MSecs count
 CPI A,MS500  ;test for>1/2 sec
 JRNC BlinkES  ;ifso,skip ahead
 SET LEDboost,SwData ;...otherwise,turn off Crank LED
 JP BCeXit  ;...and exit routine
BlinkES
 CALL ShowCrank  ;turn on Crank LED
BCeXit
 RET
;***************************************************************************
;*    ShowCrank     *
;* This routine turns the Engine Start(Crank/Boost)LED on and turns *
;* the Type aud other Rate LEDs off.    *
;* NOTE:The 6V LED will be left on if appropriate.  *
;***************************************************************************
ShowCrank
 CALL ClrLEDs  ;turn off all Rate & Type LEDs
 JRR Bat6V,Flags2,ShoES ;skip ahead if not 6V
 RES LED6V,SwData  ;turn on Regular 6V LED
ShoES
 RES LEDboost,SwData ;turn ON Crank LED
 CALL ShowData  ;update display
 RET
;***************************************************************************
;*    SetSlow      *
;* This routine sets the charger for the Slow rate by setting the appro- *
;*priate flags.     *
;***************************************************************************
SetSlow
 RES Rate,Flags  ;turn on Slow LED
 RES Rapid,Flags2 ;turn off Rapid LED
 RET
;***************************************************************************
;*    SetSlow      *
;* This routine sets the OFFSET for the correct(12 or 6V)Slow rate.*
;*        *
;***************************************************************************
StartSlow
 LDI OFFSET,OffSlow ;set Offset for 2A
 JRR Bat6V,Flags2,StrtSloX;skip if not set for 6V mode
 LDI OFFSET,Off6Slo ;...otherwise,adjust OFFSET
StrtSloX
 RET
;***************************************************************************
;*    SetMinOff     *
;* This routine sets the OFFSET for the correct(12 or 6V)maximum Slow *
;* rate(minimum OFFSET).     *
;*        *
;***************************************************************************
SetMinOff
 LDI LowOff,MinOff2 ;Iimit output to max 2A current
 JRR Bat6V,Flags2,SetMOx ;skip next line if not 6V mode
 LDI LowOff,Min6Off2 ;limit output to max 6V 2a current
SetMOx
 RET
;***************************************************************************
;*   Show Charge Rate LED(depending on mode) *
;* This routine turns on the Slow,Fast,or Rapid LED,based on Flags.*
;*         *
;***************************************************************************
ShowRate
 SET LEDboost,SwData  ;turn off Boost LED
 SET LEDrap,SwData  ;turn off Rapid LED
 SET LEDfast,SwData  ;turn off Fast LED
 SET LEDslow,SwData  ;turn off Slow LED
 JRR ChMode,Flags2,ShoRateX ;exit if in Tester Mode
ShowRap
 JRR Rapid,Flags2,ShowSlow ;goto ShowSlow if not Rapid
 RES LEDrap,SwData   ;turn on Rapid LED
 JP ShoRateX
ShowSlow
 JRS Rate,Flags,ShowFast ;goto ShowFast if set
 RES LEDslow,SwData  ;turn on Slow LED
 JP ShoRateX
ShowFast
 RES LEDfast,SwData  ;turn on Fast LED
ShoRateX
 RET
;***************************************************************************
;*    Set12V       *
;* This routine sets the charger for the 12V Regular battery type by  *
;* resetting the 6V,AGM/Gel,and Deep Cycle flags.   *
;*           *
;*    SetReg       *
;* This routine sets the charger for the Regular battery type by reset- *
;* ting the Deep Cycle and AGM/Gel flags. SetReg is actually part of *
;* Set12V          *
;***************************************************************************
Set12V
 RES Bat6V,Flags2  ;turn off 6V LED
SetReg
 RES BatTypeA,Flags  ;turn on Regular LED
 RES BatTypeB,Flags  ;turn off Gel/AGM LED
 RET
;***************************************************************************
;*   Show Charge Type LED(depending on mode) *
;* This routine turns on either the Regular,Deep Cycle,Gel/AGM,or 6V *
;* LED based on Flags.The routne also sets Vmax to match. *
;*        *
;***************************************************************************
ShowType
 SET LEDreg,SwData  ;set Regular LED to off
 SET LEDdeep,SwData  ;set Deep Cycle LED to off
 SET LEDgel,SwData  ;set Gel/AGM LED to off
 SET LED6V,SwData  ;set 6V LED to off
 JRR Bat6V,Flags2,ShowT1 ;skip ahead if not 6V
 RES LED6V,SwData  ;turn on Regular 6V LED
 JP ShowT2a  ;set Vmax for regular(15.5V)
ShowT1
 JRR BatTypeB,Flags,ShowT2;skip ahead if not Gel/AGM
 RES LEDgel,SwData  ;turn on Gel/AGM LED
 LDI Vmax,Volts144  ;Vmax=14.4V for Gel/AGM MODE
 JP ShoTypeX
ShowT2
 JRS BatTypeA,Flags,ShowT3 ;goto ShowT3 if set
 RES LEDreg,SwData  ;turn on Regular LED
ShowT2a
 LDI Vmax,Volts155  ;Vmax=15.5V for Regular MODE
 JP ShoTypeX
ShowT3
 RES LEDdeep,SwData  ;turn on Deep Cycle LED
 LDI Vmax,Volts16  ;Vmax=16V for Deep Cycle battery
ShoTypeX
 RET
;***************************************************************************
;*   Hold Charge Type LED(depending on mode) *
;* This routine turns on the Regular,Deep Cycle,or Gel/AGM LED based on *
;* Flags and keeps it on for one Fifth second.    *
;***************************************************************************
HoldType
 CALL ShowType ;turn on Battery Type LED
 CALL ShowData  ;update display
 CALL FifthSecond ;wait one Fifth second
 RET
;***************************************************************************
;*   Hold Charge Rate LED(depending on mode) *
;* This routine turns on the Slow,Fast,or Rapid LED based on Flags and *
;* keeps it on for one Fifth second.    *
;***************************************************************************
HoldRate
 CALL ShowRate  ;turn on Charge Rate LED
 CALL NumData  ;get data for,and show nominal rate(amps)
 CALL FifthSecond ;wait one Fifth second
 RET
;***************************************************************************
;*   Check High Offset    *
;* This routine is used to check whether the latest OFFSET is equal to the *
;* maximum value,HiOff. When OFFSET=HiOff,the charge rate is 0. *
;***************************************************************************
ChkHiOff
 LD A,OFFSET  ;get current OFFSET
 JRS Bat6V,Flags2,CHO6 ;skip next line if not 6V mode
 CPI A,HiOff-2  ;has OFFSET reached maximum(output off)?
 JP CHOx
CHO6
 CPI A,HiOff6-2  ;has OFFSET reached max for 6V(output off)?
CHOx
 RET
;***************************************************************************
;*    Check0V      *
;* This routine checks the latest running average of the battery voltage *
;* and sets the Carry bit if it′s less than Volts0+1 DAC count. This *
;* routine is used to check whether a battery is connected.  *
;***************************************************************************
CheckOV
CheckBatt
 SET Batt,Flags2  ;set flag for connected battery
;LD A,FreshBV  ;test latest average voltage
 LDI A,Volts0+1  ;check if higher than zero
 JRR Crnkng,Flags4,ChkBat;skip next line if not cranking
 LDI A,1   ;check for true 0if cranking
ChkBat
 CP A,FreshBV  ;test latest average voltage
 JRNC NoBatt  ;If not>0,battery not connected
 JP ChkBattX  ;...otherwise,just exit
NoBatt
 RES Batt,Flags2 ;set for battery not connected
 CALL ShowRed  ;turn on Alert(Red)LED
 CALL ClrPcnt  ;clear Percent and Display Percent
 CLR BADhi  ;clear previous voltage reading
 CLR FreshBV  ;clear previous voltage reading
ChkBattX
 RET
;***************************************************************************
;*    Get Battery Voltage   *
;* This routine gets the battery voltage stored in BADhi and saved it in  *
;* the accumulator. It also doubles the result if set for 6V battery. *
;*         *
;*    Double6V      *
;* This routine doubles the accumulator,A,if the Bat6V flag is set.This *
;* routine is called before the accumulator is compared to one of the *
;* constants originally assigned for 12v batteries.    *
;*         *
;* NOTE:If the Bat6V flag is set,and the accumulator is>8.5V,the  *
;* Hi6V Flag is set instetad of doubling A.      *
;***************************************************************************
GetBatt
 LD A,BADhi  ;get latest(avg)battery voltage
Double6V
 JRR Bat6V,Flags2,D6VX ;skip ahead if not set for 6V
 JRR Hi6V,Flags3,D6V ;double if 6V Batt<8.5V
 LDI A,MaxVolts ;...otherwise,set A to MaxVolts
;JRR ChMode,Flags2,D6VX ;check for Charge or Test mode
;CALL SetAbort  ;...set for Abort state if Charge mode
;SET Alert,Flags2 ;...set Alert Flag
 JP D6VX  ;...and skip to end of routine
D6V
 SLA A  ;double A
D6VX
 RET
;***************************************************************************
;*    Check Progress     *
;* This routine is used to ensure that the charger will abort ifthe *
;* battery voltage does not increase throughout the charge. It checks the *
;* voltage every CPint minutes for a measurable increase since the  *
;* previous check. If there isn′t,the charge is aborted.  *
;*          *
;***************************************************************************
ChkProg
 JRR MIN,TicFlag1,ChkProgX ;exit if not time to check for progress
;ChkProg0
;JRR SOC,SwDown,ChkProg1 ;skip ahead if not Start Of Charge
;RES SOC,SwDown  ;...otherwise,clear SOC flag
;CALL IniTime1   ;initialize Timer1
;LDI Mins1,5   ;...set Timer1 for 5 minutes
;CLR LastBatt   ;clear LastBatt(ensure pass 1st test)
;JP ChkProgX   ;...and exit
;ChkProg1
 LD A.BADhi   ;get latest battery reading
 SUBI A,1   ;subtract one count
 CPA,LastBatt  ;check for increase
 JRC ChkProgA   ;set to abort if no increase
 LD A,BADhi  ;set A back to BADhi
 LD LastBatt,A  ;update LastBatt
 CALL IniTime1   ;initialize Timer1
 .IFC NE FastCP  ;assemble next line only if not debugging
 LDI Mins1,CPint  ;set Timer1 for 60 minutes
 .ELSE   ;assemble next line only if debugging
 LDIMins1,3   ;setTimer1 for3 mins
 .ENDC
 DEC CCDcnt  ;update interval count
 JRNZ ChkProgX   ;just exit if not zero
 SET HR,TicFlag1  ;if zero,set for time expired
ChkProgA
 CALL SetAbort   ;set to start Abort mode
ChkProgX
 RET
;***************************************************************************
;*    Battery Progress    *
;* This routine is used to ensure that ChkProg and CheckBatt are called *
;* only when the charge rate is about to ramp up or isn′t set to ramp at *
;* all.That way,the battery voltage used to check charging progress *
;* won′t be affected by the higher current BattProg works by checking *
;* RmpCnt to make sure it′s less than 5.If the start of charge flag(SOC)*
;* is set,BattProg does not check RmpCnt.    *
;*        *
;***************************************************************************
BattProg
;JRR Rmpng,Flags3,BtPrg0 ;skip ahead if not Rapid->Fast transition
;CALL RampOS   ;otherwise,gradually reduce duty cycle
;BtPrg0
 CLR A  ;set A to 0 to ensure<(9,12,or 14.2 V)
 JRS HiPwr,Flags4,BtPrgX ;exit if high power mode
;JRS SOC,SwDown,BtPrg2 ;skip ahead if Start Of Charge
 LD A,RmpCnt ;get Ramp interval counter
;NOTE:RmpCnt will be 0 if not set to ramp at all
 CPI A,5  ;is it almost time to ramp up?
 JRNC BtPrgX  ;if not,then exit
;BtPrg2
 CALL ChkProg  ;check for charging progress
 CALL GetBatt  ;get latest voltage & double if 6V mode
BtPrgX
 RET
;***************************************************************************
;*    Check2V       *
;* This routine checks the latest running average of the battery voltage *
;* and sets the Carry bit if it′s less than Volts016. This routine is  *
;* used to check whether a battery is ready for cranking.   *
;***************************************************************************
Check2V
 LD A,FreshBV  ;test latest average voltage
 CPI A,Volts016 ;check if higher than 1.6 volts
 RET
;***************************************************************************
;*       CHECK SWITCHES    *
;* Check if switch is engaged and change modes if appropriate.  *
;*        *
;***************************************************************************
CheckSw
 JRR CrankWait,Flags,ChkStart ;check switches if not during Crank wait
 JP ChkSwRET   ;don′t check switches if during Crank wait
ChkStart
 JRS Crank,Flags,ChekRate ;don′t check display mode during Boost
 JRR MeterSw,DRC,MeterDown ;If switch is being pressed,skip ahead
 RES MeterSw,SwDown  ;set for Meter switch not pressed(up)
ChekRate
 JP ChkRate   ;Meter switch not pressed,so exit CheckSw
MeterDown
 RES Idle,Flags3  ;set for not idle
 JRS MeterSw,SwDown,ChekRate ;If switch wasn′t released,don′t check it
 SET MeterSw,SwDown  ;set for mode switch pressed(down)
 JRR MtrScale,Flags,ChkPrcnt ;if not set for Alt,then skip ahead
 RES MtrScale,Flags  ;set for Alt%,so change to Batt%
 JP ChkRate
ChkPrcnt
 JRR MtrUnits,Flags,ChkAlt ;if set for volts,then skip ahead
 RES MtrUnits,Flags  ;set for Batt%,so change to volts
JP ChkRate
ChkAlt
 SET MtrUnits,Flags  ;set for volts,so change to %
 .IFC NE ShoOff ;assemble next line only if not debugging
 JRS ChMode,Flags2,ChkRate ;don′t set for Alt if charging
 .ENDC
 SET MtrScale,Flags  ;set for batt,so change to alt
 RES Wait0P,Flags2  ;set to stop waiting for battery %
ChkRate
 CALL ShoMtrMode  ;Meter units are set before rate
;.IFC EQ DEBUG ;assemble next line only if debugging
;JRR SwOff,SwDown,SkpSw ;skip Rate and Type swith if SwOffis set
;JP ChkSwRET  ;Otherwise,just exit
;SkpSw
;.ENDC
 JRR RateSw,DRC,RateDown ;If switch is being pressed,skip ahead
 RES RateSw,SwDown  ;set for Rate switch not pressed(up)
ChekType
 JP ChkType   ;Rate switch not pressed,so check Type
RateDown
 RES Idle,Flags3  ;set for not idle
 JRS RateSw,SwDown,ChekType ;If switch wasn′t released,don′t check it
;JRR RateSw,SwDown,ChngRate ;If switch was released,then check it
;JP ChkType  ;Otherwise,skip ahead to Type Switch
;ChngRate   ;change Charge Rate
 SET RateSw,SwDown  ;set for Rate switch pressed(down)
;SET Crank,Flags  ;...otherwise temporarily set Crank flag
;JRR MtrScale,Flags,ChkCM ;skip ahead if not set for Alt%
;CLR DspPcnt  ;...otherwise,don′t use Alt% for charge
ChkCM
 JRR Crank,Flags,ChkSlow ;if not set for Crank,check for Slow
 CALL TurnOff  ;low & high power and fan off,min duty
 CALL ChrgRly  ;set relay for charge(not start)
 RES ChMode,Flags2  ;set for Tester(not Charger)Mode
 SET Disable,DRBbuf  ;disable output if Rate was Boost
 JP ModeChange  ;go to end of CheckSw
ChkSlow
 JRS ChMode,Flags2,ChkFast ;skip ahead if already Charger mode
 SET ChMode,Flags2  ;set for Charger(not tester)Mode
 RES Disable,DRBbuf  ;enable output after Rate is pressed
 RES MtrScale,Flags  ;set for Batt%(not Alt%)when not tester
 RES Rate,Flags  ;was Crank,so set for Slow
 JP ModeChange  ;go to end of CheckSw
ChkFast   ;if set for Slow,then set to Fast
 JRS Rate,Flags,ChkRap  ;If not Slow,then must be Fast
 SET Rate,Flags  ;set Charge rate for Fast
 JP ModeChange  ;go to end of CheckSw
ChkRap   ;if set for Fast,then change to Rapid
 JRS Rapid,Flags2,ChkES  ;If not Rapid,then must be Fast
 SET Rapid,Flags2   ;set Charge rate for Rapid
 JP ModeChange  ;go to end of CheckSw
ChkES   ;was set to Rapid,change to Boost
 CALL SetSlow  ;set for Slow Rate
 SET Crank,Flags   ;set Charge rate for Boost
;CALL SetReg  ;set battery type for Regular
 CALL ShowCrank  ;turn ON Crank LED
 CALL TurnOff  ;low & high power and fan off,min duty
 LDI CurentSS,CrankSS ;set Charge state to Crank
 CALL IniTime2  ;reset timer 2
 LDI Secs2,003h  ;set Timer2 for 3 seconds
 JP ChkSwRET
 ChkType  ;if Gel/AGM,then set for Regular
 JRR TypeSw,DRC,TypeDown ;If Switch is being pressed,skip ahead
 RES TypeSw,SwDown  ;set for Type switch not pressed(up)
ChkSwX
 JP ChkSwRET   ;Type switch not pressed,so exit CheckSw
TypeDown
 RES Idle,Flags3  ;set for not idle
 JRS TypeSw,SwDown,ChkSwX  ;If Switch wasn′t released,don′t check it
 SET TypeSw,SwDown  ;set for mode switch pressed(down)
 JRR Bat6V,Flags2,ChkBT1  ;If not set for 6V,check for Regular
 ChkBT0   ;if set for 6V,change to 12V regular
 RES Hi6V,Flags3  ;clear 6V over voltage flag
 CALL Set12V  ;set for Regular,12V battery
 CALL ClrPcnt  ;clear Percent and Display Percent
 JP TypeChange  ;go to end of CheckSw
 ChkBT1   ;if set for AGM/Gel,change to 6V
 JRR BatTypeB,Flags,ChkBT2 ;Ifnot set for Gel/AGM,check for Regular
 JRS Hi6V,Flags3,ChkBT0 ;don′t set to 6V ifbatt>8.5V
 CALL SetReg  ;set battery type for Regular
 SET Bat6V,Flags2  ;set for 6V battery
 CALL ClrPcnt  ;clear Percent and Display Percent
 JP TypeChange  ;go to end of CheckSw
 ChkBT2   ;if Regular,then set for Deep Cycle
 JRS BatTypeA,Flags,ChkBT3 ;If not set for Regular,must be Deep Cycle
 SET BatTypeA,Flags  ;set battery type for Deep Cycle
 RES BatTypeB,Flags  ;set battery type for not AGM/Gel
 JP TypeChange  ;go to end of CheckSw
 ChkBT3   ;must be Deep Cycle,so set for Gel/AGM
 SET BatTypeB,Flags  ;set battery type for Gel/AGM
 RES BatTypeA,Flags  ;set battery type for not Deep Cycle
TypeChange
 RES Crank,Flags   ;set charge rate for non-Boost
 CALL ShowType   ;turn on Battery Type LED
ModeChange
 RES Crank,Flags  ;clear Crank bit of Flags
 LDI CurentSS,000h  ;restart charging
ChkSwRET
 RET
;***************************************************************************
;*        FAN ON      *
;*This routine turns the cooling fan ON.FanON is called during one of *
;*the following conditions:       *
;*1.Start of charge(end of State 2)    *
;*2.Start of boost(State 16)      *
;*3.If OFFSET<HiOff-3 in Maintain(State 14)    *
;*4.Manual Mode(State 15)      *
;*5.States 4,5,11,12,and 13    *
;*         *
;***************************************************************************
FanON
 LD ATemp,A  ;save Accumulator
 LDI A,00010000b  ;update Accumulator from buffer
 LD DRC,A  ;update port from Accumulator
 LD A,ATemp  ;restore Accumulator
 RET
;***************************************************************************
;*      FAN Off       *
;*This routine turns the cooling fan off.FanOff is called during one of *
;*the following conditions:       *
;*1.Before start of charge(State 0)    *
;*2.Start of Abort(State 8)      *
;*3.Before start of Maintain(State 14)     *
;*4.If OFFSET=HiOff in Maintain(State 14)     *
;*        *
;***************************************************************************
FanOff
 LD ATemp,A  ;save Accumulator
 LDI A,00000000b ;update Accumulator from buffer
 LD DRC,A  ;update port from Accumulator
 LD A,ATemp  ;restore Accumulator
RET
;***************************************************************************
;*    ShutOff    *
;*This routine sets the charger for no output by turning off the output *
;*FETs,turning off the fan,setting the PWM for minimum duty cycle *
;*(HiOFF),and setting it for non-boost mode.     *
;*         *
;*       TurnOff      *
;*This routine sets the charger for no output by turning off the output *
;*FETs,turning off the fan,and setting the PWM for minimum duty  *
;*cycle(HiOFF).TurnOff is actually part of ShutOff.   *
;*        *
;***************************************************************************
ShutOff
 RES Crank,Flags  ;set charge rate for non-Boost
 CLR RmpCnt  ;clear ramp interval counter
TurnOff
 CALL FanOff  ;turn cooling fan off
SetOff
 RES Power,Flags2  ;turn output off
 RES Crnkng,Flags4  ;indicate not cranking
SetHiOff
 LDI OFFSET,HiOff ;set for minimum duty cycle
 JRR Bat6V,Flags2,SOx ;skip next line if not 6V mode
 LDI OFFSET,HiOff6 ;set for min.6V duty cycle
 SOx
 RET
;***************************************************************************
;*     TurnON     *
;*This routine sets the charger to run with the Charging LED,fan,and *
;*output on.         *
;*          *
;*    SetON     *
;*This routine sets the charger to run with the fan and output on *
;*SetON is actually part of TurnON     *
;*          *
;***************************************************************************
TurnON
 CALL ShowChgng  ;turn Charging LED on
SetON
 CALL FanON  ;turn cooling fan on
 SET Power,Flags2  ;tell PwrCon charger is on
 RET
;***************************************************************************
;*    Charge Relay      *
;*This routine switches the relay from Start to Charge if necessary.*
;*ChrgRly waits 200mS before switching the relay.The output should  *
;*before turned off before calling ChrgRly.    *
;*          *
;***************************************************************************
ChrgRly
 JRR ESrly,DRBbuf,ChgRlyX;skip ahead if relay already set for charge
 CALL FifthSecond ;wait 200mS
 RES ESrly,DRBbuf ;set E/S relay for charge
ChgRlyX
 RET
;***************************************************************************
;* Update the clocks and set overflow flags as necessary.  *
;*TicFlag1(s)bit 0=hours went to zero   *
;*TicFlag1(s)bit 1=minutes went to zero    *
;*TicFlag1(s)bit 2=seconds went to zero   *
;*TicFlag1(s)bit 3=miliseconds went to zero   *
;***************************************************************************
CLOCKS
 DEC MSecs1   ;decrement millisecond counter
 JRNZ Clks1   ;skip to clock2 if MSECs<>0
Do_MSecs
 LDI A,MSINIT  ;restart millisecond counter
 LD MSecs1,A  ;
 SET MSEC,TicFlag1  ;set millisec flag
 DEC Secs1  ;decrement second counter
 JRZ Do_Mins
Clks1
 JP CLOCKS1
Do_Mins
 SET SEC,TicFlag1  ;set second expired flag
 LDI Secs1,SecInit  ;restart second counter
 DEC Mins1   ;decrement minute counter
 JRNZ CLOCKS1  ;skip HRs1 if MINs1<>down to zero
Do_Hrs
 SET MIN,TicFlag1  ;set minute expired flag
 LDI Mins1,MinInit  ;restart minute counter
 DEC Hrs1   ;decrement hour counter
 JRNZ CLOCKS1   ;check for overflow
 SET HR,TicFlag1  ;set hour expired flag
CLOCKS1
 DEC MSecs2  ;decrement millisecond counter
 JRZ DOMSecs2
ClkExit
 JP CLOCEXIT
DOMSecs2
 LDI A,MSINIT  ;restart millisecond counter;
 LD MSecs2,A  ;
 SET MSEC,TicFlag2  ;set millisec flag
 DEC Secs2  ;decrement second counter
 JRNZ ClkExit  ;exit if not down to zero
Do_Mins2
 SET SEC,TicFlag2  ;set second expired flag
 LDI Secs2,SecInit  ;restart second counter
 DEC Mins2  ;decrement minute counter
 JRNZ CLOCEXIT  ;exit if not down to zero
Do_Hrs2
 SET MIN,TicFlag2  ;set minute expired flag
 LDI Mins2,MinInit  ;restart minute counter
 DEC Hrs2   ;decrement hour counter
 JRNZ CLOCEXIT  ;check for overflow
 SET HR,TicFlag2  ;set hour expired flag
CLOCEXIT
 RET
;***************************************************************************
;*   INITIALIZE TIMER1    *
;*  Subroutine to initialize timer1    *
;***************************************************************************
IniTime1
 LDI MSecs1,MSINIT
 LDI Secs1,SecInit
 LDI Mins1,MinInit
 CLR Hrs1
 CLR TicFlag1
 RET
;***************************************************************************
;*    INITIALIZE TIMER2    *
;*   Subroutine to initialize Timer2    *
;***************************************************************************
IniTime2
 LDI MSecs2,MSINIT
 LDI Secs2,SecInit
 LDI Mins2,MinInit
 CLR Hrs2
 CLR TicFlag2
 RET
;***************************************************************************
;*    ShiftA7    *
;*Subroutine to shift the accumulator left 7 times.Used by Divide2 *
;*and Divide4.Written only to save code space.  *
;***************************************************************************
ShiftA7
 SLA A  ;shift left
 RLC A ;rotate left through CARRY bit 6 times
 RLC A
 RLC A
 RLC A
 RLC A
 RLC A
 RET
;***************************************************************************
;*    DIVIDE BY 2    *
;*Subroutine to divide the number in A by 2.The remainder,if any *
;*will be available in the carry bit upon return.    *
;***************************************************************************
Divide2
 CALL ShiftA7 ;shift left once then rotate left 7 times
 RLC A ;rotate left 7th time
 RET
;***************************************************************************
;*    DIVIDE BY 4    *
;*Subroutine to divide the number in A by 4.    *
;***************************************************************************
Divide4
 CALL ShiftA7  ;shift left once then rotate left 7 times
 ANDI A,01111111b ;drop MSB
 RET
;***************************************************************************
;*    A Times 5    *
;*Subroutine to multiply the accumulator (A)by 5.    *
;*Atimes5 multplies A by 4 by shiling left twice then adding the  *
;*original value of A:(A*4)+A=A*5     *
;***************************************************************************
ATimes5
 LD ATemp,A  ;ATemp=A
 ADD A,A  ;A=A+A=A*2
 ADD A,A  ;A=A+A=ATemp*4
 ADD A,ATemp  ;A=A+ATemp=ATemp*5
 RET
;***************************************************************************
;*    CURRENT REGULATION   *
;*This routine reduces the output current by increasing the OFFSET *
;*value when the voltage is below 14.2 volts(thru SS5).An offset into *
;*an LUT is determined based on the battery voltage.The value is loaded *
;*into OFFSET which is used to controls the offtime of the SCR′s.  *
;***************************************************************************
IReg
 LD A,BADhi  ;get voltage
;LD A,FreshBV  ;get voltage
 JRS Bat6V,Flags2,IR_6V ;skip ahead if 6V mode
 JRS Rate,Flags,PH_1  ;skip ahead if 15 amp mode
 LDI DRWR,OFFADJ2.w  ;look up table for 12V 2 amp
 LDI X,OFFADJ2.d  ;initialize look up table
 LDI TempOff,OffLow2 ;highest 2A offset-lowest current
 SUBI A,BatLo2  ;sub mininum 12V 2 amp table entry(10V)
 JRNC P_A14  ;done
P_A15
 LD A,TempOff
 JP P_A12
P_A14
 LDI TempOff,OffHi2  ;lowest 12V 2A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC P_A15  ;done
 JP PH_2  ;done with 12V 2 amp
PH_1
 JRS Rapid,Flags2,IR_rap ;skip ahead if Rapid rate
IR_1
 LDI DRWR,OFFADJ15.w ;look up table for 12V 15 amp
 LDI X,OFFADJ15.d ;initialize look up table
 LDI TempOff,OffLow15 ;highest 15A offset-lowest current
 SUBI A,BatLo15  ;sub mininum 15 amp table entry
 JRNC P_A17  ;done
P_A16
 JP P_A15
P_A17
 LDI TempOff,OffHi15 ;lowest 12V 15A offset-highest current
 CPI A,040h  ;last table entry-highest index
 JRNC P_A16  ;done
 JP PH_2  ;done with 12V 15 amp
IR_rap
 JRR HiPwr,Flags4,IR_1 ;use 12V 15A table if low power mode
 LDI DRWR,OffAdj60.w ;look up table for 60 amp
 LDI X,OffAdj60.d  ;initialize look up table
 LDI TempOff,OffLow60 ;highest 60A offset-lowest current
 SUBI A,BatLo60  ;sub mininum 60 amp table entry
 JRNC IR_rp2  ;done
IR_rp1
 JP P_A15
IR_rp2
 LDI TempOff,OffHi60 ;lowest 60A offset-highest current
 CPI A,040h   ;last table entry-highest index
 JRNC IR_rp1  ;done
PH_2
 ANDI A,03Fh  ;limit to 64 byte window
 ADD A,X   ;add table base address
 LD X,A   ;
 LD A,(X)  ;get value from table
 JP P_A12  ;skip ahead and update offet value
IR_6V
 JRS Rate,Flags,IR6_3  ;skip ahead if 15  amp mode
 LDI DRWR,OfAd6V2.w  ;look up table for 6V 2 amp
 LDI X,Of Ad6V2.d  ;initialize look up table
 LDI TempOff,Off6Lo2 ;highest 2A offset-lowest current
 SUBI A,Bat6Lo2  ;sub mininum 6V 2 amp table entry(5V)
 JRNC IR6_2  ;done
IR6_1
 LD A,TempOff
 JP P_A12
IR6_2
 LDI_TempOff,Off6Hi2 ;lowest 6V 2A offset-highest current
 CPI A,020h   ;last table entry -highest index
 JRNC IR6_1  ;done
 JP IR6_10  ;done with 6V 2 amp
IR6_3
 JRSRapid,Flags2,IR6_7 ;skip ahead if Rapid rate
IR6_4
 LDI DRWR,OfAd6V15.w ;look up table for 6V 15 amp
 LDI X,OfAd6V15.d  ;initialize look up table
 LDI TempOff,Off6Lo15 ;highest 15A offset-lowest current
 SUBI A,Bat6Lo15  ;sub mininum 6V 15 amp table entry
 JRNC IR6_6  ;done
IR6_5
 JP IR6_1
IR6_6
 LDI TempOff,Off6Hi15 ;lowest 6V 15A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_5  ;done
 JP IR6_10  ;done with 6V 15 amp
IR6_7
 JRR HiPwr,Flags4,IR6_4 ;use 6V 15A table if low power mode
 LDI DRWR,Of Ad6V60.w ;look up table for 60 amp
 LDI X,OfAd6V60.d  ;initialize look up table
 LDI TempOff,Off6Lo60 ;highest 6V 60A offset-lowest current
 SUBI A,Bat6Lo60  ;sub mininum 6V 60 amp table entry
 JRNC IR6_9  ;done
IR6_8
 JP IR6_1
IR6_9
 LDITempOff,Off6Hi60 ;lowest 6V 60A offset-highest current
 CPI A,020h  ;last table entry-highest index
 JRNC IR6_8  ;done
IR6_10
 ANDI A,01Fh  ;limit to 32 byte window
 ADD A,X  ;add table base address
 LD X,A  ;
 LD A,(X)  ;get value from table
P_A12
;ADD A,FUDGE  ;debug fudge factor
 LD OFFSET,A  ;save new offset value
P_A13
 RET
;***************************************************************************
;*   VOLTAGE REGULATION   *
;*  This subroutine will adjust the value of OFFSET once per second to *
;*control the current and maintain the voltage determined by MaintVolt.*
;*         *
;***************************************************************************
VoltReg
;LD A,MSecs2  ;MSec2=MSInit once per second
;CPI A,MSINIT  ;Is MSEC1=MSINIT?
;JRZ VReg_0  ;Yes:then time to adjust
;VReg_X
;JP VReg_3  ;No:then not time to adjust
;VReg_0  ;adjust offset
 DEC VRcnt  ;decrement interval counter
 JRZ VReg_0  ;Yes:then time to adjust
 JP VoltRegX  ;No:then not time to adjust
VReg_0   ;adjust offset
 LDI VRcnt,MSINIT ;re-initialize initerval counter(1 sec)
 LD A,FreshBV  ;get battery voltage
 CALL Double6V  ;double Battery voltage if set for 6V
 DEC A
 CP A,MaintVolt ;compare with set value+1
 JRNC VReg_6  ;greater than,increase OFFSET
 JP VReg_1  ;not greater than,test if less than
VReg_6
 LD A,OFFSET  ;greater than,get phase delay value
 INC A  ;
 JRS Bat6V,Flags2,VReg_2
 CPI A,HiOff  ;test if at high limit
 JP VReg_5
VReg_2
 CPI A,HiOff6
VReg_5
 JRNC VReg_3  ;at the limit,don′t change OFFSET
VReg_4
 LD OFFSET,A  ;update OFFSET
VReg_3
 JP VoltRegX  ;done for this pass
VReg_1
 INC A
 CP A,MaintVolt ;compare with set value
 JRNC VoltRegX  ;not less than,just exit
 LD A,OFFSET  ;less than,get phase delay value
 DEC A  ;
 CPA,LowOff  ;test if at low limit
 JRNC VReg_4  ;not at the limit,update OFFSET
 VoltRegX
 RET
;***************************************************************************
;*   TIMER INTERRUPT HANDLER   *
;*This routine turns the SCRs on if the power flags are non-zero and *
;* inhibits the timer.     *
;***************************************************************************
PwrCon
 LD ATemp,A  ;save A register
 JRS Power,Flags2,PCon ;charger on,turn on SCRs
 JP PWREXIT  ;not charging,just exit
PCon
 SET SCRs,DRBbuf ;turn on the SCRs(in buffer)
 CALL UpdatePB  ;update port B from buffer
PWREXIT
;LDI TSCR,015h  ;inhibit timer
 CALL RstWDR   ;reset watch dog timer
 LDI A,FULLTIME ;TCR is reloaded here for 1 full cycle
 LD TCR,A  ;
 LDI TSCR,05dh  ;reload prescaler and start timer
 JRR Crnkng,Flags4,PC_Norm
PC_Crank
 CALL CLOCKS  ;update clocks
 RES NMInt,Flags2  ;tell ExitMain this was NMI interupt
 JP PCexit  ;leave SCRs on during Crank
;turn offSCR drive so that only a pulse is generated(SCR′s latch on)
PC_Norm
 SET NMInt,Flags2  ;tell ExitMain this was timer interupt
;RES SCRs,DRBbuf ;otherwise,turn off SCR′s(in buffer)
;CALL UpdatePB  ;update port B from buffer
PCexit
 LD A,ATemp  ;restore A register
 RETI
;***************************************************************************
;*           NON-MASKABLE INTERRUPT HANDLER   *
;*This is the NMI interrupt routine.The NMI is generated on the falling *
;*edge of the full wave rectified AC line voltage.An interrupt is  *
;*generated 120 times per second,once every 8.333ms.After each NMI,*
;*this routine performs the following steps.    *
;*1.Reset the watchdog timer and save the registers.  *
;*2.Turn off the SCRs(unless during CrankON state).   *
;*3.Set the interrupt timer according to OFFSET.    *
;*4.Reset NMInt so ExitMain knows it′s an NMI(not timer int).*
;*5.Update the clocks.     *
;*6.Restore the registers.     *
;*If turned off,the SCRs will remain off for a period determined by *
;*OFFSET.The Timer will then trigger an internpt which tells PwrCon *
;*to turn the SCRs back on ifnecessary.   *
;*           *
;***************************************************************************
IT_TIMER
 CALL RstWDR  ;reset watch dog timer
 LD ATemp,A ;save A register
 LD A,X  ;get X register
 LD XTEMP,A ;save X register
 JRS Crnkng,Flags4,IT_X
IT_Norm
 NOP
 LDI X,2Ah  ;delay for true zero cross
IT_T
 DEC X
 JRNZ IT_T
 NOP  ;adjust zero cross delay
 LD A,OFFSET ;get current offset
 LD TCR,A ;load the counter with current offset
 LDI TSCR,01011101b ;relo ad prescaler(32)and start timer
 RES SCRs,DRBbuf ;turn off SCR′s(in buffer)
 CALL UpdatePB ;update port B from buffer
IT_TMR
 RES NMInt,Flags2 ;tell ExitMain this was NMI interupt
 CALL CLOCKS ;update clocks
IT_X
 LD A,XTEMP ;restore registers
 LD X,A
 LD A,ATemp
 RETI
;***************************************************************************
;*  A/D INTERRUPT HANDLER   *
;*This is the A to D interrupt service routine.The only thing it does is *
;*clear the interrupt bit and wakes the processor up from its wait mode.*
;***************************************************************************
ADINT
RES 7,ADCR
LD A,ADR
RETI
;***************************************************************************
;* ROM DATA WINDOW for THIRD VOLTS LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the third(least significant)digit of the voltage display.  *
;***************************************************************************
.block 16-$%16
Digits0Vx
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;display_0 for 00h
.byte 01111110b ;display_1 for 01h
.byte 01111110b ;display_1 for 02h
.byte 00110001b ;display_2 for 03h
.byte 00111000b ;display_3 for 04h
.byte 00111000b ;display_3 for 05h
.byte 01011100b ;display_4 for 06h
.byte 10011000b ;display_5 for 07h
.byte 10011000b ;display_5 for 08h
.byte 10010000b ;display_6 for 09h
.byte 00111110b ;display_7 for 0Ah
.byte 00111110b ;display_7 for 0Bh
.byte 00010000b ;display_8 for 0Ch
.byte 00011000b ;display_9 for 0Dh
.byte 00011000b ;display_9 for 0Eh
;***************************************************************************
;*ROM DATA WINDOW for THIRD LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the third(least significant)digit on the LED.   *
;***************************************************************************
.block 16-$%16
Digits00x
;patterns for DigiDat1-Digit 1(LSD)& decimal point
.byte 00010010b ;bit pattern to display_0
.byte 01111110b ;bit pattern to display_1
.byte 00110001b ;bit pattern to display_2
.byte 00111000b ;bit pattern to display_3
.byte 01011100b ;bit pattern to display_4
.byte 10011000b ;bit pattern to display_5
.byte 10010000b ;bit pattern to display_6
.byte 00111110b ;bit pattern to display_7
.byte 00010000b ;bit pattern to display_8
.byte 00011000b ;bit pattern to display_9
;***************************************************************************
;*  ROM DATA WINDOW for SECOND LED DIGIT  *
;*The following bit patterns are used to display the indicated numbers as *
;*the second(middle significant)digit on the LED.  *
;***************************************************************************
.block 16-$%16
Digits0x0
;patterns for DigiDat2-Digit 2(middle digit)and MS 1
.byte 00000101b ;bit pattern to display_0_
.byte 11001111b ;bit pattern to display_1_
.byte 00100011b ;bit pattern to display_2_
.byte 10000011b ;bit pattern to display_3_
.byte 11001001b ;bit pattern to display_4_
.byte 10010001b ;bit pattern to display_5_
.byte 00010001b ;bit pattern to display_6_
.byte 11000111b ;bit pattern to display_7_
.byte 00000001b ;bit pattern to display_8_
.byte 10000001b ;bit pattern to display_9_
;***************************************************************************
;*ROM DATA WINDOW for Alternator Charge in Percent  *
;*The following values are the Percent values for the alternator voltages *
;*listed below.These numbers are only used when the charger is in  *
;*Tester mode.Voltages lower than the first entry are displayed as 0% *
;*charged.Voltages above the last entry are displayed as 199%charged. *
;***************************************************************************
.block 32-$%32
AltLvls
;%Volts Hex
.byte 0 ;13.53 CB red
.byte 12 ;13.60 CC |
.byte 25 ;13.67 CD |
.byte 38 ;13.73 CE red
.byte 50 ;13.80 CF yellow
.byte 62 ;13.87 D0 |
.byte 75 ;13.93 D1 yellow
.byte 85 ;14.00 D2 green
.byte 92 ;14.07 D3 |
.byte 97 ;14.13 D4 |
.byte 100 ;14.20 D5 |
.byte 100 ;14.27 D6 |
.byte 100 ;14.33 D7 |
.byte 100 ;14.40 D8 |
.byte 100 ;14.47 D9 |
.byte 100 ;14.53 DA |
.byte 100 ;14.60 DB |
.byte 103 ;14.67 DC |
.byte 110 ;14.73 DD |
.byte 120 ;14.80 DE green
.byte 130;14.87 DF yellow
.byte 140;14.93 E0|
.byte 150;15.00 E1 yellow
.byte 160;15.07 E2 red
.byte 170;15.13 E3 |
.byte 180;15.20 E4 |
.byte 190;15.27 E5 |
.byte 196;15.33 E6 red
.byte 199;15.40 E7 red
;***************************************************************************
;*  ROM DATA WINDOW FOR 2 amp mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
.block 64-$%64
OFFADJ2
;2 amp table
;Offset Index Volts
;(D) (h) (Dec) (Hex)
.byte 128;7F 0 10.00 96
.byte 128;7F 1 10.07 97
.byte 127;7E 2 10.13 98
.byte 127;7E 3 10.20 99
.byte 127;7E 4 10.27 9A
.byte 127;7E 5 10.33 9B
.byte 127;7E 6 10.40 9C
.byte 127;7E 7 10.47 9D
.byte 127;7E 8 10.53 9E
.byte 126;7D 9 10.60 9F
.byte 126;7D 10 10.67 A0
.byte 126;7D 11 10.73 A1
.byte 126;7D 12 10.80 A2
.byte 126;7D 13 10.87 A3
.byte 125;7C 14 10.93 A4
.byte 125;7C 15 11.00 A5
.byte 125;7C 16 11.07 A6
.byte 125;7C 17 11.13 A7
.byte 125;7C 18 11.20 A8
.byte 125;7C 19 11.27 A9
.byte 125;7C 20 11.33 AA
.byte 125;7C 21 11.40 AB
.byte 124;7B 22 11.47 AC
.byte 124;7B 23 11.53 AD
.byte 124;7B 24 11.60 AE
.byte 124;7B 25 11.67 AF
.byte 124;7B 26 11.73 B0
.byte 124;7B 27 11.80 B1
.byte 124;7B 28 11.87 B2
.byte 123;7A 29 11.93 B3
.byte 123;7A 30 12.00 B4
.byte 123;7A 31 12.07 B5
.byte 123;7A 32 12.13 B6
.byte 123;7A 33 12.20 B7
.byte 123;7A 34 12.27 B8
.byte 122;79 35 12.33 B9
.byte 122;79 36 12.40 BA
.byte 122;79 37 12.47 BB
.byte 122;79 38 12.53 BC
.byte 122;79 39 12.60 BD
.byte 121;78 40 12.67 BE
.byte 121;78 41 12.73 BF
.byte 121;78 42 12.80 C0
.byte 121;78 43 12.87 C1
.byte 120;77 44 12.93 C2
.byte 120;77 45 13.00 C3
.byte 120;77 46 13.07 C4
.byte 120;77 47 13.13 C5
.byte 120;77 48 13.20 C6
.byte 119;76 49 13.27 C7
.byte 119;76 50 13.33 C8
.byte 119;76 51 13.40 C9
.byte 119;76 52 13.47 CA
.byte 119;76 53 13.53 CB
.byte 119;76 54 13.60 CC
.byte 118;75 55 13.67 CD
.byte 118;75 56 13.73 CE
.byte 118;75 57 13.80 CF
.byte 118;75 58 13.87 D0
.byte 117;74 59 13.93 D1
.byte 117;74 60 14.00 D2
.byte 117;74 61 14.07 D3
.byte 117;74 62 14.13 D4
.byte 117;74 63 14.20 D5
;***************************************************************************
;*  ROM DATA WINDOW FOR 15 amp mode  *
;* These are the off sets to control the current output.  *
;***************************************************************************
;.block 64-$%64
OFFADJ15
;  Offset  Batt Volts
; Dec Hex  Index Dec Hex
.byte 112;70 0 9.00 87
.byte 112;70 1 9.07 88
.byte 112;70 2 9.13 89
.byte 111;6F 3 9.20 8A
.byte 111;6F 4 9.27 8B
.byte 111;6F 5 9.33 8C
.byte 111;6F 6 9.40 8D
.byte 111;6F 7 9.47 8E
.byte 111;6F 8 9.53 8F
.byte 111;6F 9 9.60 90
.byte 111;6F 10 9.67 91
.byte 111;6F 11 9.73 92
.byte 111;6F 12 9.80 93
.byte 110;6E 13 9.87 94
.byte 110;6E 14 9.93 95
.byte 109;6D 15 10.00 96
.byte 109;6D 16 10.07 97
.byte 109;6D 17 10.13 98
.byte 109;6D 18 10.20 99
.byte 109;6D 19 10.27 9A
.byte 109;6D 20 10.33 9B
.byte 109;6D 21 10.40 9C
.byte 108;6C 22 10.47 9D
.byte 108;6C 23 10.53 9E
.byte 108;6C 24 10.60 9F
.byte 108;6C 25 10.67 A0
.byte 108;6C 26 10.73 A1
.byte 107;6B 27 10.80 A2
.byte 107;6B 28 10.87 A3
.byte 107;6B 29 10.93 A4
.byte 106;6A 30 11.00 A5
.byte 106;6A 31 11.07 A6
.byte 106;6A 32 11.13 A7
.byte 106;6A 33 11.20 A8
.byte 106;6A 34 11.27 A9
.byte 106;6A 35 11.33 AA
.byte 106;6A 36 11.40 AB
.byte 105;69 37 11.47 AC
.byte 105;69 38 11.53 AD
.byte 104;68 39 11.60 AE
.byte 104;68 40 11.67 AF
.byte 104;68 41 11.73 B0
.byte 104;68 42 11.80 B1
.byte 104;68 43 11.87 B2
.byte 104;68 44 11.93 B3
.byte 104;68 45 12.00 B4
.byte 103;67 46 12.07 B5
.byte 103;67 47 12.13 B6
.byte 103;67 48 12.20 B7
.byte 103;67 49 12.27 B8
.byte 102;66 50 12.33 B9
.byte 102;66 51 12.40 BA
.byte 102;66 52 12.47 BB
.byte 102;66 53 12.53 BC
.byte 102;66 54 12.60 BD
.byte 102;66 55 12.67 BE
.byte 101;65 56 12.73 BF
.byte 101;65 57 12.80 C0
.byte 101;65 58 12.87 C1
.byte 101;65 59 12.93 C2
.byte 101;65 60 13.00 C3
.byte 100;64 61 13.07 C4
.byte 100;64 62 13.13 C5
.byte 99;63 63 13.20 C6
;***************************************************************************
;*   ROM DATA WINDOW FOR 60 amp mode  *
;* These are the offsets to control the current output.  *
;***************************************************************************
;.block 64-$%64
OffAdj60
; Offset     Volts
;Dec Hex    Index Dec Hex
.byte 77;49 0 9.80 93
.byte 77;49 1 9.87 94
.byte 77;48 2 9.93 95
.byte 77;48 3 10.00 96
.byte 76;47 4 10.07 97
.byte 76;47 5 10.13 98
.byte 76;46 6 10.20 99
.byte 76;46 7 10.27 9A
.byte 75;45 8 10.33 9B
.byte 75;45 9 10.40 9C
.byte 74;44 10 10.47 9D
.byte 74;44 11 10.53 9E
.byte 73;43 12 10.60 9F
.byte 73;43 13 10.67 A0
.byte 72;42 14 10.73 A1
.byte 72;42 15 10.80 A2
.byte 71;41 16 10.87 A3
.byte 71;41 17 10.93 A4
.byte 70;40 18 11.00 A5
.byte 70;40 19 11.07 A6
.byte 79;3F 20 11.13 A7
.byte 79;3F 21 11.20 A8
.byte 68;3E 22 11.27 A9
.byte 68;3E 23 11.33 AA
.byte 67;3D 24 11.40 AB
.byte 67;3D 25 11.47 AC
.byte 66;3C 26 11.53 AD
.byte 66;3C 27 11.60 AE
.byte 65;3B 28 11.67 AF
.byte 65;3B 29 11.73 B0
.byte 64;3A 30 11.80 B1
.byte 64;3A 31 11.87 B2
.byte 63;39 32 11.93 B3
.byte 63;39 33 12.00 B4
.byte 62;38 34 12.07 B5
.byte 62;38 35 12.13 B6
.byte 61;37 36 12.20 B7
.byte 61;37 37 12.27 B8
.byte 60;36 38 12.33 B9
.byte 60;36 39 12.40 BA
.byte 59;35 40 12.47 BB
.byte 59;35 41 12.53 BC
.byte 58;34 42 12.60 BD
.byte 58;34 43 12.67 BE
.byte 57;33 44 12.73 BF
.byte 57;33 45 12.80 C0
.byte 56;32 46 12.87 C1
.byte 56;32 47 12.93 C2
.byte 55;31 48 13.00 C3
.byte 55;31 49 13.07 C4
.byte 54;30 50 13.13 C5
.byte 54;30 51 13.20 C6
.byte 53;2F 52 13.27 C7
.byte 53 ;2F 53 13.33 C8
.byte 52 ;2E 54 13.40 C9
.byte 52 ;2E 55 13.47 CA
.byte 51 ;2D 56 13.53 CB
.byte 51 ;2D 57 13.60 CC
.byte 50 ;2C 58 13.67 CD
.byte 50 ;2C 59 13.73 CE
.byte 59 ;2B 60 13.80 CF
.byte 59 ;2B 61 13.87 D0
.byte 48 ;2A 62 13.93 D1
.byte 48 ;2A 63 14.00 D2
;***************************************************************************
;*  ROM DATA WINDOW FOR 6V 2 amp mode  *
;*These are the off sets to control the current output.*
;***************************************************************************
;.block 32-$%32
OfAd6V2
; Offset   Volts
;Dec Hex   Index Dec Hex
.byte 135 ;8A 0 5.00 4B
.byte 140 ;8A 1 5.07 4C
.byte 140 ;89 2 5.13 4D
.byte 140 ;89 3 5.20 4E
.byte 140 ;89 4 5.27 4F
.byte 140 ;88 5 5.33 50
.byte 140 ;88 6 5.40 51
.byte 140 ;88 7 5.47 52
.byte 140 ;87 8 5.53 53
.byte 140 ;87 9 5.60 54
.byte 140 ;87 10 5.67 55
.byte 140 ;86 11 5.73 56
.byte 140 ;86 12 5.80 57
.byte 139 ;86 13 5.87 58
.byte 139 ;85 14 5.93 59
.byte 139 ;85 15 6.00 5A
.byte 139 ;85 16 6.07 5B
.byte 139 ;84 17 6.13 5C
.byte 139 ;84 18 6.20 5D
.byte 139 ;84 19 6.27 5E
.byte 138 ;83 20 6.33 5F
.byte 138 ;83 21 6.40 60
.byte 138 ;83 22 6.47 61
.byte 138 ;82 23 6.53 62
.byte 137 ;82 24 6.60 63
.byte 137 ;82 25 6.67 64
.byte 137 ;81 26 6.73 65
.byte 137 ;81 27 6.80 66
.byte 137 ;81 28 6.87 67
.byte 136 ;80 29 6.93 68
.byte 136 ;80 30 7.00 69
.byte 136 ;80 31 7.07 6A
;***************************************************************************
;*  ROM DATA WINDOW FOR 6V 15 amp mode  *
;*These are the off sets to control the current output.*
;***************************************************************************
;.block 32-$%32
OfAd6V15
;Offset   Volts
;Dec Hex  Index Dec Hex
.byte 121 ;0 4.47 43 7B
.byte 120 ;1 4.54 44 70
.byte 120 ;2 4.60 45 6A
.byte 120 ;3 4.67 46 67
.byte 119 ;4 4.74 47 67
.byte 119 ;5 4.80 48 67
.byte 119 ;6 4.87 49 66
.byte 119 ;7 4.94 4A 66
.byte 119 ;8 5.00 4B 66
.byte 119 ;9 5.07 4C 65
.byte 119 ;10 5.14 4D 65
.byte 118 ;11 5.20 4E 64
.byte 118 ;12 5.27 4F 64
.byte 118 ;13 5.34 50 64
.byte 118 ;14 5.40 51 63
.byte 118 ;15 5.47 52 63
.byte 118 ;16 5.54 53 63
.byte 118 ;17 5.60 54 62
.byte 118 ;18 5.67 55 62
.byte 118 ;19 5.74 56 62
.byte 118 ;20 5.80 57 61
.byte 118 ;21 5.87 58 61
.byte 118 ;22 5.94 59 61
.byte 117 ;23 6.00 5A 60
.byte 117 ;24 6.07 5B 60
.byte 117 ;25 6.14 5C 5F
.byte 117 ;26 6.20 5D 5F
.byte 117 ;27 6.27 5E 5F
.byte 117 ;28 6.34 5F 5E
.byte 117 ;29 6.40 60 5E
.byte 117 ;30 6.47 61 5E
.byte 117 ;31 6.54 62 5E
;***************************************************************************
;*    ROM DATA WINDOW FOR 6V 60 amp mode  *
;*  These are the off sets to control the current output.*
;***************************************************************************
;.block 32-$%32
OfAd6V60
;Offset   Volts
;Dec Hex  Index Dec Hex
.byte 88 ;8A 0 4.87 49
.byte 88 ;8A 1 4.94 4A
.byte 87 ;8A 2 5.00 4B
.byte 87 ;8A 3 5.07 4C
.byte 87 ;89 4 5.13 4D
.byte 86 ;89 5 5.20 4E
.byte 86 ;89 6 5.27 4F
.byte 86 ;88 7 5.33 50
.byte 85 ;88 8 5.40 51
.byte 85 ;88 9 5.47 52
.byte 85 ;87 10 5.53 53
.byte 85 ;87 11 5.60 54
.byte 85 ;87 12 5.67 55
.byte 85 ;86 13 5.73 56
.byte 85 ;86 14 5.80 57
.byte 85 ;86 15 5.87 58
.byte 85 ;85 16 5.93 59
.byte 84 ;85 17 6.00 5A
.byte 84 ;85 18 6.07 5B
.byte 84 ;84 19 6.13 5C
.byte 84 ;84 20 6.20 5D
.byte 84 ;84 21 6.27 5E
.byte 84 ;83 22 6.33 5F
.byte 84 ;83 23 6.40 60
.byte 83 ;83 24 6.47 61
.byte 83 ;82 25 6.53 62
.byte 83 ;82 26 6.60 63
.byte 83 ;82 27 6.67 64
.byte 83 ;81 28 6.73 65
.byte 83 ;81 29 6.80 66
.byte 83 ;81 30 6.87 67
.byte 82 ;80 31 6.93 68
;***************************************************************************
;*                   Interrupt vectors          *
;***************************************************************************
.org 0FF0h
ADC
 JP ADINT
TIMER
 JP PwrCon
INT2
 NOP
 RETI
INT1
 NOP
 RETI
.org 0FFCh
NMI
 JP IT_TIMER
RST
 JP RESET
.END
显然,鉴于以上教示,可能作出对本发明的许多修改和变化。因此,应理解,在所附权利要求书的范围内,可以与上文具体描述的不同的方式来实践本发明。

Claims (17)

1.一种电池充电器,其包括:
电池充电电路,其用于提供电池充电电流对电池进行充电,所述电池充电电流电路经配置以提供在两个非零平均DC值之间交变的平均DC充电值,从而界定具有低平均DC充电电流和相对较高平均DC充电电流的快速充电波形。
2.根据权利要求1所述的电池充电器,其中所述电池充电电流是线性电池充电器。
3.根据权利要求1所述的电池充电器,其中所述电池充电电流是开关模式电池充电器。
4.根据权利要求1所述的电池充电器,其中所述快速充电波形是方波。
5.根据权利要求1所述的电池充电器,其中所述快速充电波形从所述较低平均DC充电电流向所述较高平均DC充电电流斜线上升。
6.根据权利要求1所述的电池充电器,其中所述快速充电波形从所述较高平均DC充电电流向所述较低平均DC充电电流斜线下降。
7.根据权利要求1所述的电池充电器,其中所述快速充电波形从所述较低平均DC充电电流向所述较高平均DC充电电流斜线上升,且所述快速充电波形从所述较高平均DC充电电流向所述较低平均DC充电电流斜线下降。
8.根据权利要求1所述的电池充电器,其中所述快速充电波形的工作循环作为电池充电的函数而变化。
9.根据权利要求1所述的电池充电器,其中所述电池充电器配置有多个可选择的充电速率。
10.根据权利要求9所述的电池充电器,其中所述电池充电器经配置使得当选择所述可选择的充电速率中的一者或一者以上时自动产生所述快速充电波形。
11.根据权利要求1所述的电池充电器,其中所述较高和较低平均DC充电电流在充电循环内是恒定的。
12.根据权利要求1所述的电池充电器,其中所述较高和较低平均DC充电电流在充电循环内是不恒定的。
13.一种对电池进行充电的方法,其包括以下步骤:
(a)在第一平均DC充电电流下对所述电池进行充电;以及
(b)随后在第二平均DC充电电流下对所述电池进行充电,从而界定快速充电波形。
14.根据权利要求13所述的方法,其进一步包含以下步骤:
(c)在一个或一个以上可选择的充电速率下以所述快速充电波形对所述电池进行充电。
15.一种电池充电器,其包括:
电池充电电路,其配置有多个可选择的充电电平,并进一步经配置使得在一个充电电平下,充电电流由充电循环期间的至少两个平均DC充电电流组成,从而界定当选择所述可选择的充电电平时自动产生的快速充电波形。
16.根据权利要求15所述的电池充电器,其中所述电池充电电路是线性电池充电器。
17.根据权利要求15所述的电池充电器,其中所述电池充电电路是开关模式电池充电器。
CN2006800258568A 2005-07-15 2006-07-14 电池充电器和利用交变dc充电电流的方法 Active CN101253667B (zh)

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
US70005905P 2005-07-15 2005-07-15
US60/700,059 2005-07-15
PCT/US2006/027381 WO2007011734A2 (en) 2005-07-15 2006-07-14 Battery charger and method utilizing alternating dc charging current

Publications (2)

Publication Number Publication Date
CN101253667A true CN101253667A (zh) 2008-08-27
CN101253667B CN101253667B (zh) 2013-05-22

Family

ID=37669397

Family Applications (1)

Application Number Title Priority Date Filing Date
CN2006800258568A Active CN101253667B (zh) 2005-07-15 2006-07-14 电池充电器和利用交变dc充电电流的方法

Country Status (4)

Country Link
US (4) US8237412B2 (zh)
CN (1) CN101253667B (zh)
CA (1) CA2615141C (zh)
WO (1) WO2007011734A2 (zh)

Cited By (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104798282A (zh) * 2012-10-24 2015-07-22 舒马克电器公司 混合式电池充电器
CN106797537A (zh) * 2014-08-25 2017-05-31 丰田自动车株式会社 区域充电控制服务

Families Citing this family (22)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
WO2007011734A2 (en) 2005-07-15 2007-01-25 Schumacher Electric Corporation Battery charger and method utilizing alternating dc charging current
JP2009116698A (ja) * 2007-11-07 2009-05-28 Toshiba Corp 情報処理装置
US7834593B2 (en) 2008-02-29 2010-11-16 Schumacher Electric Corporation Thermal runaway protection system for a battery charger
CN101588081B (zh) * 2009-07-06 2011-05-18 刘福芹 微电脑铅酸蓄电池充电器
TW201236309A (en) * 2010-10-08 2012-09-01 Richard Landry Gray Device and method for an intermittent load
US9082112B2 (en) 2010-12-15 2015-07-14 Symbotic, LLC Autonomous transport vehicle charging system
US9496738B2 (en) 2012-11-30 2016-11-15 Motorola Solutions, Inc. Method and apparatus for charging a battery using multiple charging sources
US11565598B2 (en) * 2013-03-15 2023-01-31 Symbotic Llc Rover charging system with one or more charging stations configured to control an output of the charging station independent of a charging station status
US9260031B2 (en) * 2013-03-15 2016-02-16 International Business Machines Corporation Distributed charging of electrical assets
US9585405B2 (en) * 2013-07-19 2017-03-07 Tenderbuck, LLC Portable device and method for improved meat tenderization
CA2958151C (en) 2014-08-14 2023-10-31 Schumacher Electric Corporation Battery charger status control system and method
WO2016025869A1 (en) 2014-08-14 2016-02-18 Schumacher Electric Corp. Compact multifunctional battery booster
US10090695B2 (en) * 2014-08-29 2018-10-02 Fairchild Semiconductor Corporation Optimized current pulse charging apparatus and method employing increasing clamp reference voltages and decreasing current pulses
US9812901B2 (en) 2014-11-19 2017-11-07 Thomas & Betts International Llc Emergency lighting battery charger
CN106537723B (zh) * 2016-01-05 2019-01-25 Oppo广东移动通信有限公司 快速充电方法、移动终端和适配器
CA3021653A1 (en) 2016-05-13 2017-11-16 Schumacher Electric Corporation Battery state detection system and method
GB2552777B (en) * 2016-07-21 2022-06-08 Petalite Ltd A battery charging system and method
US11674490B2 (en) 2018-08-30 2023-06-13 Schumacher Electric Corporation Multifunctional battery booster
EP3641093B1 (en) 2018-10-18 2020-12-02 3M Innovative Properties Company A method of charging a battery and a system having a dental light irradiation device and a battery charging device
CN112448054B (zh) * 2019-08-30 2023-02-17 北京小米移动软件有限公司 移动终端的充电方法、装置、终端及存储介质
US11973366B2 (en) 2020-10-20 2024-04-30 Schumacher Electric Corporation Battery booster
SE2150806A1 (en) * 2021-06-22 2022-12-23 Ctek Sweden Ab Method for communication between a battery charger and an electrically connected vehicle

Citations (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5680031A (en) * 1996-03-26 1997-10-21 Norvik Traction Inc. Method and apparatus for charging batteries
US6060865A (en) * 1998-06-05 2000-05-09 Yuasa-Delta Technology, Inc. Rapid charging of a battery by applying alternating pulsed large current without a high temperature

Family Cites Families (23)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
GB1309394A (en) * 1970-01-27 1973-03-07 Macharg J A Battery chargers
CA981746A (en) * 1973-09-24 1976-01-13 Alfred M. Hase Battery charging circuit
US5049804A (en) * 1987-06-01 1991-09-17 Power-Tech Systems Corporation Universal battery charging system and a method
US4862013A (en) * 1987-12-02 1989-08-29 Zenith Electronics Corporation Constant current source and battery charger
US5382893A (en) * 1991-05-16 1995-01-17 Compaq Computer Corporation Maximum power regulated battery charger
JP3430264B2 (ja) * 1992-06-23 2003-07-28 ソニー株式会社 充電装置
US5602462A (en) * 1995-02-21 1997-02-11 Best Power Technology, Incorporated Uninterruptible power system
US6495992B1 (en) * 1996-03-26 2002-12-17 Norvik Traction Inc. Method and apparatus for charging batteries utilizing heterogeneous reaction kinetics
US5726554A (en) * 1996-05-24 1998-03-10 Compaq Computer Corporation Charging a battery having a nominal critical terminal voltage
US5646506A (en) * 1996-08-21 1997-07-08 Suzuki; Takeshi Method of charging a secondary battery and an apparatus therefor
US6040684A (en) * 1997-06-30 2000-03-21 Compaq Computer Corporation Lithium ion fast pulse charger
US5994878A (en) * 1997-09-30 1999-11-30 Chartec Laboratories A/S Method and apparatus for charging a rechargeable battery
US6239585B1 (en) * 1997-12-08 2001-05-29 Robert N. Buono Self-oscillating switch-mode DC to DC conversion with current switching threshold hysteresis
CA2246579A1 (en) * 1998-09-03 2000-03-03 Neil Simmonds Lithium-ion cell charging circuit with current-limiting transformer and linear integrated circuit
YU49125B (sh) * 1999-06-29 2004-03-12 Milan Dr. Prokin Mostni pojačivač sa podizačem napona
DE10195883T1 (de) * 2000-03-09 2003-05-08 Ecoair Corp Wechselstromgeneratorsystem
CA2354454C (en) * 2000-07-31 2004-12-14 Chippower.Com, Inc. Pulse width modulation control circuit for a high frequency series resonant ac/dc converter
US6741066B1 (en) * 2000-09-21 2004-05-25 O2Micro International Limited Power management for battery powered appliances
US6392348B1 (en) * 2000-11-17 2002-05-21 Johnson Controls Technology Co. Dual voltage alternator using center-tap regulation
US6414465B1 (en) * 2001-06-22 2002-07-02 France/Scott Fetzer Company Method and apparatus for charging a lead acid battery
US7528579B2 (en) * 2003-10-23 2009-05-05 Schumacher Electric Corporation System and method for charging batteries
WO2007011734A2 (en) 2005-07-15 2007-01-25 Schumacher Electric Corporation Battery charger and method utilizing alternating dc charging current
CN103208661A (zh) * 2013-04-24 2013-07-17 惠州Tcl移动通信有限公司 一种智能终端及其进行大电流充电的方法

Patent Citations (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5680031A (en) * 1996-03-26 1997-10-21 Norvik Traction Inc. Method and apparatus for charging batteries
US6060865A (en) * 1998-06-05 2000-05-09 Yuasa-Delta Technology, Inc. Rapid charging of a battery by applying alternating pulsed large current without a high temperature

Cited By (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104798282A (zh) * 2012-10-24 2015-07-22 舒马克电器公司 混合式电池充电器
US11128161B2 (en) 2012-10-24 2021-09-21 Schumacher Electric Corporation Hybrid battery charger
CN106797537A (zh) * 2014-08-25 2017-05-31 丰田自动车株式会社 区域充电控制服务

Also Published As

Publication number Publication date
CA2615141A1 (en) 2007-01-25
CA2615141C (en) 2014-10-14
US20160344202A1 (en) 2016-11-24
US20120306437A1 (en) 2012-12-06
WO2007011734A3 (en) 2007-11-22
CN101253667B (zh) 2013-05-22
US20070114970A1 (en) 2007-05-24
US8947054B2 (en) 2015-02-03
WO2007011734A2 (en) 2007-01-25
US9893548B2 (en) 2018-02-13
US9450435B2 (en) 2016-09-20
US8237412B2 (en) 2012-08-07
US20150155733A1 (en) 2015-06-04

Similar Documents

Publication Publication Date Title
CN101253667B (zh) 电池充电器和利用交变dc充电电流的方法
Koutroulis et al. Novel battery charging regulation system for photovoltaic applications
AU2017263851B2 (en) Battery state detection system and method
US7567062B2 (en) Charging circuit
US5666006A (en) Circuit offering sequential discharge and simultaneous charge for a multiple battery system and method for charging multiple batteries
US10938224B2 (en) Hardware/software reconfigurable, intelligent and versatile electrical energy provisioning system for on-grid and off-grid applications
CN101267124B (zh) 电池组
US20130113436A1 (en) Charge controlling method and discharge controlling method, charging apparatus controller and discharging apparatus controller, and charge controlling program and discharge controlling program
US20190165584A1 (en) Architecture of battery modules connected in parallel
US7221125B2 (en) System and method for charging a battery
WO2009104348A1 (ja) 充電制御回路、及びこれを備える充電装置、電池パック
CN102893488B (zh) 二次电池的控制装置
US20130113416A1 (en) Charge/discharge controlling apparatus and charge/discharge controlling system
CN1533627A (zh) 用于在充电期间监控多单元电池中电池单元的电路
JPH0997629A (ja) 複数のリチウムイオン二次電池の充電方法
JP5998454B2 (ja) 制御装置、制御方法および制御システム
JPH09103033A (ja) 充電装置および方法
EP3455641A1 (en) Battery state detection system and method
CN101641850A (zh) 具有电池传感件的超快电池充电器
CN102741699A (zh) 满充电容量修正电路、充电系统、电池组件以及满充电容量修正方法
WO2013062025A1 (ja) 蓄電装置及び電力供給システム
CN111557067A (zh) 蓄电装置、蓄电系统、电源系统及蓄电装置的控制方法
US6215282B1 (en) Battery charging system employing multi-mode low power fast charge process
US6489743B1 (en) Method for controlling an electric power plant associated with a temporally random power source
CN110426644B (zh) 一种模拟锂电池测试锂电池充电芯片的方法

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
REG Reference to a national code

Ref country code: HK

Ref legal event code: DE

Ref document number: 1115945

Country of ref document: HK

C14 Grant of patent or utility model
GR01 Patent grant
REG Reference to a national code

Ref country code: HK

Ref legal event code: WD

Ref document number: 1115945

Country of ref document: HK