[go: up one dir, main page]
More Web Proxy on the site http://driver.im/

CA2527068C - Apparatus and methods for multi-channel metering - Google Patents

Apparatus and methods for multi-channel metering Download PDF

Info

Publication number
CA2527068C
CA2527068C CA2527068A CA2527068A CA2527068C CA 2527068 C CA2527068 C CA 2527068C CA 2527068 A CA2527068 A CA 2527068A CA 2527068 A CA2527068 A CA 2527068A CA 2527068 C CA2527068 C CA 2527068C
Authority
CA
Canada
Prior art keywords
pic
operable
status
comm
communication
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.)
Expired - Fee Related
Application number
CA2527068A
Other languages
French (fr)
Other versions
CA2527068A1 (en
Inventor
Sayre A. Swarztrauber
Doron Shafrir
Siddharth Malik
Robert Hayward
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.)
Quadlogic Controls Corp
Original Assignee
Quadlogic Controls 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 Quadlogic Controls Corp filed Critical Quadlogic Controls Corp
Priority to CA2527068A priority Critical patent/CA2527068C/en
Priority to CA002567955A priority patent/CA2567955A1/en
Publication of CA2527068A1 publication Critical patent/CA2527068A1/en
Application granted granted Critical
Publication of CA2527068C publication Critical patent/CA2527068C/en
Expired - Fee Related legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Classifications

    • HELECTRICITY
    • H04ELECTRIC COMMUNICATION TECHNIQUE
    • H04BTRANSMISSION
    • H04B3/00Line transmission systems
    • H04B3/54Systems for transmission via power distribution lines
    • H04B3/546Combination of signalling, telemetering, protection
    • GPHYSICS
    • G01MEASURING; TESTING
    • G01RMEASURING ELECTRIC VARIABLES; MEASURING MAGNETIC VARIABLES
    • G01R21/00Arrangements for measuring electric power or power factor
    • G01R21/133Arrangements for measuring electric power or power factor by using digital technique
    • GPHYSICS
    • G01MEASURING; TESTING
    • G01RMEASURING ELECTRIC VARIABLES; MEASURING MAGNETIC VARIABLES
    • G01R22/00Arrangements for measuring time integral of electric power or current, e.g. electricity meters
    • G01R22/06Arrangements for measuring time integral of electric power or current, e.g. electricity meters by electronic methods
    • G01R22/061Details of electronic electricity meters
    • G01R22/063Details of electronic electricity meters related to remote communication
    • GPHYSICS
    • G01MEASURING; TESTING
    • G01RMEASURING ELECTRIC VARIABLES; MEASURING MAGNETIC VARIABLES
    • G01R22/00Arrangements for measuring time integral of electric power or current, e.g. electricity meters
    • G01R22/06Arrangements for measuring time integral of electric power or current, e.g. electricity meters by electronic methods
    • G01R22/061Details of electronic electricity meters
    • G01R22/066Arrangements for avoiding or indicating fraudulent use
    • HELECTRICITY
    • H04ELECTRIC COMMUNICATION TECHNIQUE
    • H04BTRANSMISSION
    • H04B2203/00Indexing scheme relating to line transmission systems
    • H04B2203/54Aspects of powerline communications not already covered by H04B3/54 and its subgroups
    • H04B2203/5429Applications for powerline communications
    • H04B2203/5433Remote metering
    • HELECTRICITY
    • H04ELECTRIC COMMUNICATION TECHNIQUE
    • H04BTRANSMISSION
    • H04B2203/00Indexing scheme relating to line transmission systems
    • H04B2203/54Aspects of powerline communications not already covered by H04B3/54 and its subgroups
    • H04B2203/5462Systems for power line communications
    • H04B2203/5466Systems for power line communications using three phases conductors
    • YGENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
    • Y02TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
    • Y02BCLIMATE CHANGE MITIGATION TECHNOLOGIES RELATED TO BUILDINGS, e.g. HOUSING, HOUSE APPLIANCES OR RELATED END-USER APPLICATIONS
    • Y02B90/00Enabling technologies or technologies with a potential or indirect contribution to GHG emissions mitigation
    • Y02B90/20Smart grids as enabling technology in buildings sector
    • YGENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
    • Y04INFORMATION OR COMMUNICATION TECHNOLOGIES HAVING AN IMPACT ON OTHER TECHNOLOGY AREAS
    • Y04SSYSTEMS INTEGRATING TECHNOLOGIES RELATED TO POWER NETWORK OPERATION, COMMUNICATION OR INFORMATION TECHNOLOGIES FOR IMPROVING THE ELECTRICAL POWER GENERATION, TRANSMISSION, DISTRIBUTION, MANAGEMENT OR USAGE, i.e. SMART GRIDS
    • Y04S20/00Management or operation of end-user stationary applications or the last stages of power distribution; Controlling, monitoring or operating thereof
    • Y04S20/30Smart metering, e.g. specially adapted for remote reading

Landscapes

  • Engineering & Computer Science (AREA)
  • Power Engineering (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • Computer Networks & Wireless Communication (AREA)
  • Signal Processing (AREA)
  • Information Transfer Systems (AREA)
  • Arrangements For Transmission Of Measured Signals (AREA)

Abstract

In one aspect, the invention comprises a device for measuring electricity usage of several circuits in an integrated environment, comprising: means for remote disconnection via power line communication; means for detection of electricity theft; means for tamper detection; and means for reverse voltage detection. In another aspect, the invention comprises an apparatus for multi-channel metering of electricity, comprising: (a) a meter head operable to measure electricity usage for a plurality of electricity consumer lines; (b) a transponder operable to transmit data received from the meter head via power line communication to a remotely located computer, and to transmit data received via power line communication from the remotely located computer to the meter head; and (c) a load control module operable to actuate connection and disconnection of each of a plurality of relays, each relay of the plurality of relays corresponding to one of the plurality of electricity consumer lines.

Description

APPARATUS AND METHODS FOR MULTI-CHANNEL METERING
Background and Summary One embodiment of the present invention comprises a metering device that is related to the Quadlogic ASIC-based family of meters (see U.S. Pat. No.
6,947,854, and U.S. Pat. App. Pub. No. 2006/0036388). Specifically, this embodiment (referred to herein for convenience as "Energy Guard") is a multi-channel meter that preferably is capable of providing much of the functionality of the above-mentioned family of meters, and further provides the improvements, features, and components listed below.
Used in at least one embodiment, a MiniCloset is a 24-channel metering device that can measure electric usage for up to 24 single-phase customers, 12 two-phase customer, or 8 three-phase customers. Preferably connected to the MiniCloset are one or more Load Control Modules (LCMs), discussed below.
Energy Guard preferably comprises a MiniCloset meter head module and two LCMs mounted into a steel box. Relays that allow for an electricity customer to be remotely disconnected and reconnected, along with current transformers, also are mounted into the box.
Upon installation, an electricity customer's electricity supply line is tapped off the main electric feeder, passed through the Energy Guard apparatus, and run directly to the customer's home. The construction and usage of the Energy Guard will be apparent to those skilled in the art upon review of the description below and related figures. Source it code is supplied in the attached Appendix.
Energy Guard meters preferably are operable to provide:
(A) Remote Disconnect/Reconnect: The meter supports full duplex (bi-directional) communication via power line communication ("PLC") and may be equipped with remotely operated relays (60 amp, 100 amp, or 200 amp) that allow for disconnect and reconnect of electricity users remotely.
(B) Theft Prevention: The system is designed with three specific features to prevent theft. First, an Energy Guard apparatus preferably is installed on a utility pole above the medium-tension lines, making it difficult for customers to reach and tamper with. Second, because there are no additional signal wires with the system (i.e., all communication is via the power line), any severed communication wires are immediately detectable. That is, if a communication wire is cut, service is cut, which is readily apparent. A third theft prevention feature is that the meter may be used to measure the transformer energy in order to validate the measured totals of individual clients.
Discrepancies can indicate theft of power.
(C) Tamper Detection: The Energy Guard preferably provides two modes of optical tamper detection. Each unit contains a light that reflects against a small mirror-like adhesive sticker. The absence of this reflective light indicates that the box has been opened. This detection will automatically disconnect all clients measured by that Energy Guard unit. In addition, if the Energy Guard enclosure is opened and ambient light enters, this will also automatically disconnect all clients measured by that Energy Guard unit. These two modes of tamper detection are continuously engaged and alternate multiple times per second for maximum security.
(D) Reverse Voltage Detection: In some cases, a utility company can disconnect power to an individual client and that client is able to obtain power via an alternative feed. If the utility were to reconnect power under these conditions, damage could occur to the metering equipment and/or the distribution system. Energy Guard preferably is able to detect this fault condition. The Energy Guard can detect any voltage that feeds back into the open disconnect through the lines that connect to the customers' premises.
If voltage is detected, the firmware of the Energy Guard will automatically prevent the reconnection.
(E) Pre-Payment: Pre-payment for energy can be done via phone, electronic transaction, or in person. The amount of kWh purchased is transmitted to the meter and stored in its memory. The meter will count down, showing how much energy is still available before reaching zero and disconnecting. As long as the customer continues to purchase energy, there will be no interruption in service, and the utility company will have a daily activity report.
(F) Load Limiting: As an alternative to disconnection for nonpayment or part of a pre-payment system, Energy Guard meters can allow the utility to remotely limit the power delivered to a set level, disconnecting when that load is exceeded. If the customer exceeds that load and is disconnected, the customer can reset a button on the optional remote display unit to restore load as long as the connected load is less than the pre-set limit. Alternatively, clients can call an electric utility service line by telephone to have the service restored. This feature allows electric utilities to provide electricity for critical systems even, for example, in the case of a non-paying customer.
(G) Monthly Consumption Limiting: Some customers benefit from subsidized rates and are given a maximum total consumption per month. The Energy Guard firmware is capable of shutting down power when a certain consumption level is reached.
However, this type of program is best implemented when advanced notification to customers is provided. This can be achieved either with a display in the home whereby a message or series of messages notifies customers that their rate of consumption is approaching the projected consumption for the month. Alternatively (or in conjunction) timed service interruptions can be programmed so that as the limit is approaching, power is disconnected for periods of time with longer and longer increments to notify the residents. These planned interruptions in service act as a warning to customers that their limit is nearing so that they have time to alter their consumption patterns.
(H) Meter Validation: The integrated module of the system preferably is removable. This permits easy laboratory re-validation of meter accuracy in the event of client billing disputes.
(I) Operational Benefits for Utility: The Energy Guard has extensive onboard event logs and diagnostic functions, providing field technicians with a wealth of data for commissioning and trouble shooting the electrical and communication systems.
Non billing parameters include: amps, volts, temperature, total harmonic distortion, frequency, instantaneous values of watts, vars and volt-amperes, V2 hrs, 12 hrs, power factor, and phase angle.
These features and others will be apparent to those skilled in the art after reviewing the attached descriptions, software code, and schematics.
In one aspect, the invention comprises a device for measuring electricity usage, comprising: means for remote disconnection via power line communication; means for detection of electricity theft; means for tamper detection; and means for reverse voltage detection.
In another aspect, the invention comprises an apparatus for multi-channel metering of electricity, comprising: (a) a meter head operable to measure electricity usage for a plurality of electricity consumer lines; (b) a transponder in communication with the meter head and operable to transmit data received from the meter head via power line communication to a remotely located computer, and to transmit data received via power line communication from the remotely located computer to the meter head;
and (c) a load control module in communication with the meter head and operable to actuate connection and disconnection of each of a plurality of relays, each relay of the plurality of relays corresponding to one of the plurality of electricity consumer lines.
In various embodiments: (1) the apparatus further comprises a tamper detector in communication with the meter head; (2) the tamper detector comprises a light and a reflective surface, and wherein the meter head is operable to instruct the load control module to disconnect all of the customer lines if the tamper detector provides notification that the light is not detected reflecting from the reflective surface; (3) the apparatus further comprises a box containing the meter head, the load control module, and the relays, and wherein the tamper detector comprises a detector of ambient light entering the box; (4) the apparatus further comprises a box containing the meter head, the load control module, and the relays, and wherein the box is installed on a utility pole;
(5) the apparatus further comprises means for comparing transformer energy to total energy used by the consumer lines; (6) the apparatus further comprises mans for detecting reverse voltage flow through the consumer lines; (7) the apparatus further comprises a computer readable memory in communication with the meter head and a counter in communication with the meter head, the counter corresponding to a customer line and operable to count down an amount of energy stored in the memory, and the meter head operable to send a disconnect signal to the load control module to disconnect the customer line when the counter reaches zero; (8) the apparatus further comprises a computer readable memory in communication with the meter head, the memory operable to store a load limit for a customer line, and the meter head operable to send a disconnect signal to the load control module to disconnect the customer line when the load limit is exceeded; (9) the apparatus further comprises a computer readable memory in communication with the meter head, the memory operable to store a usage limit for a customer line, and the meter head operable to send a disconnect signal to the load control module to disconnect the customer line when the usage limit is exceeded; and (10) the transponder is operable to communicate with the remotely located computer over medium tension power lines.
Brief Description of the Drawings FIG. 1 is a block/wiring diagram showing connection of preferred embodiments.
FIG. 2 is a block diagram showing physical configuration of preferred embodiments.
FIGS. 3A-3B are schematic diagrams of a preferred CPU board of a Scan Transponder and MiniCloset.
FIG. 4 is a schematic diagram of a preferred Scan Transponder power supply.
FIG. 5 is a schematic diagram of a preferred MiniCloset power supply.
FIG. 6 is a schematic diagram of a preferred circuit board for returning current transformer information to a MiniCloset meter head.
FIGS. 7A-7C are schematic diagrams of a preferred Load Control Module circuit board.
FIGS. 8A-8D are schematic diagrams of a preferred power supply board that provides for optical tamper detection.
FIGS. 9A-9C are schematic diagrams of a preferred Energy Guard connection board.
FIG. 10 is a schematic diagram for a control circuitry board operable to provide relay control.
Detailed Description of Preferred Embodiments In one embodiment, an Energy Guard metering apparatus comprises a MiniCloset The MiniCloset and Scan Transponder referred to herein are largely the same as described in U.S. Pat. No. 6,947,854. That is, although each has been improved over the One aspect of the invention comprises taking existing multichannel metering functionality found in the MiniCloset and adding remote connect and disconnect via PLC. Providing such additional functionality required adding new hardware and 20 FIG. 1 is a block diagram of connections of a preferred embodiment.
Medium voltage power lines A, B, C, and N (neutral) feed into Distribution Transformer 110.
Low voltage lines connect (via current transformers 120) Distribution Transformer 110 to Energy Guard unit 140. Energy Guard unit 140 monitors current transformers 120, and feeds single phase customer lines 1-24.
25 FIG. 2 is a block diagram of preferred structure of an Energy -Guard unit 140.
Scan Transponder 210 is the preferred data collector for the unit 140, may be located external to or inside the MiniCloset, and may be the main data collector for more than one MiniCloset at a time. The Scan Transponder 210 preferably: (a) verifies data (each communication preferably begins with clock and meter identity verification to ensure data integrity); (b) collects data (periodically it collects a data block from each meter unit, with each block containing previously collected meter readings, interval readings, and event logs); (c) stores data (preferably the data is stored in non-volatile memory for a specified period (e.g., 40 days)); and (d) reports data (either via PLC, telephone modem, RS-232 connection, or other means).
The slide plate 280 comprises a Minicloset meter head and a load control module 240 that provides the control signals to activate the relays. All of the electronics preferably is powered up by power supply 250. The back plate assembly 270 comprises multiple (e.g., 24) Current Transformers and relays - grouped, in this example, as three sets of 8 CTs and relays. Customer cables are wired through the CTs and connect to the circuit on customer premises 290. The remotely located Scan Transponder 210 accesses the Energy Guard meter head and bi-directionally communicates using power line carrier communication.
The signal flow shown in FIGS. 1 and 2 preferably is accomplished by implementing different software code modules operating concurrently to enable remote connect/disconnect ability in the Minicloset. These software modules, provided in the Appendix below, are:
Code Module Location Function lcm.def and Load Control Actuate connect and pic.def Module disconnect of relays.
pulse.c and Meter Head Establish communication with pulse.h LCM.
picend.def and Meter Head Provide control signals to picvars.def LCM.
pulselink.def and Meter Head Provides LCM with pulses to pulseoutm.c be used for connecting and disconnecting relays.
FIGS. 3-10 are schematics of preferred components, as described below. The preferred connect/disconnect relays are series K850 KG relays, but those skilled in the art will recognize that other relays may be used without departing from the scope of the invention.
Figure Schematic Detail 3 PCB 107D CPU board of the Scan Transponder and MiniCloset.
4 PCB 135C Power Supply for Scan Transponder.
PCB 144C Power Supply for MiniCloset.
6 PCB 146C This board brings back the Current Transformer information back to MiniCloset meter head.
7 PCB 160A Board for Load Control Module.
8 PCB 170 EG power supply board that adds capability for optical tamper detection.
9 PCB 171 EG Connection board. A board with traces to route the signal.
PCB 172 Control circuitry board for Relay control.
5 While certain specific embodiments of the invention have been described herein for illustrative purposes, the invention is not limited to the specific details, representative devices, and illustrative examples shown and described herein. Various modifications may be made without departing from the spirit or scope of the invention defined by the appended claims and their equivalents.

APPENDIX

LCM.DEF
; QLC LCM (Load Control Module) program for PIC 16C63A;
;
include 'CApictools\16c63a.inc' =
include 'CApictools\16c63.inc' =
; Configuration bits FUSES _BODEN_OFF ; Brown-out reset disabled FUSES _CP_OFF ; No code protect FUSES _PWRTE_OFF ; Disable power-up timer FUSES _WDT_ON ; Watchdog Timer Enabled FUSES _ RC _OSC ; Oscillator = RC
; Program Parameter Equates Software_type equ 7 ; Which PIC program is this?
; 7 = LCM program Software_version equ 2 ; Version #
LCM_base_addr equ 16 ; Address of first LCM
Ram_start equ 020h ; Beginning of available RAM
RESET_VECTOR equ 0 ; Location of reset vector ROM_start equ 008h ; first available program location Num_start_bits equ 12 ; Number of start bits ; Port definitions comm_port equ PORTA
data_out equ 3 data_in equ 4 clock_in equ 5 ctl_port equ PORTA
driver_enable equ 0 ; output bit to turn on the drivers Driver_enable_mask equ 1 driver_enable Initialization values for I/O ports init_TRISA equ 00110000b ; Data direction for port A
init_TRISB equ 000h ; B port data direction - all ports output init_TRISC equ 000h ; C port data direction - all out read_TRISC equ Olfh ; C port data direction for jumper read - 0-4 in Init_comm_port_value equ 1 data_out + Driver_enable_mask = bit 7 = 1: Port B pullups disabled , = bit 6 = 0: Int on falling edge , , bit 5 = 0: Timer 0 uses inst clock ; bit 4 =0: Timer 0 counts on rising edge bit 3 = 1: Prescaler used by WDT
, = bit 2,1,0 = 111:Prescaler divide by 128 , ; NOTE - interrupts and timer 0 are not used by this program ms_preset equ 700 ; Time set for millisecond delay =
, ; RAM locations ORG Ram_start Status_reg ds 4 ; status register ORG Status_reg Status_MSB ds 1 Clk_timeout_flag equ 7 ; Timeout waiting for comm clock edge bad_reset_flag equ 6 ; Non-POR, non-WDT reset encountered POR_flag equ 5 ; Power-on reset detected WDT_reset_flag equ 4 ; WDT reset, not from sleep Status_LSB ds 1 CPU_reset_flag equ 7 Need_param_refresh_flag equ 6 Parity_err_flag equ 5 Global_cmd_timer ds 1 Jumper_state ds 1 ; current state of input jumpers Parameter_reg ds 4 ; Communication parameters org Parameter_reg ds 1 , =
ds 2 =
ds 1 ; Fast communication variables ;
Comm_state ds 1 ; Stored state of fast comm uart Wstate ds 1 ; Stored state of fast comm word handler Comm_bit_count ds 1 ; Bit counter for fast comm Comm_buffer ds 1 ; fast comm word buffer Work_addr ds 1 ; Address read from jumpers Temp ds I ; temporary register Tpar ds 1 ; Transverse parity Word_count ds 1 ; Counter for sending and receiving 5-bit words Command ds 1 ; Command received over comm link Register_ID ds 1 ; Register specified in comm command PIC_addr ds 1 ; Address of this PIC chip Comm_buf ds 5 ; Communication buffer Input_hold ds I ; Hold register for comm rcv value Output_bit_reg ds 4 ; Hold register for output bit mask Flags ds 1 ; Program control flags Clk_wait_flag equ 7 ; indicates which clock edge we are waiting for Global_cmd_flag equ 6 ; Processing global command scratch ds 1 ; Work register Timeout_ctr ds 2 ; Counter for pulse duration Millisecs ds 1 ; Counter for pulse duration milliseconds Clk_timeout_ctr ds 2 ; counter for clock timeout NPR timer ds 2 ; counter for need parameter refresh =
ORG 0a0h ; Bank 1 RAM locations IF $ - 1 & 0100h error - RAM overflow ENDIF
=
ORG RESET_VECTOR
jmp start ; Jump to first program location = Start of program space =
ORG ROM_start =
= Initialization =
Start setb RPO ; point to upper register bank jnb NOT_POR,got_POR ; Power on reset, set flags clrb RPO ; point to RAM bank 0 jnb NOT_TO,WDT_reset ; Watchdog reset setb status_MSB.bad_reset_flag ; Indicate unknown reset condition jmp Do_initialize WDT_reset setb Status_MSB.WDT_reset_flag jmp do_initialize got_POR
clrb RPO ; point to RAM bank 0 mov Status_MSB,#1 POR_flag ; Set POR flag clr Status_LSB
Do_initialize mov FSR,#Ram_start+2 ; Point past status flags :c1r_loop clr INDF ; Clear RAM location inc FSR ; Increment pointer jz Init_state ; If zero, done mov W,FSR ; get pointer and W,#7fH ; look at 7 LSB's jnz :c1r_loop ; Not end of segment, continue add FSR,#20h ; Point to next segment jmp :c1r_loop ; Not last segment, continue Init_state setb Status_LSB.CPU_reset_flag ; Indicate CPU reset setb Status_LSB.Need_param_refresh_flag ; Indicate parameter refresh needed mov comm_port,#Init_comm_port_value ;
initialize comm port state mov Comm_state,#Edge_wait mov Comm_bit_count,#Num_start_bits ; Initialize fast comm state machine clr PORTB
clr PORTC
jmp Main_loop ; start running main program =
=
; Comm Receive routines Edge_wait ; Initialize Watchdog timer mov !OPTION,#option_reg_val ; Set option reg setb comm_port.data_out ; send a 1 dec Comm_bit_count ; decrement bit count jz See_edge_one ; if zero, looking for a 1 jb Input_hold.data_in,Set_edge_wait ; Looking for 0, reset bit count if imp Comm_ret ; done See_edge_one jnb Input_hold.data_in,Set_edge_wait ; looking for 1, reset if 0 mov Wstate,#Rcv_addr ; First word is address mov Tpar,#01fh ; Init parity imp Rcv_next_word Rcv_stop mov Comm_state,#Edge_wait mov Comm_bit_count,#Num_start_bits ; Preset state to wait for edge jnb Input_hold.data_in,Parity_error ; stop bit must be 1 jmp Cmd_exec ; Done, process received buffer Rcv_bits dc ; copy ...
snb Input_hold.data_in ; ... input bit ...
setc ... to carry rl Comm_buffer ; shift buffer imp Rcv_word_handler ; Check for complete word ;
; Comm Transmit routines Send_edge dec Comm_bit_count ; decrement bit count jz :One ; if zero, send a 1 clrb comm_port.data_out ; send a 0 imp Comm_ret :One setb comm_port.data_out ; send a 1 imp Do_xmit_word Send_bits rl Comm_buffer ; put xmit bit into carry jc :one clrb comm_port.data_out ; send a '0' imp :check :one setb comm_port.data_out ; send a '1' :check imp Xmit_word_handler =
= Comm receive word handler routines ;
Rcv_word_handler djnz Comm_bit_count,Comm_ret ; If word not complete, continue and Comm_buffer,#031h ; only 6 bits dc mov W, Comm_buffer ; get 5 MSBs of received word call parity_lookup xor W,Comm_buffer ; compare with received word jnz Parity_error rr Comm_buffer and Comm_buffer,#01fh ; extract 5-bit value xor Tpar,Comm_buffer ; calculate total parity mov PCLATH,#Rcv_addr<
mov W,Wstate jmp W ; Execute word handler routine Rcv_addr clrb Flags.Global_cmd_flag ; Clear global command flag mov W,Comm_buffer ; Get received address mov PIC_addr,W ; save it xor W,#1fh ; is it global command jnz See_if us ; No, check for address match setb Flags.Global_cmd_flag ; Set global command flag jmp Its_us ; process rest of command See if us mov !PORTC,#read_TRISC ; Switch C port bit 0-4 to input clrb ctl_port.driver_enable ; Disable output drivers, enable jumper read mov temp,#9 :loop djnz temp,:loop ; Wait at least 20 uSec mov W,/PORTC ; Get inverse of jumpers in W
mov Work_addr,W ; Save jumper value setb ctl_port.driver_enable ; Enable output drivers mov !PORTC,#init_TRISC ; Restore C port status mov Jumper_state,Work_addr ; Save jumper state and Work_addr,#03h ; Ignore all but 2 LSBs add Work_addr,#LCM_base_addr ; Add base offset cjne Work_addr,PIC_addr,Set_edge_wait Its_us mov Wstate,#Rcv_cmd ; point to next routine jmp Rcv_next_word Rcv_cmd mov Command,Comm_buffer ; save command jnb Command.4,Comm_get_fast ; Fast read command, skip Reg ID
mov Wstate,#Rcv_reg_ID ; point to next routine jmp Rcv_next_word Comm_get_fast mov Wstate,#Rcv_tpar ; point to next routine jmp Rcv_next_word Rcv_reg_ID
mov register_ID,Comm_buffer ; save register number mov Wstate,#Rcv_tpar ; point to next routine jnb Command.3,Rcv_next_word ; If no value, done mov word_count,#7 ; Init word count mov Wstate,#Rcv_value ; point to next routine jmp Rcv_next_word Rcv_value rl Comm_buffer rl Comm_buffer rl Comm_buffer ; Shift rcvd bits to MSBs mov Comm_bit_count,#5 ; shift 5 bits :shift_loop rl Comm_buffer rl Comm_buf+4 rl Comm_buf+3 rl Comm_buf+2 rl Comm_buf+1 rl Comm_buf ; Shift a bit from Comm_buf to comm_buf djnz Comm_bit_count,:shift_loop djnz word_count,Rcv_next_word ; any more words?
mov Wstate,#Rcv_tpar ; point to next routine jmp Rcv_next_word Rcv_tpar mov W,Tpar ; Get result of parity calculations jnz Parity_error ; If not 0, parity error jmp Set_rcv_stop ; set up to receive stop bit ;
Comm transmit word handler routines =
Xmit_word_handler djnz Comm_bit_count,Comm_ret ; If word not complete, continue Do_xmit_word mov PCLATH,#$<
mov W,Wstate jmp W ; Execute word handler routine Send_addr mov Wstate,#Send_cmd> ; point to next word routine mov W,PIC_addr ; get address jmp Send_next_word Send_cmd mov Wstate,#Send_value> ; point to send value jnb Command.4,Value_is_next ; Is it fast read command?
mov Wstate,#Send_reg_ID> ; point to next word routine Value_is_next mov W,Command ; get command jmp Send_next_word Send_reg_ID
mov Wstate,#Send_value> ; point to next word routine mov W,Register_ID ; get Register ID
jmp Send_next_word Send_value mov Wstate,#Next_value> ; point to next word routine mov Word_count,#7 ; value is 7 words long Next_value mov Comm_bit_count,#5 :loop rl comm_buf+4 rl comm_buf+3 rl Comm_buf+2 rl Comm_buf+1 rl Comm_buf rl Comm_buffer djnz Comm_bit_count,:loop mov W,Comm_buffer ; Get 5-bit word djnz word_count,Send_next_word ; if not last word, all set mov Wstate,#Send_Tpar> ; send parity next mov W,Comm_buffer jmp Send_next_word Send_Tpar mov Wstate,#Send_stop ; point to next word routine mov W,Tpar ; get transverse parity jmp Send_next_word Send_stop jmp Set_edge_wait ; Go back to receive mode =
=
; Process received buffer org 100h Cmd_exec Process_cmd cjbe Command,#7h,Fast_register_read ; is it fast read?
cje Command,#10h,read_register ; is it read register command?
cje Command,#18h,write_register ; is it write register?
cje Command,#19h,reset_status_bits ; is it reset status?
jmp Cmd_process_done Fast_register_read mov register_ID,command ; Register number is same as command code Read_register mov W,#27 mov W,register_ID-W ; Get index of register to read jnc Cmd_process_done ; if negative, not a valid register mov Temp,W ; save index mov PCLATH,#$< ; set up High-order PC bits mov W,Temp ; get index jmp PC+W
jmp cpy_output_reg jmp cpy_reg_28 jmp cpy_reg_29 jmp cpy_reg_30 Cpy_reg_31 ; Reg 31 = Status register mov Comm_buf,Status_reg mov Comm_buf+1,Status_reg+1 mov Comm_buf+2,Status_reg+2 mov Comm_buf+3,Status_reg+3 jmp Setup_reply Cpy_reg_30 ; Reg 30 = Serial number call semo mov comm_buf+3,W
call semo+1 mov comm_buf+2,W
call serno+2 mov comm_buf+1,W
call serno+3 mov comm_buf,W
jmp Setup_reply Cpy_reg_29 ; Reg 29 = Software type and version mov Comm_buf,#Software_type mov Comm_buf+1,#Software_version mov Comm_buf+2,#0 mov Comm_buf+3,#0 ; Send Software type and version jmp Setup_reply Cpy_reg_28 ; Reg 28 = Parameter reg mov Comm_buf,Parameter_reg mov Comm_buf+1,Parameter_reg+1 mov Comm_buf+2,Parameter_reg+2 mov Comm_buf+3,Parameter_reg+3 jmp Setup_reply Cpy_output_reg ; Reg 27 = Output state mov Comm_buf,Output_bit_reg mov Comm_buf+1,Output_bit_reg+1 mov Comm_buf+2,Output_bit_reg+2 mov Comm_buf+3,Output_bit_reg+3 jmp Setup_reply Write_register mov Comm_bit_count,#5 ; need to shift buffer by 5 bits :loop rl comm buf+4 rl comm_buf+3 rl comm_buf+2 rl comm_buf+1 rl comm_buf djnz Comm_bit_count,:loop cjne Register_ID,#28,See_write_output_reg ; Not reg 28, see if output reg mov Parameter_reg,Comm_buf mov Parameter_reg+1,Comm_buf+1 mov Parameter_reg+2,Comm_buf+2 mov Parameter_reg+3,Comm_buf+3 ; Copy received data to reg clrb Status_LSB.Need_param_refresh_flag ; Reset need parameter refresh flag jmp Cpy_reg_28 ; send contents back in reply See_write_output_reg cjne Register_ID,#27,Cmd_process_done ; if not output reg, ignore mov Output_bit_reg,Comm_buf mov Output_bit_reg+1,Comm_buf+1 mov Output_bit_reg+2,Comm_buf+2 mov Output_bit_reg+3,Comm_buf+3 ; Copy received data to reg call Update_outputs jmp Cpy_output_reg ; send contents back in reply Reset_status_bits mov Comm_bit_count,#5 ; need to shift buffer by 5 bits :loop rl comm_buf+4 rl comm_buf+3 rl comm_buf+2 rl comm_buf+1 rl comm_buf djnz Comm_bit_count,:loop mov W,/Comm_buf+1 ; get byte and Status_reg+1,W ; Clear bits mov W,/Comm_buf ; get MSB
and Status_reg,W ; Clear bits mov Register_ID,#31 ; indicate status reg in reply jmp Cpy_reg_31 Setup_reply jb Flags.Global_cmd_flag,Set_edge_wait ; If it was global, don't reply mov W,Status_LSB ; Get status LSB
mov Comm_buf+4,W ; preset stored flags and W,#01fh ; Turn off 3 MSBs or W,Status_MSB ; Combine 5 LSbs with Status_MSB
sz setb Comm_buf+4.7 ; If any other flag bits set, indicate in MSB
, mov Tpar,#1fh ; Initialize parity word mov Comm_state,#Send_edge ; Go to send_edge state mov Wstate,#Send_addr ; Point to next routine mov Comm_bit_count,#Num_start_bits ; Init number of bits jmp Comm_ret Cmd_process_done jmp Set_edge_wait ; No reply needed, done ;
; Exit routines for comm , Parity_error setb status_LSB.Parity_err_flag ; Indicate parity error Set_edge_wait mov Comm_state,#Edge_wait ; Go to edge wait state mov Comm_bit_count,#Num_start_bits ; Init number of bits jmp Comm_ret Set_send_reply mov Comm_state,#Send_edge ; Go to send edge state mov Comm_bit_count,#Num_start_bits jmp Comm_ret Rcv_next_word mov Comm_state,#Rcv_bits ; set up to receive 6-bit word mov Comm_bit_count,#6 jmp Comm_ret Send_next_word and W,#01fh ; only 5 bits xor Tpar,W ; update parity calculation call parity_lookup mov Comm_buffer,W ; Save word with parity (6 bits) rl Comm_buffer rl Comm_buffer ; move to MSbs mov Comm_state,#Send_bits ; set up to send 6-bit word mov Comm_bit_count,#6 jmp Comm_ret Set_rcv_stop mov Comm_state,#Rcv_stop ; point to next routine jmp Comm_ret ORG 200h Serno retw 05ah,092h,05fh,000h , = retw Offh,Offh,Offh,Offh , ds 4 ret =
=
= Returns 6-bit value corresponding to passed 5-bit value with odd parity ;
parity_loolwp mov Temp,W ; Save index mov PCLATH,#:table< ; Set up high-order bits mov W,Temp ; get index imP Pc w :table retw 1,2,4,7,8,11,13,14,16,19,21,22,25,26,28,31,32,35,37,38,41,42,44,47,49,50,52,55, 56,59,61 ,62 Sets output bits according to received data = Comm_buf = Pulse duration in milliseconds ; 0: Continuous output (infinite duration) 1-255: Set output state for specified duration = After duration is over, turn all outputs off =
= Comm_buf+1[3] = Bit map of output states - MSB first ; bits 23-18: Unused bits 17-0: Outputs 18-1 =
Update_outputs mov W,Comm_buf+3 ; get lsbs and W,#03h ; only need 2 bits mov Temp,W
add Temp,W ; Shift into bits 1 and 2 (X1 and X2) mov W,PORTA ; Get present status of port A pins and W,#0f9h ; clear output control bits or W,Temp ; Set desired output state mov PORTA,W ; output new value rr comm_buf+1 rr comm_buf+2 rr comm buf+3 ff COMM_bUf-F 1 ff comm_buf+2 rr comm_buf+3 ; shift buffer left 2 bits mov PORTB,comm_buf+2 mov PORTC,comm_buf+3 mov !PORTA,#init_TRISA
mov !PORTB,#init_TRISB
mov !PORTC,#init_TRISC
mov Millisecs,Comm_buf ; first byte is pulse duration jz done_output_set ms_loop mov Timeout_ctr,#ms_preset<
mov Timeout_ctr+1,#ms_preset>
:loop djnz Timeout_ctr+1,:loop djnz Timeout_ctr,:loop djnz Millisecs,ms_loop ; delay for pulse duration and PORTA,#0f9h ; turn off X1 and X2 clr PORTB
clr PORTC ; turn off other outputs done_output_set ret ;
Main Program start =
Main_loop mov !PORTA,#Init_TRISA ; Initialize port A direction mov !PORTB,#Init_TRISB ; Initialize port B direction mov !PORTC,#Init_TRISC ; Init port C direction mov Clk_timeout_ctr,#12 ; preset ...
clr Clk_timeout_ctr+1 ; ... clock timeout counter clrb Flags.Clk_wait_flag ; Indicate waiting for clock low Clkwait_loop djnz scratch,Clk_cont clr WDT ; Reset watchdog djnz Clk_timeout_ctr+1,Clk_cont djnz Clk_timeout_ctr,Clk_cont jb Status_MSB.POR_flag,got_POR ; Ignore clock timeout until POR flag cleared setb Status_MSB.Clk_timeout_flag ; Indicate timeout on comm clock jmp Clk_cont jb Comm_port.clock_in,:high ; clock high :low jb Flags.Clk_wait_flag,Clkwait_loop mov Input_hold,Comm_port ; Save Data port value setb Flags.Clk_wait_flag ; Indicate waiting for clock high jmp Clkwait_loop :high jnb Flags.Clk_wait_flag,Clkwait_loop djnz NPR_timer+1,:cont ; Dec LSB of need parm timer djnz NPR_timer,:cont ; Dec MSB
setb Status_LSB.Need_param_refresh_flag ; set flag every 64k clocks :cont mov PCLATH,#0 ; Set up high-order bits for routines in page 0 mov W,Comm_state ; get vector jmp W ; Execute comm state machine Comm_ret jmp Main_loop PIC.DEF
/*
include file for serial communication with PIC chips *1 #pragma switch(ALL,FREQ) switch (PIC_serial_status) case sending_bits:
case sending_st5_bits:
#ifdef VATEST
out_bit_value = (PICxmitBuf. bits.bufLong[0] & 0x80000000) != 0; /* out bit value =
MSB */
PICxmitButbits.bufLong[0] = PICxmitBuf. bits.bufLong[0] 1;
if (PICxmitBuf. bits.bufLong[1] & 0x80000000) PICxmitBufbits.bufLong[0]++;
PICxmitBufbits.bufLong[1] = PICxmitBuf. bits.bufLong[1] 1;
if (PICxmitBuf. bits.bufLong[2] & 0x80000000) PICxmitBuf.bits.bufLong[1]++;
PICxmitButbits.bufLong[2] = PICxmitBuf. bits.bufLong[2] 1; /* Shift 96-bit buffer */
#else out_bit_value = 0;
shift_LSB_ptr = &PICxmitBuf. bits.bufByte[12]; /* point past least significant word of 96-bit register */
asm(" MOVE.L _shift_LSB_ptr,A0", /* Get pointer to buffer, clear carry */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* 96 bits have been shifted, MSB is in carry */
" ROXL.W _out_bit_value" /* Put MSB in out_bit_value */
);
#endif break;
case do_send_cmd:
bit _count = NUM_START_BITS-1;
PIC_serial_status = sending_start;
out_bit_value = 0;
break;
case do_PIC_start :
bit_count = 3 * BITS_PER_SEC;
out_bit_value = 1;
PIC_serial_status = sending_PIC_start;
break;
case sending_start:
out_bit_value = 0;
break;
case sending_stop:
case sending_start_l:
out_bit_value = 1;
break;
default:
out_bit_value = 1;
if (out_bit_value) fs1004.io.pulseOut2Off = 1;
else fs1004.io.pulseOut2Off = 0; /* Send bit out */
in_bit_value = fs1004.io.pulseIn1State; /* Get rcvd bit value */
fs1004.io.pulseOut1Off = 1; /* Send clock rising edge */
switch (PIC_serial_status) case waiting_for_start:
if (in_bit_value == 0) zero_count++;
else if (zero_count == (NUM_START_BITS-1)) PIC_serial_status = rcving_bits;
bit_count = PICrcyBufbitCount + 1;
else zero_count = 0;
break;
case rcving_bits:
#i fdef VATEST
PICrcyButbits.bufLong[0] = PICrcyBufbits.bufLong[0] 1;
if (PICrcyBufbits.bufLong[1] & 0x80000000) PICrcyBufbits.bufLong[0]++;
PICrcyBufbits.bufLong[1] = PICrcyBufbits.bufLong[1] 1;
if (PICrcyButbits.bufLong[2] & 0x80000000) PICrcyBuf. bits.bufLong[1]++;
PICrcyBufbits.bufLong[2] = (PICrcyBuf. bits.bufLong[2] << 1) +
in_bit_value;
#else shift_LSB_pft = &PICrcyBufbits.bufByte(12]; /*
point past least significant word of 96-bit register */
asm(" MOVE.L _shift_LSB_pft,A0", /* Get pointer to buffer, clear carry */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
, " ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)", /* rotate left and decrement pointer */
" ROXL.W -(A0)" /* 96 bits have been shifted, LSb is unknown */
);
PICrcyBuf.bits.bufByte[111 =
(PICrcyBufbits.bufByte[11] & Oxfe) I in_bit_value; /* add in received bit */
#endif break;
default:
{

if (--bit_count <= 0) {
switch (PIC_serial_status) {
case rcving_bits:
PIC_serial_status = rcving_stop;
bit_count = 1;
break;
case sending_bits:
PIC_serial_status = sending_stop;
bit_count = 1;
break;
case sending_stop:
if (PICxmitBuf.PIC_addr == GLOBAL_PIC_ADDR) PIC_serial_status = idle;
else {
PIC_serial_status = waitingfor_start;
bit_count = PIC_wait_limit;
zero_count = 0;
}
break;
case sending_PIC_start:
PIC_serial_status = idle;
break;
case sending_start:
PIC_serial_status = sending_start_1;
bit_count = 1;
break;
case sending_start_l:
PIC_serial_status = sending_bits;
bit_count = PICxmitBuf.bitCount;
break;
case waiting_for_start:
PICrcvfiufflags 1= rcv_timeout_flagIrcv_data_ready_flag;
PIC_serial_status = idle;
break;
case rcving_stop:
if (in_bit_value == 0) PICrorBuf.flags1= rcv_bad_length_flag;
PIC_serial_status = idle;
PICrcvfiutflags1= rcv_data_ready_flag;
bit_count = 1;
break;
default:
PIC_serial_status = idle;
#pragma switch(ALL,NOFREQ) PULSE.0 #include "mtrlink.der /* #include "flash.def' */
#define PSTRU_DEFINED
#include "pulselink.der #include "pulse.h"
#include "ufloat.h"
#include "log.h"
#include "alarm.h"
#include "copymem.h"
#include "plcctrl.h"
#include <stdio.h>
#ifdef fakeMC5 #undef NUMPH
#define NUMPH 24 #endif /* define WDT flags for the PIC communication routine */
#pragma region ("ram=WDTFlags") short int WDTpulseSec ;
#pragma region ("ram=ram") #pragma region ("data=secondBack") void (*pulseSecondp)(void)=pulseSecond;
#pragma region ("data=data") #ifndef IS_MC5 #pragma region ("data=everySubsecond") #ifdef IS_RSM
void (*pulseSubsecp)(void)=pulseSubsecond ;
#else void (*pulseSubsecp)(void)=pulseService;
#endif #pragma region ("data=data") #endif #pragma region ("data=powerUp") void (*pulseStartupp)(void)=pulseStartup ;
#pragma region ("data=data") #pragma region ("data=dayBack") , void (*pulseDayp)(void)=pulseDay ;
#pragma region ("data=data") /* clear out PIC */
void pulseColdstart() int i ;
for (i=0; i<num_PICs; i-H-) if (PIC_statuslitsoftware_type == 3) {
PIC_statuslitclear_pulse_regs = TRUE;
PIC_statuslitget_status = TRUE;

clear state = SEND_GLOBAL_CLR;

void pulseStartup(void) int i;
#ifndef IS_RSM
int work_PIC_addr;
#endif #ifdef IS_MC5 int work_num_pulses;
#endif #ifdef VATEST
/* test !!!!! */
temp_command = SYSTEM_CONTROL;
temp_reg_ID = 0;
temp_command_data = READ_ENCODER_ID;
temp_flags = rcv_data_ready_flag;
#endif for (i=0;(!dont_clear_PIC_stats) && (i<(2*NUMPH));i++) pulseDatanerror_cnt = 0;
pulseData[i].ID_field[0]=0;
pulseData[i]seading = 0;
) for (i=0; i<MAX_PICS; i++) PIC_status[i].PIC_addr = 0;
hold_num_pulse_ctrs = releaseCodep->option.numPulseCounters;
if (hold_num_pulse_ctrs > NUMPH) num_pulse_ctrs = NUMPH;
else num_pulse_ctrs = hold_num_pulse_ctrs;
num_PICs = 1;
#ifdef IS_MC5 PIC_status[0].PIC_addr = MC5_MUX_PIC_ADDR; /* If MC5, add PDM PIC(s) to PIC
table */
if (int_configltmessg.configLTM[PULSE1].accum) work_num_pulses = num_pulse_ctrs;
work_PIC_addr =0;
while (work_num_pulses > 0) PIC_status[num_PICs++].PIC_addr = work_PIC_addr++; /* Pulse counters for Q13 */
work_num_pulses -= 4;
if (int_configltmessg.configLTM[PULSEnaccum) work_num_pulses = num_pulse_ctrs;
work_PIC_addr = 6;
while (work_num_pulses > 0) {
PIC_status[num_PICs++1.PIC_addr = work_PIC_addr++; /* Pulse counters for Q14 */
work_num_pulses -=4;
num_LCMs = releaseCodep->option.LCM_flags & 0x03;
work_PIC_addr = LCM_BASE_ADDR;
for (i=0;i<num_LCMs;i+-F) PIC_status[num_PICs++1.PIC_addr = work_PIC_addr++; /* LCM's */

#else #ifdef IS_ST5 PIC_status[0].PIC_addr = ST5_MUX_PIC_ADDR; /* If ST5, add mux to PIC table */
ATM_work = releaseCodep->option.couplers_mask;
work_PIC_addr = ATM_BASE_ADDR;
for (i=0;i<4;i++) {
if ((ATM_work & 0x08) != 0) /* Bit is set in mask, add ATM PIC to table */
PIC_status[num_PICs++1.PIC_addr = work_PIC_addr;

work_PIC_addr++;
ATM_work = ATM_work 1;
#else if (num_pulse_ctrs == 0) num_PICs =0;
#endif #endif for (i=0; i<MAX_PICS; i++) /* Build PIC table */
PIC_statusgget_serno = TRUE;
PIC_status[i].get_version = TRUE;
PIC_status[aget_status = FALSE;
PIC_statusnreset_status = FALSE;
PIC_statusnupdate_parameter = FALSE;
if (!dont_clear_PIC_stats) PIC_statusfil.PIC_reset_count = 0;
PIC_status[i].comm_error_count = 0;
PIC_status[i].PIC_data_err_count = 0;
PIC_status[i].software_type =0;
PIC_statusnsoftware_version =0;
PIC_status[i].serial_number = 0;
PIC_status[i].curr_pulse_reg = 0;
#ifdef IS_MC5 if (PIC_status[i].PIC_addr >= ST5_MUX_PIC_ADDR) PIC_status[i] .reply_wait_limit = DIRECT_PIC_WAIT_LIMIT;
else PIC_statuslitreply_wait_limit = BUFEL.RED_PIC_WAIT_LIMIT;
#else PIC_status[i].reply_wait_limit = DIRECT_PIC_WAIT_LIMIT;
#endif if (P1C_status[i].PIC_addr <= MAX_PULSE_PIC_ADDR) PIC_status[i].num_pulse_regs = PULSES_PER_PIC;
else PIC_status[il.num_pulse_regs = 0;
current_PIC_index =0;
rcv_PIC_index =0;
if (dont_clear_PIC_stats) dont_clear_PIC_stats = FALSE; /* Clear flag */
else PIC_bad_addr_count = 0;
PICrcyBufflags =0;
PIC_serial_status = do_PIC_start;
PIC_clk_state = clk_low; /* Initialize serial comm variables */
i ..
}
clear_state = NO_GLOBAL_SEND;
pulseOutMode = releaseCode.option.picMode ; /* for compatibility with old code */
if (startup.coldStart) {
pulseColdstart() ;
) const unsigned char parity6[32] =
{1,2,4,7,8,11,13,14,16,19,21,22,25,26,28,31,32,35,37,38,41,42,44,47,49,50,52,55 ,56,59,61,62);
void pulseDay() ( dont_clear_PIC_stats = TRUE; /* Tell pulseStartup not to clear error counts */
rebuild_timer = REBUILD_DELAY; /* Set up for delayed table rebuild */

void pulseSecond() {
#ifndef IS_ST5 pulseService();
#endif if (Comm_background_flags.do_rebuild) pulseStartup();
Comm_background_flags.do_rebuild = FALSE;

if (Comm_background_flags.do_alarm) {
putAlarm(&PIC_alarm,4);
Comm_background_flags.do_alann = FALSE;

/* set_PLC_relays function *1 /* Called from PLC routines to request update of */
/* PLC port multiplexer PIC chip on 5T5 power board */
#ifdef IS_ST5 void set_PLC_relays(int xmitRelay,int rcvRelay) while (MUX_control.active_flaglIMUX_control.request_flag) ccwait();
MUX_control.xmit_mask = xmitRelay;
MUX_controlscv_mask = rcvRelay;
MUX_control.done_flag = FALSE;
MUX_controlsequest_flag = TRUE;
if ((MUX_control.xmit_mask != MUX_controllast_xmit_mask) II
(MUX_control.rcv_mask != MUX_control.last_rcv_mask)) while OMUX_control.done_flag &&
!(MUX_control.active_flag && (PIC_serial_status == rcving_bits)) ) ccwait();
I
#endif void pulseService(void) {
BOOLEAN need_pulse_read, copy_rcvd_data, rev_buf err;
#ifdef IS_MC5 BOOLEAN
got_ver_3, got_ver_3_3;
int I;
unsigned char *work_char_ptr;
unsigned long work_bit_mask;
#endif int work_pulse_index;
phaccum accumXfer;
int i ;
if (num_PICs == 0) PIC_serial_status = idle;
if (PIC_serial_status == idle) if (!WDTpulseSec) WDTpulseSec=1; /*Tell WDT controller that we are OK*/
if (hold_num_pulse_ctrs != releaseCodep->option.numPulseCounters) /* hdwr -n has changed */
dont_clear_PIC_stats = FALSE;
rebuild_timer = 1; /* Force immediate table rebuild */
if ((PIC_serial_status = idle) &&
(rebuild_timer != 0) &&
(--rebuild_timer == 0)) Comm_background_flags.do_rebuild = TRUE;

else if ((PIC_serial_status == idle) &&
(num_PICs != 0) &&
(pulseOutMode != PIC_MC_SERIAL) &&
(!Comm_background_flags.do_rebuild)) /* Serial processing enabled? */
if (PICrcyBuf.flags & rcv_data_ready_flag) /* Process received message */
PICro/Buf. flags &= -rcv_data_ready_flag;
rcv_buf err = !decode_rcv_buffer();
if ((PIC_comm_mon.control_flags & RCV_DATA_RDY) =0) PIC_comm_monscv_buf = PICrcyBuf;
PIC_comm_mon.control_flags1= RCV_DATA_RDY;
if ((ext_comm.control_flags & CPY_RCV_DATA) != 0) ext_commscv_buf = PICrcyBuf;
ext_comm.control_flags &= -CPY_RCV_DATA;
ext_comm.control_flags 1= RCV_DATA_RDY;
#ifdefIS_ST5 if (ATM_control.active_flag) ATM_controlsesult_flags = PICrcyBufflags;
if (rcv_buf err) if (ATM_control.state != WAIT_ALIGN) {
ATM_controkerror_flag = TRUE;
ATM_control.active_flag = FALSE;
ATM_control.done_flag = TRUE;
else switch (ATM_control.state) case DO_PRESET:
ATM_control.xmit_level = PICrcyBulcommand_data 24;
ATM_control.coupler_level = (PICrcyBuf.command_data 16) & OxOff;
ATM_control.active_flag = FALSE;

break;
case SET ALIGN:
ATM_control.state = WAIT_ALIGN;
break;
case WAIT_ALIGN:
ATM_control.optimum_cap_code = PICrevriutcommand_data &
ATM_RC_CAP_MASK;
ATM_control.optimum_reading = PICro/Buf.command_data >> 16;
ATM_control.result_flags 1= (PICrcv13uf.command_data & Oxe000);
/* Copy flags from reply */
if ((ATM_controlsesult_flags & Oxc000) != 0) /* Analog levels out of range */
ATM_control.error_flag = TRUE;

if (ATM_control.optimum_reading < ATM_MIN_READING) ATM_controlsesult_flags 1= Ox1000; /* Indicate reading too low */
ATM_control.error_flag = TRUE;

ATM_control.active_flag = FALSE;
break;
case DO_PLC_SET:
case DO_ATM_DISCONNECT:
ATM_control.active_flag = FALSE;
break;
default:
ATM_control.active_flag = FALSE;
ATM_control.error_flag = TRUE;
break;
if (!ATM_control.active_flag) ATM_control.done_flag = TRUE;
if (MUX_control.active_flag) MUX_control.result_flags = PICrcyBuf. flags;
if (rcv_buf err) MUX_control.error_flag = TRUE;
MUX_control.last_xmit_mask =0;
MUX_control.last_rcv_mask =0;

else MUX_control.last_xmit_mask = PICro/Buf.command_data & Oxff;
MUX_control.last_rcv_mask = (PICro/Buf.command_data >> 8) & Oxff;

MUX_control.active_flag = FALSE;
MUX_control.done_flag = TRUE;

#endif if (rcv_buf err) #ifdef IS_ST5 if (!ATM_control.active_flag (ATM_control.state != WAIT_ALIGN)) #endif last_comm_err_flag = PICrcyBuf. flags;
copymem(sizeof (PICbitBuf), (char *) (&HoldrcyBuf), (char *) (&PICro/Buf));
if ((PICrcyBuf. flags & rcv_bad_addr_flag) != 0) { /* past end of valid PICs, address error */
PIC_bad_addr_count++;
set_PIC_alarm(PIC_adderr_O,PICro/Buf.PIC_addr, (PICxmitBuf.PIC_addr 8)+PICxmitBuf.command);

else ( /* PIC address was valid, but comm failed */
PIC_status[rcv_PIC_index].comm_error_count++;
if (PIC_status[rcv_PIC_indextcomm_error_count > 2) set_PIC_alarm(PIC_comerr_O,PIC_status[rcv_PIC_indexl.PIC_addr, PICrcyBufflags);

/* Lost contact with PIC, read serial number and software version */
PIC_status[rcv_PIC_index] .get_serno = TRUE;
PIC_status[rcv_PIC_index] .get_version = TRUE;

else /* Valid message received */
if ((PICrcyBuf.command == READ_REGISTER) && (PICro/Bufseg_ID ==
STATUS_REG)) , process_status_bits();
}
else if (PICrcyBuf.command == SYSTEM_CONTROL) {
if (PICrcyBufreg_ID == STATUS_REG) { /* Response frome reset status bits cmd */
PIC_status[rcv_PIC_index] .reset_status = FALSE;
process_status_bits();
I
else if ( (PIC_status[rcv_PIC_index].software_type == 4) &&
((PIC_status[rcv_PIC_index].last_cmd_data & Oxffff0000) ==
READ_ENCODER_ID) ) { /* response from encoder read ID comd */
work_pulse_index = (PICrcyBuf.PIC_addr * PULSES_PER_PIC) +
PICrcyBuf.reg_ID;
i = (PIC_status[rcv_PIC_index] .last_cmd_data 8z Ox0000ff00) 8;
work_char_ptr = (unsigned char *) &PICrcyBuf.command_data;
for (j=0; j<4 ; j++) {
if ((*work_char_ptr == 0)11(i >= ID_F1ELD_LENGTH)) {
j = 10; /* indicate end of message found */
I
else {
pulseData[work_pulse_index].[D_buffer[i] = *work_char_ptr;
i++;
work_char_ptr-i-+;
I
}
if (j>5) ( /* found end of ID field from remote encoder */
for (i=0; i<ID_FIELD_LENGTH; i++) {
pulseData[work_pulse_index].ID_field[i] =
pulseData[work_pulse :index].ID_buffer[i];
pulseData[work_pulse_indexLID_buffer[i] = 0;
I
I
}
I
else if ((PICrcyBuf.command == READ_REGISTER) && (PICrcliBuf.reg_ID ==
ERROR_REG)) {
if (PIC_status[rcv_PIC_indexlsoftware_type == 4) { /* Remote encoder interface module */
work_pulse_index = (PICro/Buf.PIC_addr * PULSES_PER_PIC) +
(PICrcyBuf.command_data 24);
if (work_pulse_index < (2 * NUMPH)) ( pulseData[work_pulse_index].error_cnt++;
for (i=0; i<ID_FIELD_LENGTH;
pulseData[work_pulse jndex1.1D_buffer[i++] = 0);
ttendif else if ((PICrcyBuf.command == WRITE_REGISTER) && (PICrcvfiutreg_ID ==
PARM_REG)) PIC_status[rcv_PIC_indextupdate_parameter = FALSE;
else if ((PICrcvfiuf.command == READ_REGISTER) && (PICrcv13ufreg_ID ==
VERS_REG)) PIC_status[rcv_PIC_index]. get_version = FALSE;
PIC_status[rcv_PIC_index].software_type =
(PICrcyBuf.command_data & Oxff000000) >> 24;
PIC_status[rcv_PIC_index].software_version =
(PICreviiuf.command_data & Ox0Off0000) 16;
PIC_status[rcv_PIC_index].loop_rate =
(PICrcyButcommand_data & Ox0000ftD0) >> 8;
else if ((PICro/Butcommand --= READ_REGISTER) && (PICrcvfiuf.reg_ID ==
SERNO_REG)) PIC_status[rcv_PIC_index] .get_semo = FALSE;
PIC_status[rcv_PIC_indextserial_number = PICro/Buf.command_data;
else if (OPICrcv13utcommand == READ_REGISTER) II (PICreviiutcommand <=
MAX_FAST_READ)) && (PICrcvl3utreg_ID <= MAX_PULSE_REG)) /* Pulse reading */
work_pulse_index = (PICrcyBuf.PIC_addr * PULSES_PER_PIC) +
PICrcyBufreg_ID;
if (work_pulse_index < (NUMPH * 2)) pulseData[work_pulse_index] .reading = PICrcyBuf.command_data;
copy_rcvd_data = FALSE;
if (PIC_status[rcv_PIC_index].get_version) else if (PIC_status[rcv_PIC_index]. software_type == 4) /* Remote encoder interface module */
copy_rcvd_data = TRUE;
accumXfer.low = pulseData[work_pulse_index].reading;
else if (PIC_status[rcv_PIC_index].software_type == 3) /* Remote pulse counter module */
copy_rcvd_data = TRUE;
if (!PIC_status[rcv_PIC_indexl.get_semo) sprintf((char *) pulseData[work_pulse indext1D_field,"S%081dP%d", PIC_status[rcv PIC_index].seriallnumber, PICrcvflutreglID);
if (releaseCode.option.countEveryEdge) accumXfer.low = pulseData[work_pulse_index] .reading;

else accumXfer.low = pulseData[work_pulse_index].reading 1;

accumXfer.high = OL;
#ifndef VATEST
if (copy_rcvd_data) #ifndef IS MC5 ¨/* It is an RSM or ST5, so mapping for pulse 1 thru 4 is M1Q13, M1Q14, M2Q13, M2Q14 */
ph[0][work_pulse_index/2][(work_pulse_index&Ox01)?PULSE2:PULSEl] .accum =
ph [1] [work_pulse_index/2] [(work_pulse_index&Ox01)?PULSE2:PULSE1] .accum =
accumXfer ;
#else /* It is an MC5, so mapping for pulse 1 thru 48 is M1Q13..M24Q13, M1Q14..M24Q14 */
ph[0][work_pulse_index%NUMPH]Rwork_pulse_index/NUMPH)?PULSE2:PULSE1].accum =
ph[l][work_pulse_index%NUMPH]Rwork_pulse_index/NUMPH)?PULSE2:PULSEllaccum =
accumXfer ;
#endif #endif if ((PICrcvfluf. flags & (PIC_error_flag I PIC invalid_data_flag)) != 0) PIC status[rcv_PIC indextget_status = TRUE;
if ((PIC¨rcvBuf.flags &¨PIC_need refresh_flag) != 0) PIC status[rcv_PIC indextup¨date_parameter = TRUE;
/* check status flags */
/* Decide what command to send */
PICxmitBuf.flags = 0;
#ifndef IS_ST5 /* MC5 or RSM, check for cold-start processing to clear pulse registers */
if (clear_state == SEND_GLOBAL CLR) /* Cold start, send global clr */
PICxmitBuf.PIC_addr = GLOBAL PIC ADDR;
PICxmitBuf.command = CLEAR_PULS¨E_REGISTERS;
format_xmit buffer();
clear_state = SENDING_GLOBAL_CLR;
PIC_serial_status = do_send_cmd; /* Start UART */
else if (clear_state == SENDING_GLOBAL_CLR) clear_state = GLOBAL_CLR_SENT;

#else /* ST5, check for ATM (Automatic Tuning Module) operations */
if (ATM_controlsequest_flag) ATM_controlsequest flag = FALSE;
fl ATM_control.error_¨ag = FALSE;
ATM_control.active_flag = TRUE;
ATM_control.state = ATM DONE;
PICxmitBuf.PIC_addr = AT¨M_control.ATM_number + ATM_BASE_ADDR;
switch (ATM_control.operation) case SET PRE_ALIGN:
PICxmi¨tBuf.command = WRITE REGISTER;
PICxmitBufseg_ID = OUTPUT ¨REG;
PICxmitBuf.command_data = A¨TM_control.start_cap_code &
ATM_RC CAP_MASK;
PICxmitBuf.command data1= ATM_PRESET_CODE;
ATM_control.state = D¨O_PRESET;
break;
case DO_ALIGN:
PICxmitBuf.command = WRITE REGISTER;
PICxmitBufseg_ID = CONTROL¨ REG;
if (ATM_control.start_cap_code > ATM_control.end_cap_code) = - 40 -ATM control.end_cap_code = ATM_control.start_cap_code;
PICxmi¨tBuf.command_data = ATM_control.start_cap_code &
ATM_RC_CAP_MASK;
PICxmitBuf.command_data = (PICxmitBuf.command_data 12) (ATM_control.end cap_code & ATM_RC_CAP_MASK) (ATM MEAS_TI¨ME 24);
ATM_control.state = SET_ALIGN;
ATM_control.align_timer = ATM_control.end_cap_code -ATM_control.start_cap_code;
ATM_control.align_timer *= ((ATM_DISC_TIME + ATM_MEAS_TIME +4) *
(1.25 /62.5));
ATM_control.align_timer += 13; /* Time in 1/64 sec to wait before checking result */
/* Number of steps * time per step + 25% + .2 second */
break;
case SET NORMAL_PLC:
PICxmitBuf.command = WRITE_REGISTER;
PICxmitBuf. reg_ID = OUTPUT_REG;
PICxmitBuf.command_data = ATM_control.optimum_cap_code &
ATM_RC_CAP_MASK;
PICxmitBuf.command_data1= ATM PLC_CODE;
ATM_control.state = DO_PLC_SET
break;
case DISCONNECT_COUPLER:
PICxmitBuf.command = WRITE_REGISTER;
PICxmitBufreg_ID = OUTPUT REG;
PICxmitBuf.command_data = A¨TM_control.optimum_cap_code &
ATM_RC_CAP_MASK;
PICxmitBuf.command data1= ATM DISC CODE;
ATM control.state = DO_ATM_DISCONNE¨ CT;
break default:
case READ_XMIT_LEVEL:
ATM_control.error_flag = TRUE;
ATM_control.done_flag = TRUE;
ATM_control.active_flag = FALSE;
break;
if (ATM_control.active_flag) f format_xmit_buffer();
PIC_wait limit = DIRECT PIC_WAIT_LIMIT;
PIC_seria¨l_status = do_send_cmd; /* Start UART */

else if (ATM_control.active_flag) if ((ATM_control.state != WAIT_ALIGN) II
(--ATM_control.align_timer <= 0)) ATM_control.error_flag = TRUE;
ATM_control.done_flag = TRUE;
ATM_control.active_flag = FALSE;
}
else /* poll ATM for auto-tune end */
PICxmitBuf.command = 0;
format_xmit_buffer();
= DIRECT_PIC_WAIT_LIMIT;
PIC_serial_status = do_send_cmd; /* Start UART */

else if (MUX_controlsequest_flag) MUX_controlsequest_flag = FALSE;
MUX_control.error_flag = FALSE;
if ((pulseOutMode == PIC_ST_SERIAL)) PICxmitBuf. bits.bufByte[0] = ((MUX_controlscv_mask & 0x03) 5) I
((MUX_control.xmit_mask & Ox7f) >> 2);
PICxmitBuf. bits.bufByte[1] = ((MUX_control.xmit_mask & 0x03) 6);
bit_count = 11;
PIC_serial_status = sending_st5_bits; /* Start UART */
MUX_control.last_xmit_mask = MUX_control.xmit_mask;
MUX_control.last_rcv_mask = MUX_control.rcv_mask;
MUX_control.done_flag = TRUE;

else MUX_control.active_flag = TRUE;
PICxmitBuf.PIC_addr = ST5_MUX_PIC_ADDR;
PICxmitBuf.command = WRITE_REGISTER;
PICxmitBufreg_ID = OUTPUT_REG;
PICxmitBuf.command_data = (MUX_controlscv_mask 8) +
MUX_control.xmit_mask;
format_xmit_buffer();
PIC_wait_limit = DIRECT_PIC_WAIT_LIMIT;
PIC_serial_status = do_send_cmd; /* Start UART */

*tendif else if ((ext_comm.control_flags & (XMIT DATA_RDY I XMIT_REQUEST)) =
(XMIT_DATA_RDY I XMIT_REQUEST)) 1 /* Send command for external routine */
PICxmitBuf = ext_comm.xmit buf;
ext_comm.control_flags &= ¨XMIT_REQUEST;
ext_comm.control_flags 1= CPY_RCV_DATA;
/* Look up correct PIC status index for reuested PIC */
for (i=0; ((i<MAX_PICS¨) && (PIC_status[i].PIC_addr != PICxmitBuf.PIC_addr));
i++);
if (i < num_PICs) PIC_status[i]last_cmd_data = PICxmitBuf.command data;
PIC_status[i].last_command = PICxmitBuf.command7 #ifdef IS_MC5 if (ext comm.xmit_buf.PIC addr < ST5 MUX PIC ADDR) = ______________ L
AI¨LIMIT;
else #endif PIC_wait_limit = DIRECT_PIC_WAIT_LIMIT;
format_xmit_buffer();
PIC_serial_status = do_send_cmd; /* Start UART */

else if ( ((ext_comm.control_flags & SUPPRESS_NORMAL_COMM) == 0) && (--ST5_PIC_delay_ctr <= 0)) ST5_PIC_delay_ctr = ST5_PIC_DELAY; /* Slow down routine communications in the ST5 */
#else #endif PICxmitBuf.PIC addr = PIC_status[current PIC_index].PIC_addr;
need_pulse_readl TRUE; /* Set defaults */
#ifdef IS_ST5 if ((pulseOutMode == PIC_ST SERIAL) &&
(PICxmitBuf.PIC_addr == ST5_MUX_PIC_ADDR)) else #endif if (PIC_status[current_PIC_index] .force_pulse_read &&
OPIC_status[current_PIC_indexl.get_version) &&
(PIC_status[current_PIC_index].PIC_addr < ST5_MUX_PIC_ADDR) ) PIC_status[current_PIC_index].force_pulse_read = FALSE;
else PIC_status[current_PIC_index].force_pulse_read = TRUE;
#ifndef IS_ST5 if (PIC_status[current_PIC_indextclear_pulse_regs &&
(clear_state == GLOBAL_CLR_SENT) ) /* Global clear sent, get status */
need_pulse_read = FALSE;
PICxmitBuf.command = READ_REGISTER;
PICxmitBufseg_ID = STATUS_REG;
format_xmit_buffer();
else #endif if (PIC_status[current_PIC_index].get_version) need_pulse_read = FALSE;
PICxmitBuf.command = READ_REGISTER;
PICxmitBuf. reg_ID = VERS_REG;
format_xmit_buffer();
else if (PIC_status[current_PIC_index] .get_serno) need_pulse_read = FALSE;
PICxmitBuf.command = READ_REGISTER;
PICxmitBuf. reg_ID = SERNO_REG;
format_xmit_buffer();
else if (PIC_status[current_PIC jndex] .update_parameter) PICxmitBuf.command = WRITE_REGISTER;
if (PIC_status[current_PIC_index]. software_type == 3) /* Pulse ctr */
/* Pulse ctr parameters: *1 /* Power-On sample rate: 42/sec */
/* Power-off sample rate: 1/sec */
/* Days to count if rcving pulses: */
/* RSM: 5 days *1 /* PDM: 35 days */
/* Days to count if no pulses rcvd: */
/* RSM: 1 day */
/* PDM: 3 days */

/* on RSM, the 2 lsbs of */
/* load_shed_mask[0] are sent to */
/* the PIC output bits *1 #ifdef IS_RSM
PICxmitButcommand_data = Ox01150507 &
(load_shed_state[0] I Oxfffffffc);
#else PICxmitButcommand_data = 0x0115230d;
#endif #ifdef IS_MC5 else if (PIC_status[current_PIC_index] software_type == 4) /* Remote encoder reader */
PICxmitBuf.command_data = READ_ENCODER_PARM;
if ((releaseCodep->option.couplers_mask & Ox01) == 0) /* If mask bit 0 is 0, no touch-pad compatibility */
PICxmitBuf.command_data &= Oxff0Offff;

else if (PIC_status[current_PIC_index].software_type == 5) /* MC5 mux */
got_ver_3 = got_ver_3_3 = FALSE;
for (i=0; i<num_PICs; i-H-) if (PIC_status[i].get_version) got_ver_3 = TRUE;
got_ver_3_3 = TRUE;

else if (PIC_statusnsoftware_type == 3) got_ver_3 = TRUE;
if (PIC_status[i].software_version == 3) got_ver_3_3 = TRUE;
}
if (got_ver_3) if (got_ver_3_3 &&
((releaseCodep->option.couplers_mask & 0x02) != 0)) PICxmitBuf.command_data = Ox0c007000; /* 32 bps, periodic wake-up */

else PICxmitBuf.command_data = 0x0c007080; /* 32 bps, no wake-up */
}

else , PICxmitBuf.command_data = 0x02030080; /* 205 bps, no wake-up */
#endif #ifdef IS_ST5 else if (PIC_status[current_PIC_indextsoftware_type == 8) /* Auto tune module */
PICxmitBuf.command_data = 0x02030000 I (ATM_DISC_TIME << 8) I
(ATM_RC_XMIT_ON 8)1ATM_NUM_CAP_BITS;
/* xmit offset = 2, cplr offset = 3, */
/* relay delay = ATM_DISC_TIME, Xmit mask = ATM_RC_XMIT_ON, */
/* number of capacitor relays = ATM_NUM_CAP_BITS
else if (PIC_status[current_PIC_index] .software_type == 6) /* ST5 mux */
PICxmitBuf.command_data = Ox00000000;

#endif else if (PIC_status[current_PIC_index] software_type == 7) /* Load Control Module */
PICxmitBuf.command_data = Ox00000000;

else PIC_status[current_PIC_index] .update_parameter = FALSE;
/* unknown software type, cancel command */
if (PIC_status[current_PIC_index].update_parameter) need_pulse_read = FALSE;
PICxmitBuf. reg_ID = PARM_REG;
format_xmit_buffer();

else if (PIC_status[current_PIC_index].reset_status) need_pulse_read = FALSE;
PICxmitBuf.command = SYSTEM_CONTROL;
PICxmitBuf.command_data =
(PIC_status[current_PIC_index]. status_reg_value & Oxffbf);
PICxmitBuf.command_data = PICxmitBuf.command_data << 16; /* Move status bits to MSb's */
PICxmitBuf.reg_ID = STATUS_REG;
format_xmit_buffer();
else if (PIC_status[current_PIC_index].get_status) need_pulse_read = FALSE;
PICxmitBuf.command = READ_REGISTER;
PICxmitBufseg_ID = STATUS_REG;

i format_xmit_buffer();
}
#ifdef IS_MC5 if (need_pulse_read && (PIC_status[current_PIC_index]. software_type == 4)) need_pulse_read = FALSE;
PICxmitBucommand = SYSTEM_CONTROL;
if (++PIC_status[current PIC indexl.curriD_reg >= PULSES_PER_PIC) PIC_status[current_PICtind¨exlcurr_ID_reg = 0;
if ( (((PIC_status[current PIC_index].PIC addr * PULSES_PER_PIC) +
PIC_statuslcurrent_PIC_indexlcurr ID reg) % 24) >= num_pulse_ctrs) PIC_status[current_PIC-lin¨clex] .curr_ID_reg = 0;
PICxmitBufseg_ID = PIC_status[current PIC_indexlcurr_ID reg;
work_pulse index = (PIC_status[current:PIC_index].PIC_adcir *
PULSES_PER_PIC) + ¨PICxmitBufreg_ID;
for (i=0; i<ID_FIELD_LENGTH; i-H-) if (pulseData[work_pulse_indexl.ID_buffer[i] == 0) {
j=i-1;
i = ID_FIELD_LENGTH;

if (j<0) {
j = 0;
) else if (j > (ID_FIELD_LENGTH-4)) j = ID_F1ELD_LENGTH-4;

PICxmitBuf.command_data = READ_ENCODER_ID I (j 8);;
format_xmit_buffer();

#endif ) if (need_pulse_read) {
#ifdef IS_MC5 if (PIC_statuslcurrent_PIC_index]. software_type == 7) {
i = PIC_status[current_PIC_index].PIC_addr - LCM_BASE_ADDR; 1* get LCM #
*1 work_bit_mask = (load_shed_state[0] (9 * i)) & Ox000001ff;
PICxmitButcommand_data =0;
for (i=0;i<9;i++) if ((work_bit_mask & Ox100) != 0) PICxmitBuf.command_data = (PICxmitBuf.command_data << 2) + 1; /* lsb turns relay on */
else PICxmitBuf.command_data = (PICxmitBuf.command_data << 2) + 2; /* msb turns relay on */
work_bit_mask = work_bit_mask << 1;
PICxmitBuf.command_data1= 0x32000000; /* Set pulse time = 50 mS */
PICxmitBuf.command = WRITE_REGISTER;
PICxmitBufreg_ID = OUTPUT_REG;
format_xmit_buffer();
need_pulse_read = FALSE;

else #endif if (PIC_statusicurrent_PIC_indexl.num_pulse_regs == 0) #ifndef IS_5T5 PICxmitBuf.command = READ_REGISTER;
PICxmitBuf. reg_ID = VERS_REG;
format_xmit_buffer();
need_pulse_read = FALSE;
#endif else #ifdef IS_MC5 if ( (((PIC_status[current_PIC_indexl.PIC_addr * PULSES_PER_PIC) +
PIC_status[current_PIC_indexlcurr_pulse_reg) % 24) >= num_pulse_ctrs) PIC_status[current_PIC_indextcurr_pulse_reg = 0;
#endif if (PIC_status[current_PIC_indexlcurr_pulse_reg <= MAX_FAST_READ) PICxmitBuf.command = PIC_status[current_PIC_index].curr_pulse_reg;
else PICxmitBuf.command = READ_REGISTER;
PICxmitBufreg_ID = PIC_status[current_PIC_index] .curr_pulse_reg;
format_xmit_buffer();
need_pulse_read = FALSE;
if (++PIC_status[current_PIC_index].curr_pulse_reg >=-PIC_status[current_PIC_index].num_pulse_regs) PIC_status[current_PIC_index].curr_pulse_reg = 0;
#ifdef IS_RSM
PIC_status[current_PIC_index].update_parameter = TRUE;
#endif _ ) }
}
PIC_status[current_PIC_index].last_cmd_data = PICxmitBuf.command_data;
PIC_status[current_PIC_index].last_command = PICxmitBuf.command;
PIC_wait_limit = PIC_status[current_PIC_index] .reply_wait_limit;
rcv_PIC_index = current_PIC_index;
if (++current_PIC_index == num_PICs) current_PIC_index =0;
if (!need_pulse_read) PIC_serial_status = do_send_cmd; /* Start UART */

}
#ifdef IS_RSM /* In RSM, generate serial stream from subseconds */
void pulseSubsecond(void) ( if (num_PICs != 0) if (PIC_clk_state == clk_high) /* Falling edge, just set clock low */
fs1004.io.pulseOut1Off = 0;
PIC_clk_state = clk_low;

else PIC_clk_state = clk_high;
#include "pic.def' /* Do PIC serial comm on clock rising edge */

}
#endif void process_status_bits(void) unsigned int work_pulse_index, work_status_bits;

PIC_status[rcv_PIC_indextget_status = FALSE;
PIC_status[rcv_PIC_index] .status_reg_value = PICrcyButcommand_data >> 16;
PIC_status[rcv_PIC_index].time_since_global = (PICrcyBuf.command_data 8) &
Oxff;
if (PIC_status[rcv_PIC_indextstatus_reg_value != 0) PIC_status[rcv_PIC_index].reset_status = TRUE;
if ((PIC_status[rcv_PIC jndexbstatus_reg_value & Ox8f10) != 0) PIC_statusircv_PIC_indexl.PIC_data_err_count++; /* PIC detected bad data */
set_PIC_alarm(PIC_flags_O,PIC_status[rcv_PIC_indexl.PIC_addr, PIC_status[rcv_PIC_index].status_reg_value);
work_status_bits = (PIC_status[rcv_PIC_index]. status_reg_value >> 8) & Ox0f;
work_pulse_index = PIC_status[rcv_PIC_index].PIC_addr * PULSES_PER_PIC;
while (work_status_bits > 0) if (work_status_bits & Ox01) pulseData[work_pulse_indexl.error_cnt++;
work_status_bits = work_status_bits >> 1;
work_pulse_index++;

if (((PIC_status[rcv_PIC_index].status_reg_value & 0x20) != 0) &&
!PIC_status[rcv_PIC_index].clear_pulse_regs) PIC_status[rcv_PIC_index].comm_error_count++; /* PIC detected comm parity err */
if (PIC_status[rcv_PIC_index].comm_error_count > 2) set_PIC_alarm(PIC_comerr_O,PIC_status[rcv_PIC_index].PIC_addr, PICrcvl3uf.flags I 0x0800);
if ((PIC_statusircv_PIC_indextstatus_reg_value & 0x3080) != 0) PIC_status[rcv_PIC_indexl.PIC_reset_count++; /* PIC was reset */
if (PIC_statuslrcv_PIC_index].PIC_reset_count > 1) set_PIC_alarm(PIC_reset_O,PIC_status[rcv_PIC_index].PIC_addr, PIC_status[rcv_PIC_index].status_reg_value);

if (PIC_status[rcv_PIC_index] .clear_pulse_regs &&
(clear_state == GLOBAL_CLR_SENT) ) PIC_statusircv_PIC_indextclear_pulse_regs = FALSE;
if ( ((PIC_status[rcv_PIC_index].status_reg_value & Ox0f) != Ox0f) &&
(PIC_status[rcv_PIC_index]. software_type == 3) ) i . CA 02527068 2006-11-14 {
PIC_status[rcv_PIC_index] .PIC_data_err_count++; /* Clear cmd failed */
set_PIC_alarm(PIC_flags_O,PIC_status[rcv_PIC_index].PIC_addr, PIC_status[rcv_PIC_index].status_reg_value);
}

else if ( ((PIC_status[rcv_PIC_index].status_reg_value & OxOf) != 0) &&
OPIC_status[rcv_PIC_index].status_reg_value & Oxf10) == 0) ) I
PIC_status[rcv_PIC_index].PIC_data_err_count += 1000; /* Spurious clr cmd */
set_PIC_alarm(PIC_flags_O,PIC_status[rcv_PIC_index].PIC_addr, PIC_status[rcv_PIC_index].status_reg_value);
I

void set_PIC_alarm(alarmcodes pass_alarm_codes, int pass_PIC_addr, unsigned int pass_alarm_data) I
if (!Comm_background_flags.do_alarm) I
PIC_alann.alarm_codes = pass_alarm_codes + pass_PIC_addr;
PIC_alarm.ack = pass_alarm_data;
Comm_background_flags.do_alarm = TRUE;
) I
unsigned char workTpar;
BOOLEAN decode_rcv_buffenvoid) I
int i;
unsigned int workInt;
workTpar = Ox if;
if (PICrcyBuf.flags == 0) I
work_PIC_addr = Get5();
if (PICrcyButflags == 0) PICrcyBuf.PIC_addr = work_PIC_addr; /* Valid address received */
PICrcyBuf.command = Get5();
if (PICrcyBuf.command > OxOf) PICro/Bufseg_ID = Get5();
else PICro/Buf. reg_ID = PICrcyBuf.command;
PICrcyBuf.command_data = 0;
for (i=0; i<6; i++) PICro/Buf.command_data = (PICrcyBuf.command_data 5) + Get5();
workInt = Get5();
PICrcyBuf.command_data = (PICrcyButcommand_data 2) + (workInt 3);

PICrcyBuf. flags1= workInt & 0x07;
workInt = Get5();
if (workTpar 1=0) PICrcyBuf. flags1= rcv_tpar_error_flag;
/* Look up correct PIC_status index for data in rcv buffer */
for (i=0; ((i<MAX_PICS) && (PIC_status[i].PIC_addr != PICrcyBuf.PIC_addr));
i++);
if (i >= num_PICs) PICrcyBuf. flags1= rcv_bad_addr_flag; /* past end of valid PICs, address error */
if (i == MAX_PICS) rcv_PIC jndex = 0;
else rcv_PIC_index =
#ifdef VATEST
#if VATEST==1 PICrcyBuf.command = temp_command;
PICrcyBuf.reg_ID = temp_reg_ID;
PICrcyBuf.command_data = temp_command_data;
PICrcyBuf.flags = temp_flags;
ftendif #endif return((PICrcyBut flags &
¨(PIC_error_flagIPIC_need_refresh_flagIPIC_invalid_data_flag)) == 0);

void format_xmit_buffer(void) int i,j,ShiftCount;
unsigned int WorkInt;
unsigned long WorkData;
PICxmitBuf.bitCount =0;
PICxmitBuf.bits.bufLong[0] = 0;
PICxmitBuf. bits.bufLong[1] = 0;
PICxmitBuf. bits.bufLong[2] = 0; /* Clear xmit bit buffer */
workTpar = Ox If; /* Initializa Tpar */
Stuff6(PICxmitBuf.PIC_addr);
Stuff6(PICxmitBuf.command);
if (PICxmitBuf.command > Ox0f) Stuff6(PICxmitBuf.reg_ID);
if (PICxmitBuf.command > Ox17) i _ WorkData = PICxmitBuf.command_data;
ShiftCount = 32;
for (i = 0;i<7;i++) WorkInt = 0;
for (j=0;j<5;j++) WorkInt = WorkInt 1;
if (WorkData & 0x80000000) WorkInt += 1;
WorkData = WorkData 1;
if (--ShiftCount == 0) WorkInt = (WorkInt 3) + (PICxmitBuf.flags & 0x07);
.l = 5;

Stuff6(WorkInt);

Stuff6(workTpar);
/* Buffer set, set up UART control */
PICrcyBuf.bitCount = 66;
if ((PIC_comm_mon.control_flags & XMIT_DATA_RDY) == 0) PIC_comm_mon.xmit_buf = PICxmitBuf;
PIC_comm_mon.controlflags 1= XMIT_DATA_RDY;

PICrcyBuf.flags =0;
PICrcyBuf.PIC_addr = PICxmitBuf.PIC_addr; /* preset address of remote PIC */

unsigned int Get5(void) int byte_index, bit_index;
unsigned int work_result;
work_result = 0;
if ((PICrcvBuf. flags &
-(PIC_error_flagIPIC_need_refresh_flagIPIC_invalid_data_flag)) == 0) byte_index = 96 - PICrcyBufbitCount;
bit_index = byte_index & 0x07;
byte_index = byte_index 3;
work_result = (PICrcyBuf. bits.bufByte[byte_index] 8) +
PICrcyBufbits.bufByte[byte_index+1];

work_result = work_result >> (10 - bit_index);
work_result &= Ox3f;
if (parity6[work_result >> 1] != work_result) work_result =0;
PICrcvBufflags 1= rcv_parity_err_flag;
else work_result = work_result >> 1;
workTpar A= work_result;
PICrcl/BufbitCount -= 6;
if (PICrcyBufbitCount < 0) PICro/But flags1= rcv_bad_length_flag;
return(work_result);
void Stuff6(int pass_data) int byte_index, bit_index;
workTpar A= pass_data;
byte_index = PICxmitBuf.bitCount >> 3;
bit_index = PICxmitBuf.bitCount & 0x07;
pass_data = parity6[pass_data] (10 - bit_index);
PICxmitBuf.bits.bufByte[byte_index] 1= pass_data >> 8;
PICxmitBuf. bits.bufByte[byte_index+1] 1= pass_data & Oxff;
PICxmitBuf.bitCount += 6;

PULSE.H
*1 #ifndef BOOLEAN_DEFINED
#define BOOLEAN_DEFINED
typedef int BOOLEAN;
#endif /* subsecond processing for pulse counters */
void pulseSubsecond(void);
/* Daily PIC table rebuild */
void pulseDay(void);
/* Main PIC communication routine */
void pulseService(void);
/* PIC comm routine - once-per-second code */
void pulseSecond(void);
/* Subroutines for PIC communication */
void Stuff6(int pass_data);
void format_xmit_buffer(void);
BOOLEAN decode_rcv_buffer(void);
void process_status_bits(void);
unsigned int Get5(void);
void set_PIC_alarm(alarmcodes pass_alarm_type, int pass_PIC_addr, unsigned int pass_alarm_data);
/* Startup code for PIC communication */
void pulseStartup (void);
/* Routine to clear pulse registers after cold start */
void pulseColdstart(void);
/* defined in pt.c */
#define RELAY_A 0 #define RELAY_B 1 void pulseOut(int picNbr,int relayNbr,int ONoff);
void ptEveryMinute(void) ;
void ptEverySecond(void) ;
void set_PLC_relays(int xmitRelay,int rcvRelay) ;

PICEND.DEF
/*
include file at end of mtrsamp to control MC and ST pic chips from mtrsamp interrupt */
#ifdef IS_MC5 if (pulseOutMode==PIC_MC_SERIAL) {
asm (" MOVE.L #0x80400E,A0");
asm (" AND.W #0xFCFF,(A0)"); /* Clear clock and data ports */

#endif #ifdef IS_5T5 asm (" MOVE.L #0x80400E,A0");
asm (" AND.W #0xFEFF,(A0)"); /* Insert clock falling edge */
if (PIC_serial_status == sending_st5_bits) {
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" NOP");
asm (" MOVE.L #0x80400E,A0");
asm (" OR.W #0x0100,(A0)"); /* If sending bits, activate clock*/

#endif PlCVARS.DEF
/*
local variables to control MC and ST pic chips from mtrsamp interrupt meter/c/lib/picvars.def */
unsigned long bitOneFlag;

i PULSELINK.DEF
/* determine if variables are external or defined here */
#undef ref #ifdef PSTRU_DEFINED
#define ref #else #define ref extern #endif #if (NUMPH >6) #define IS_MC5 #else #ifdef MAX SCAN_METERS
#define IS_S¨T5 #else #define IS_RSM
#endif #endif /* Values for hdwr -p (pulseOutMode) */
#define STANDARD_PIC_COMM 0 #if 0 /* remove these equates from mtrlink.def */
#define PIC_PULSE SERIAL 1 #define PIC_MC SERIAL 2 #define PIC_ST_SERIAL 3 #endif /* then uncomment them here */
/* #define VATEST 1 */
#ifdef VATEST
#undef IS_MC5 #undef IS_RSM
#undef IS_ST5 #define IS_RSM
#undef NUMPH
#define NUMPH 3 #undef MAX_SCAN_METERS
#endif /* Uncomment for water meters (Oakville Hydro) */
#define READ_ENCODER_ID Ox49ff0000 #define READ_ENCODER_PARM 0x0312500c 1* Uncomment for gas meters (Sonix) #define READ_ENCODER ID 0x49fe0389 #define READ_ENCODERIPARM 0x0300500c */
#define ID_FIELD_LENGTH 13 #define PULSES_PER_PIC 4 #ifdef IS MC5 #define B¨ITS PER SEC 822 #define MAX1PICS¨ 16 #else #ifdef IS ST5 #define B¨ITS PER SEC 942 #define MAX1PICS¨ 5 #else #define BITS PER SEC 32 #define MAX¨_PICS¨ 1 #endif #endif #define DIRECT_PIC_WAIT_LIMIT 24 #define BUFFERED_PIC_WAIT_LIMIT 10* BITS_PER_SEC
#define NUM_START_BITS 12 #ifdef IS ST5 #define ¨REBUILD_DELAY 30000 #else #define REBUILD_DELAY 1000 #endif typedef struct unsigned long serial_number;
unsigned long last_cmd data;
unsigned char PICiaddr;
unsigned char software_type;
unsigned char software version;
unsigned char 1¨oop_rate;
unsigned int status_reg_value;
unsigned char time_since_global;
unsigned char num_pulse_regs;
unsigned char curr_pulse_reg;
unsigned char curr_ID_reg;
unsigned char last_command;
unsigned int reply_wait_limit;

, unsigned int PIC_data_err_count;
unsigned int PIC_reset_count;
unsigned int comm_error_count;
unsigned force_pulse_read: 1;
unsigned get_serno : 1;
unsigned get_version : 1;
unsigned get_status : 1;
unsigned reset_status : 1;
unsigned update_parameter: 1;
unsigned clear_pulse_regs: 1;
}
PIC_status_t;
typedef enum {
sending_bits, sending_st5_bits, rcving_bits, do_PIC_start, sending_PIC_start, do_send_cmd, sending_start, sending_start_l, sending_stop, waiting_for_start, rcving_stop, idle }
PIC_s_stat_t;
typedef enum {
SET_PRE_ALIGN, DO_ALIGN, SET_NORMAL_PLC, DISCONNECT_COUPLER, READ_XMIT_LEVEL
}
ATM_op_t;
typedef enum {
DO_PRESET, DO_PLC_SET, SET_ALIGN, WAIT_ALIGN, DO_ATM_DISCONNECT, ATM_DONE
}
ATM_state_t;

, typedef struct unsigned char PIC_addr;
unsigned char command;
unsigned char reg_ID;
unsigned long command_data;
unsigned int flags;
int bitCount;
union{
unsigned long bufLong13];
unsigned char bufByte[12];
1 bits;
}
PICbitBuf;
#ifndef BOOLEAN DEFINED
#define BOOLEAN DEFINED
typedef int BOOLEAN;
#endif /* Definition of bits in Flags field of PIC comm buffers */
/* NOTE- Top 4 bits (Oxf000) reserved for use by ATM code */
#define rcv_bad_addr_flag Ox0100 #define rcv_tpar_error_flag 0x0080 #define rcv_data_ready_flag 0x0040 #define rcv_bad_length_flag 0x0020 #define rcv_timeout_flag Ox0010 #define rcv_parity_err_flag 0x0008 #define PIC_error_flag 0x0004 #define PIC_need_refresh_flag 0x0002 #define PIC_invalid_data_flag Ox0001 /* Command codes for PIC communication */
#define MAX_FAST_READ 0x07 #define CLEAR PULSE REGISTERS 0x08 E
#define READ_R¨ GISTE¨R Ox10 #define WRITE REGISTER Ox18 #define SYSTEM¨ _CONTROL 0x19 /* Register ID codes for PIC communication */
#define MAX PULSE REG 15 #define CONT¨ROL_REG 16 #define ERROR_REG 26 #define OUTPUT REG 27 #define PARM_RE¨G 28 #define VERS_REG 29 , #define SERNO_REG 30 #define STATUS_REG 31 /* Special-purpose PIC addresses */
#define GLOBAL_PIC ADDR 31 #define MC5 MUX_PI¨C ADDR 30 #define ST5=MUX_PIC_ADDR 29 #define LCM BASE ADDR 161* First LCM is at address 16 */
#define ATM¨BASE_ADDR 20/* First ATM is at address 20 */
#define MAX¨_PULSE_PIC_ADDR 15 /* pulse couters are from 0 to 15 */
/* Bit usage in the ATM relay control word */
#define ATM RC_XMIT ON 0x00008000 #define ATM_RC_MEAS_XMIT 0x00004000 #define ATM_RC MEAS CPLR 0x00002000 #define ATM_RCIRES_S¨HORTED Ox00001000 #define ATM_RC CAP MASK Ox000003ff #define ATM_NU¨M_CA¨P_BITS 10 #define ATM_PRESET_CODE ATM_RC_XMIT_ON I ATM_RC_MEAS_XMIT I
ATM_RC_MEAS_CPLR
#define ATM_PLC CODE ATM_RC_XMIT_ON I ATM_RC_RES_SHORTED
#define ATM_DISC_CODE 0 /* Other ATM control equates */
#define ATM_MEAS_TIME 20L /* mSec to wait between cap change and ADC reading */
#define ATM_DISC TIME 20L /* mSec to wait before switching cap relays */
#define ATM_MIN_READING 0x0038 /* If reading at end of autotune less than this, fail */
/* Equates for ST5 comm */
#define STS_PIC_DELAY 66 #pragma region ('ram=ram") ref unsigned short current_PIC index, rcv_PIC_index;
ref PIC_status_t PIC_status[MAX=PICS];
struct ( unsigned long reading;
int error cnt;
unsigned char ¨113_field[ID_FIELD LENGTH);
unsigned char ID_buffer[ID FIELD LENGTH];
) ref pulseData[2*NUM¨PH];

struct PICbitBuf xmit_buf;
PICbitBuf rcv_buf;
int control_flags;
} ref ext_comm, PIC_comm_mon;
struct ATM_op_t operation;
unsigned int ATM_number;
ATM_state_t state;
unsigned request_flag : 1;
unsigned done_flag 1;
unsigned error_flag : 1;
unsigned active_flag : 1;
unsigned int start_cap code;
unsigned int end_cap_code;
unsigned int optimum_cap_code;
unsigned int optimum_reading;
unsigned int xmit_level;
unsigned int coupler_level;
unsigned int result_flags;
long int align_timer;
) ref ATM_control;
struct unsigned request_flag : 1;
unsigned done_flag : 1;
unsigned error_flag : 1;
unsigned active_flag : 1;
unsigned int xmit_mask;
unsigned int rcv_mask;
unsigned int result_flags;
unsigned int last_xmit_mask;
unsigned int last_rcv_mask;
} ref MUX_control;
struct unsigned do_rebuild : 1;
unsigned do_alarm 1;
} ref Comm_background_flags;
/* Bit definitions in ext_buf.control_flags */
#define SUPPRESS_NORMAL_COMM Ox0001 #define XMIT_REQUEST 0x0002 /* External routine requests send of xmit_buf */
#define CPY_RCV_DATA 0x0004 /* External cmd was sent, copy rcvd buffer to rcv_buf */
#define RCV_DATA_RDY 0x0008 /* Got reply from external cmd, reply is in rcv_buf *1 #define XMIT_DATA_RDY Ox0010 /* xmit_buf has copy of last cmd sent */

ref PICbitBuf PICxmitBuf, PICro/Buf, HoldrcyBuf;
ref PIC_s_stat_t PIC_serial_status;
ref unsigned int num_PICs;
ref unsigned int num_LCMs;
ref unsigned int rebuild_timer;
ref unsigned int ATM_work;
ref unsigned int work_PIC_addr;
ref unsigned int num_pulse_ctrs;
ref unsigned int hold_num_pulse_ctrs;
ref unsigned int bit_count;
ref unsigned int out_bit_value;
ref unsigned char *shift_LSB_ptr;
ref unsigned char in_bit_value;
ref unsigned int PIC_wait_limit;
ref unsigned int zero_count;
ref unsigned int last_comm_err_flag;
ref BOOLEAN dont_clear_PIC_stats;
ref int ST5_PIC_delay_ctr;
ref unsigned int PIC_bad_addr_count;
ref alarmstru PIC_alarm;
#ifdef VATEST
/* test !!!! */
ref int temp_command;
ref int temp_reg_ID;
ref long temp_command_data;
ref int temp_flags;
/* test !!!! */
#endif ref enum {
clk_high, clk_low ) PIC_clk_state;
ref enum {
NO_GLOBAL_SEND, SEND_GLOBAL_CLR, SENDING_GLOBAL_CLR, GLOBAL_CLR_SENT
i clear_state;
/* Old equates maintained for compatibility */
#if 0 #define RELAY_A_BIT 1 #define RELAY_B_BIT 2 #define IDLE 0 #define TX 1 #define RX 2 #define DATA_READY 3 #define WAKE 4 #define PIC_RESET 5 #define WAKE COUNT RELOAD (64*4) /* Four Seconds */
#define RESET¨COUNT:RELOAD 10 /* 1/4 Seconds */
#define RELAY¨_A_OFF_CMD 5 /*active low trigger*/
#define RELAY A ON CMD 4 #define RELAY:B1OFF_CMD 7 #define RELAY B ON CMD 6 #define CLEAR¨ACC C¨MD 8 #define SUBAC¨C CMD¨ 12 #define ECHO CMD¨ 14 #define SLEEP¨SMD 15 #define PULSE SERIAL_COM_MAX 15 #define WAKE¨CMD 16 fi #dene RESET:CMD 17 #define PULSE COM NUM 18 #define NO_PUISE_B¨IT_DATA Ox1-1-1-1.14-1-F
#define RELAY_CMD_MIN 4 #define RELAY_CMD_MAX 7 #endif PULSEOUTM.DEF
#include "clklinlc.der #include "mtrlink.def' #include "plc.def' #include "serlink.der #include "pulselink.def' #ifndef NO_FULSES
#include "scan.h"
#include "pulse.h"
#include "log.h"
void pulseout_second_back(void);
void pulseout_ram_initl(void);
ADDRFN pulseoutaddrfn ;
#pragma region ("data=ramlnitl") void (*pulseout_ram_initlp)(void)=pulseout_ram_initl;
#pragma region ("data=data") #pragma region ("data=secondBack") void (*pulseout_second_backp)(void)=pulseout_second_back ;
#pragma region ("data=data") ADDRFN_RET pulseoutaddrfn(reg8stru reg8) /* write the load shed event to flash */
putEvent(LOAD_SHED_EVENT,1,&reg8.ulong);
return(0);
void pulseout_ram_init10 addrfn_tblfGET_FROM_SLAVEIIPULSEOUT_STATE1= pulseoutaddrfn ; 1 void pulseout_second_back() #endif ,

Claims (30)

1. An apparatus for remote multi-channel metering of electricity using power line communication, comprising:
a plurality of metering points located on a secondary side of a distribution transformer and operable to separately measure electricity usage for each of a plurality of electricity consumer lines;
said apparatus in communication with a transponder located on a primary side of said distribution transformer and operable to transmit data to and receive data from said transponder via power line communication, said transponder operable to transmit data to and receive data from a remotely located computer;
said apparatus operable to control one or more load control modules operable to actuate connection and disconnection of each of a plurality of relays, each relay of said plurality of relays corresponding to one of said plurality of electricity consumer lines; and a box containing said plurality of metering points, said load control module, and said relays, wherein said distribution transformer converts medium tension distribution voltages to low tension voltages appropriate for supplying power to customers, and wherein said apparatus is operable to inject signals onto and receive signals from low voltage power lines that supply customers with electric power; said signals providing two-way communication between a meter head and said transponder and traversing said distribution transformer.
2. An apparatus as in claim 1, further comprising a tamper detector in communication with said meter head.
3. An apparatus as in claim 2, wherein said tamper detector comprises a light and a reflective surface, and wherein said meter head is operable to instruct said load control module to disconnect all of said customer lines if said tamper detector provides notification that said light is not detected reflecting from said reflective surface.
4. An apparatus as in claim 2, wherein said tamper detector comprises a detector of ambient light entering said box.
5. An apparatus as in claim 1, wherein said box is installed on a utility pole.
6. An apparatus as in claim 1, further comprising means for comparing transformer energy to total energy used by said consumer lines.
7. An apparatus as in claim 1, further comprising means for detecting reverse voltage flow through said consumer lines.
8. An apparatus as in claim 1, further comprising a computer readable memory in communication with said meter head and a counter in communication with said meter head, said counter corresponding to a customer line and operable to count down an amount of energy stored in said memory, and said meter head operable to send a disconnect signal to said load control module to disconnect said customer line when said counter reaches zero.
9. An apparatus as in claim 1, further comprising a computer readable memory in communication with said meter head, said memory operable to store a load limit for a customer line, and said meter head operable to send a disconnect signal to said load control module to disconnect said customer line when said load limit is exceeded.
10. An apparatus as in claim 1, further comprising a computer readable memory in communication with said meter head, said memory operable to store a usage limit for a customer line, and said meter head operable to send a disconnect signal to said load control module to disconnect said customer line when said usage limit is exceeded.
11. An apparatus as in claim 1, wherein said transponder is operable to communicate with said remotely located computer over medium tension power lines.
12. An apparatus as in claim 1, further comprising a display unit in communication with said meter head and operable to display data received from said meter head.
13. An apparatus as in claim 12, wherein said display unit is operable to display information regarding a customer's energy consumption.
14. An apparatus as in claim 12, wherein said display unit is operable to display warnings regarding a customer's energy usage or suspected theft of energy.
15. An apparatus as in claim 12, wherein said display unit is operable to transmit to said meter head information entered by a customer.
16. An apparatus as in claim 1, wherein said transponder is operable to communicate with said remotely located computer via at least one of: radio communications, fiber optics, and telephone lines.
17. An apparatus as in claim 1, wherein said apparatus is operable to transmit data directly to said transponder at frequencies within the range 10-25 kHz.
18. An apparatus as in claim 1, wherein said apparatus is operable to transmit data directly to said transponder at frequencies corresponding to half-odd harmonics of 60 Hz.
19. An apparatus as in claim 1, wherein said box is located in a secure area.
20. An apparatus for multi-channel metering of electricity, comprising:
a control module in communication with a secondary circuit of a distribution transformer, wherein said distribution transformer converts medium tension distribution voltages to low tension voltages appropriate for supplying power to customers;
said control module in direct communication with a transponder in communication with a primary circuit of said transformer and operable to transmit data to and receive data from said transponder via direct power line communication, through said distribution transformer, said transponder operable to transmit data to and receive data from a remotely located computer;

a plurality of meter modules in communication with said control module, each meter module operable to measure electricity usage on one of a plurality of electricity consumer lines fed from the secondary circuit of said distribution transformer;
one or more relays in communication with said control module and operable to actuate connection and disconnection of electricity to said electricity consumer lines;
and a box containing said control module, said meter modules and said relays, wherein said apparatus is operable to inject signals onto and receive signals from low voltage power lines that supply customers with electric power;
said signals providing two-way communication between said meter head and said transponder and traversing said distribution transformer to communicate at least partially over medium tension power lines to said remotely located computer.
21. An apparatus as in claim 20, wherein said one or more relays are operable to control each phase of said electricity consumer lines.
22. An apparatus for multi-channel metering of electricity, comprising:
a meter head located on a secondary side of a transformer and operable to separately measure electricity usage for each of a plurality of electricity consumer lines;
said meter head in direct communication with a transponder located on a primary side of said transformer operable to transmit data to and receive data from said transponder via direct power line communication, said transponder operable to transmit data to and receive data from a remotely located computer;
a load control module in communication with said meter head and operable to actuate connection and disconnection of each of a plurality of relays, each relay of said plurality of relays corresponding to one of said plurality of electricity consumer lines; and a box containing said meter head, said load control module, and said relays.
23. An apparatus as in claim 22, further comprising a tamper detector in communication with said meter head.
24. An apparatus as in claim 23, wherein said tamper detector comprises a light and a reflective surface, and wherein said meter head is operable to instruct said load control module to disconnect all of said customer lines if said tamper detector provides notification that said light is not detected reflecting from said reflective surface.
25. An apparatus as in claim 23, wherein said tamper detector comprises a detector of ambient light entering said box.
26. An apparatus as in claim 22, wherein said box is installed on a utility pole.
27. An apparatus as in claim 22, further comprising means for comparing transformer energy to total energy used by said consumer lines.
28. An apparatus as in claim 22, further comprising means for detecting reverse voltage flow through said consumer lines.
29. An apparatus for multi-channel metering of electricity, comprising:
a control module in communication with a secondary circuit of a distribution transformer;
said control module in direct communication with a transponder in communication with a primary circuit of said transformer and operable to transmit data to and receive data from said transponder via direct power line communication, through said distribution transformer, said transponder operable to transmit data to and receive data from a remotely located computer;
a plurality of meter modules in communication with said control module, each meter module operable to measure electricity usage on one of a plurality of electricity consumer lines fed from the secondary circuit of said distribution transformer;
one or more relays in communication with said control module and operable to actuate connection and disconnection of electricity to said electricity consumer lines;
and a box containing said control module, said meter modules and said relays.
30. An apparatus as in claim 29, wherein said one or more relays are operable to control each phase of said electricity consumer lines.
CA2527068A 2005-11-15 2005-11-15 Apparatus and methods for multi-channel metering Expired - Fee Related CA2527068C (en)

Priority Applications (2)

Application Number Priority Date Filing Date Title
CA2527068A CA2527068C (en) 2005-11-15 2005-11-15 Apparatus and methods for multi-channel metering
CA002567955A CA2567955A1 (en) 2005-11-15 2006-11-14 Apparatus and methods for multi-channel metering

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CA2527068A CA2527068C (en) 2005-11-15 2005-11-15 Apparatus and methods for multi-channel metering

Publications (2)

Publication Number Publication Date
CA2527068A1 CA2527068A1 (en) 2007-05-15
CA2527068C true CA2527068C (en) 2013-08-20

Family

ID=38051420

Family Applications (1)

Application Number Title Priority Date Filing Date
CA2527068A Expired - Fee Related CA2527068C (en) 2005-11-15 2005-11-15 Apparatus and methods for multi-channel metering

Country Status (1)

Country Link
CA (1) CA2527068C (en)

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
FR2980946B1 (en) * 2011-10-03 2014-03-21 Schneider Electric Ind Sas METHOD FOR LOCATING CURRENT CONSUMER POINTS IN AN ELECTRIC POWER DISTRIBUTION SYSTEM, PROCESSING DEVICE, CURRENT SENSOR AND CURRENT METER THEREFOR

Also Published As

Publication number Publication date
CA2527068A1 (en) 2007-05-15

Similar Documents

Publication Publication Date Title
US5994892A (en) Integrated circuit design automatic utility meter: apparatus &amp; method
US7596459B2 (en) Apparatus and methods for multi-channel electric metering
US8378844B2 (en) Utility meter with external signal-powered transceiver
US10474591B2 (en) Electronic meter with a removable protective plug
US9885739B2 (en) Intelligent electronic device capable of operating as a USB master device and a USB slave device
US11644490B2 (en) Digital power metering system with serial peripheral interface (SPI) multimaster communications
WO1998010299A1 (en) Electronic electric meter for networked meter reading
ES2441617T3 (en) System and method for monitoring and billing in line of power consumption
US9927470B2 (en) Intelligent electronic device having a memory structure for preventing data loss upon power loss
US20110115641A1 (en) Three-phase multifunction verifier
GB2379993A (en) Electrical energy consumption and generation metering arrangement
CN101351803B (en) Apparatus and methods for multi-channel metering
CA2527068C (en) Apparatus and methods for multi-channel metering
CA2567955A1 (en) Apparatus and methods for multi-channel metering
EP0742443A2 (en) Improvements in or relating to electricity meters
GB2325598A (en) Optical metering using modem and power lines
BRPI0806143B1 (en) MULTI-CHANNEL ELECTRICITY MEASURING APPLIANCES
EP0742444A2 (en) Improvements in or relating to electricity meters
MX2008007018A (en) Apparatus and methods for multi-channel metering
EA030402B1 (en) Multi-user electricity meter
US20240349405A1 (en) Devices, systems and methods for electrical utility submetering
Pere et al. New metering and meter reading visions and decisions of the Helsinki Energy Board
JPH0735779A (en) Road survey system terminal

Legal Events

Date Code Title Description
EEER Examination request
MKLA Lapsed

Effective date: 20210831

MKLA Lapsed

Effective date: 20191115

MKLA Lapsed

Effective date: 20191115