📄 thermo21.c
字号:
//---------------------------------------------------------------------------
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// Except as contained in this notice, the name of Dallas Semiconductor
// shall not be used except as stated in the Dallas Semiconductor
// Branding Policy.
//---------------------------------------------------------------------------
//
// thermo21.c - Thermochron iButton utility functions
//
// Version: 2.00
//
// History:
// 1.03 -> 2.00 Reorganization of Public Domain Kit
// Convert to global CRC utility functions
// Y2K fix.
#include <stdio.h>
#include "time.h"
#include <string.h>
#include "ownet.h"
#include "thermo21.h"
// a hack for sdcc/TINI, just printf to stdout
int fprintf (FILE *fp, char *format, ...) reentrant {
va_list arg;
*fp; // hush the compiler
va_start(arg, format);
vsprintf(NULL, format, arg);
va_end(arg);
}
FILE * fopen(char * path, char *mode) {
path, mode; //hush the compiler
return (FILE *)0;
}
int fclose(FILE *fp) {
fp; // hust the compiler
return 0;
}
static int RunThermoScript(int,ThermoStateType *,ThermoScript script[], FILE *fp);
static int ThermoStep(int,ThermoStateType *,ThermoScript *,int *,int *,int *,char *);
static int ReadPages(int,int,int,int *,uchar *);
static int WriteScratch(int,uchar *,int,int);
static int CopyScratch(int,int,int);
static int WriteMemory(int,uchar *, int, int);
// step constants
enum { ST_SETUP=0, ST_READ_STATUS, ST_READ_ALARM, ST_READ_HIST,
ST_READ_LOG, ST_CLEAR_MEM, ST_CLEAR_VERIFY, ST_WRITE_TIME,
ST_WRITE_CONTROL, ST_WRITE_RATE, ST_FINISH, ST_GET_SESSION,
ST_FIND_THERMO, ST_REL_SESSION, ST_READ_PAGES, ST_WRITE_MEM,
ST_CLEAR_SETUP };
// status contants
enum { STATUS_STEP_COMPLETE, STATUS_COMPLETE, STATUS_INPROGRESS,
STATUS_ERROR_HALT, STATUS_ERROR_TRANSIENT };
// download steps
static ThermoScript Download[] =
{{ ST_READ_STATUS, "Setup to read the mission status"},
{ ST_READ_PAGES, "Read the status page"},
{ ST_READ_ALARM, "Setup to read alarm pages"},
{ ST_READ_PAGES, "Read the alarm pages"},
{ ST_READ_HIST, "Setup to read histogram pages"},
{ ST_READ_PAGES, "Read the histogram pages"},
{ ST_READ_LOG, "Setup to read log pages"},
{ ST_READ_PAGES, "Read the log pages"},
{ ST_FINISH, "Finished"}};
// read status only steps
static ThermoScript GetStatus[] =
{{ ST_READ_STATUS, "Setup to read the mission status"},
{ ST_READ_PAGES, "Read the status page"},
{ ST_FINISH, "Finished"}};
// mission steps (assume already did StatusThermo)
static ThermoScript Mission[] =
{{ ST_CLEAR_SETUP, "Setup clear memory"},
{ ST_WRITE_MEM, "Write clear memory bit"},
{ ST_CLEAR_MEM, "Clear the memory"},
{ ST_READ_STATUS, "Setup to read the mission status"},
{ ST_READ_PAGES, "Read the status page"},
{ ST_CLEAR_VERIFY, "Verify memory is clear"},
{ ST_WRITE_TIME, "Setup to write the real time clock"},
{ ST_WRITE_MEM, "Write the real time clock"},
{ ST_WRITE_CONTROL,"Setup to write the control"},
{ ST_WRITE_MEM, "Write the control"},
{ ST_WRITE_RATE, "Setup to write the sample rate to start mission"},
{ ST_WRITE_MEM, "Write the sample rate"},
{ ST_READ_STATUS, "Read the new mission status"},
{ ST_FINISH, "Finished"}};
// global state information
static int current_speed[MAX_PORTNUM];
//--------------------------------------------------------------------------
// The 'DownloadThermo' downloads the specified Thermochron in 'SerialNum'
// and puts the data in the state variable 'ThermoState'. Progress output
// is printed to the specified file 'fp'.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Device serial number to download
// 'ThermoState' - pointer to a structure type that holds the raw and
// translated Thermochron data.
// 'fp' - file pointer to print status information to
//
// Returns: TRUE (1) : Thermochron download with raw data in ThermoState
// FALSE (0): not downloaded. Abort due to repeated errors
// or user keypress.
//
int DownloadThermo(int portnum, uchar *SerialNum,
ThermoStateType *ThermoState, FILE *fp)
{
// set the serial num
owSerialNum(portnum, SerialNum, FALSE);
// run the script and download thermochron
return RunThermoScript(portnum,ThermoState,Download,fp);
}
//--------------------------------------------------------------------------
// The 'ReadThermoStatus' reads the Thermochron status in 'SerialNum'
// and puts the data in the state variable 'ThermoState'. Progress output
// is printed to the specified file 'fp'.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Device serial number to download
// 'ThermoState' - pointer to a structure type that holds the raw and
// translated Thermochron data.
// 'fp' - file pointer to print status information to
//
// Returns: TRUE (1) : Thermochron status read with raw data in ThermoState
// FALSE (0): status not read. Abort due to repeated errors
// or user keypress.
//
int ReadThermoStatus(int portnum, uchar *SerialNum,
ThermoStateType *ThermoState, FILE *fp)
{
// set the serial num
owSerialNum(portnum, SerialNum, FALSE);
// run the script and read status of thermochron
return RunThermoScript(portnum,ThermoState,GetStatus,fp);
}
//--------------------------------------------------------------------------
// The 'MissionThermo' starts a new Thermochron mission on 'SerialNum'
// from the state information provided in 'ThermoState'. Progress output
// is printed to the specified file 'fp'.
//
// 'portnum' - number 0 to MAX_PORTNUM-1. This number is provided to
// indicate the symbolic port number.
// 'SerialNum' - Device serial number to download
// 'ThermoState' - pointer to a structure type that holds the raw and
// translated Thermochron data.
// 'fp' - file pointer to print status information to
//
// Returns: TRUE (1) : Thermochron missioned
// FALSE (0): not missioned. Abort due to repeated errors
// or user keypress.
//
int MissionThermo(int portnum, uchar *SerialNum,
ThermoStateType *ThermoState, FILE *fp)
{
// set the serial num
owSerialNum(portnum, SerialNum, FALSE);
// run the script and mission thermochron
return RunThermoScript(portnum,ThermoState,Mission,fp);
}
//--------------------------------------------------------------------------
// Run the specified script. Return TRUE if all steps completed else FALSE.
// Status is printed to file 'fp'.
//
int RunThermoScript(int portnum, ThermoStateType *ThermoState,
ThermoScript script[], FILE *fp)
{
char msg[256],LastDescription[256],LastMsg[256];
int StepCount,SubStep,ErrorCount,Status;
int last_clear_step=0;
// reset the step to the begining
StepCount = 0;
SubStep = 0;
ErrorCount = 0;
Status = STATUS_INPROGRESS;
// loop to perform all of the steps to download the Thermochron
do
{
// switch on the status of the last step done
switch(Status)
{
// step complete so go to the next
case STATUS_STEP_COMPLETE:
StepCount++;
SubStep = 0;
ErrorCount = 0;
Status = STATUS_INPROGRESS;
LastDescription[0] = 0;
LastMsg[0] = 0;
break;
// in progress so call again
case STATUS_INPROGRESS:
// record the step position of the last memory clear
// this is in case we need to attempt a clear again
if (script[StepCount].Step == ST_CLEAR_SETUP)
last_clear_step = StepCount;
// print step description if different
if (strcmp(LastDescription,
script[StepCount].StepDescription) != 0)
{
fprintf(fp,"%s --> ",script[StepCount].StepDescription);
sprintf(LastDescription,"%s",script[StepCount].StepDescription);
}
// perform a step in the job
ThermoStep(portnum,ThermoState,&script[StepCount],&SubStep,
&Status, &ErrorCount, msg);
// print results if different
if (strcmp(LastMsg,msg) != 0)
{
fprintf(fp,"%s\n",msg);
sprintf(LastMsg,"%s",msg);
}
else
fprintf(fp,".");
break;
// encountered a transient error
case STATUS_ERROR_TRANSIENT:
// check if transient error is a memory clear
if (script[StepCount].Step == ST_CLEAR_VERIFY)
{
// put back to starting clear over again
StepCount = last_clear_step;
SubStep = 0;
ErrorCount = 0;
Status = STATUS_INPROGRESS;
break;
}
// if 20 tansient errors in a row then abort
if (ErrorCount > 20)
Status = STATUS_ERROR_HALT;
else
Status = STATUS_INPROGRESS;
break;
// all steps complete
case STATUS_COMPLETE:
fprintf(fp,"End script normally\n");
return TRUE;
break;
// non-recoverable error
case STATUS_ERROR_HALT:
fprintf(fp,"Aborting script due to non-recoverable error\n");
return FALSE;
break;
}
}
while (!Serial0CharArrived());
// key abort
fprintf(fp,"Aborting script due to key press\n");
return FALSE;
}
//----------------------------------------------------------------------
// Use the script to perform a step and return.
//
int ThermoStep(int portnum, ThermoStateType *ThermoState,
ThermoScript *StateScript, int *SubStep,
int *Status, int *ErrorCount, char *msg)
{
short rslt;
static int read_page_num, read_pages, write_addr, write_len;
static uchar *read_buf, *write_buf;
static uchar tbuf[5];
ErrorCount; // hush the compiler
// do the current step
switch (StateScript->Step)
{
// the operation is complete
case ST_FINISH:
sprintf(msg,"Operation complete");
*Status = STATUS_COMPLETE;
break;
// read the mission status page
case ST_READ_STATUS:
read_page_num = STATUS_PAGE;
read_pages = 1;
read_buf = ThermoState->MissStat.status_raw;
sprintf(msg,"Ready to read status page %d",
read_page_num);
*Status = STATUS_STEP_COMPLETE;
break;
// set up to read the alarm registers
case ST_READ_ALARM:
read_page_num = 17;
read_pages = 3;
read_buf = ThermoState->AlarmData.alarm_raw;
sprintf(msg,"Ready to read alarm pages %d to %d",
read_page_num, read_page_num + read_pages - 1);
*Status = STATUS_STEP_COMPLETE;
break;
// set up to read the histogram data
case ST_READ_HIST:
read_page_num = 64;
read_pages = 4;
read_buf = ThermoState->HistData.hist_raw;
sprintf(msg,"Ready to read histogram pages %d to %d",
read_page_num, read_page_num + read_pages - 1);
*Status = STATUS_STEP_COMPLETE;
break;
// set up to read the log data
case ST_READ_LOG:
read_page_num = 128;
read_pages = 64;
read_buf = ThermoState->LogData.log_raw;
sprintf(msg,"Ready to read log pages %d to %d",
read_page_num, read_page_num + read_pages - 1);
*Status = STATUS_STEP_COMPLETE;
break;
// read the specified pages
case ST_READ_PAGES:
// check for last page
if (*SubStep == 0)
// set the sub-step to the current page being read
*SubStep = read_page_num;
// read the status page
rslt = ReadPages(portnum, read_page_num, read_pages, SubStep, read_buf);
if (rslt == FALSE)
{
sprintf(msg,"Thermochron not on 1-Wire Net");
*Status = STATUS_INPROGRESS;
}
else
{
sprintf(msg,"Pages read from Thermochron");
*Status = STATUS_STEP_COMPLETE;
}
break;
// setup the clear memory
case ST_CLEAR_SETUP:
// create a small buff to write to start the clear memory
tbuf[0] = 0x40;
write_buf = &tbuf[0];
write_len = 1;
write_addr = 0x20E;
sprintf(msg,"Write to setup clear memory");
*Status = STATUS_STEP_COMPLETE;
break;
// clear the memory
case ST_CLEAR_MEM:
// set the clear memory command (not check return because verify)
owAccess(portnum);
owWriteByte(portnum,0x3C);
msDelay(3);
owTouchReset(portnum);
sprintf(msg,"Clear memory command sent");
*Status = STATUS_STEP_COMPLETE;
break;
// clear the memory
case ST_CLEAR_VERIFY:
// look at the memory clear bit
if ((ThermoState->MissStat.status_raw[0x14] & 0x40) == 0x40)
{
sprintf(msg,"Memory is clear");
*Status = STATUS_STEP_COMPLETE;
break;
}
else
{
sprintf(msg,"Memory did NOT clear");
*Status = STATUS_ERROR_TRANSIENT;
break;
}
break;
// setup write time, clock alarm, control, trips
case ST_WRITE_TIME:
// create the write buffer
FormatMission(&ThermoState->MissStat);
write_buf = &ThermoState->MissStat.status_raw[0x00];
write_len = 13;
write_addr = 0x200;
sprintf(msg,"Write time, clock alarm, and trips setup");
*Status = STATUS_STEP_COMPLETE;
break;
// write the control, mission delay and clear flags
case ST_WRITE_CONTROL:
write_buf = &ThermoState->MissStat.status_raw[0x0E];
write_len = 7;
write_addr = 0x20E;
sprintf(msg,"Write control, mission delay, clear flags setup");
*Status = STATUS_STEP_COMPLETE;
break;
case ST_WRITE_RATE:
write_buf = &ThermoState->MissStat.status_raw[0x0D];
write_len = 1;
write_addr = 0x20D;
sprintf(msg,"Write sample rate setup");
*Status = STATUS_STEP_COMPLETE;
break;
// write the specified memory location
case ST_WRITE_MEM:
if (WriteMemory(portnum, write_buf, write_len, write_addr))
{
sprintf(msg,"Memory written to Thermochron");
*Status = STATUS_STEP_COMPLETE;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -