Untitled

 avatar
unknown
plain_text
14 days ago
55 kB
3
Indexable

#include <iom162.h>
#include <ina90.h>
#include <stdio.h>
#include <string.h>
#include "Flash_AT26DF161.h"

#include "TTSerial.h"  // Define PS021 register settings

// Select which Tool Serial number this is
// in order to load the correct set of PS021 regisers
//unsigned char reg_data[16][4];
ps021Regs_ ps021reg;

// Statoil Torque Counter runs without RCU.
// Uses extra connector to short circuit pin 13 on TorqueCounter card
// - This forces the Taring in this mode, note that the same connector
//   also turns on the torque counter so we need to wait some time
//   in order for the readings to stabilize, before accepting the
//   tara value.
// The NO_RCU_MODE define controls wether this functionality is implemented
//#define TESTING_NORCU

// LED defines
#define DISP_CS
#define Digit0_turn 0x23
#define Digit1_turn 0x22
#define Digit2_turn 0x21
#define Digit3_turn 0x20
#define Digit0_torque 0x27
#define Digit1_torque 0x26
#define Digit2_torque 0x25
#define Digit3_torque 0x24

// State LED defines
#define Comp_1 0x04
#define Comp_2 0x08
#define High 0x01
#define Low 0x02

//#define RS485_Mode (PORTG|=0x02)          //(1 << PC1)
#define RS232_Mode (PORTC&=0xFD)          //(0 << PC1)
//#define RS485_drive_enable (PORTC|=0x01)  //(1 << PC0)
//#define RS485_drive_disable (PORTC&=0xFE) //(0 << PC0)

// Communications defines
// TC = TurnsCounter
// TT = TorqueTool
#define TCVAL     0x10
#define TCRETCONF 0x30
#define TCGVAL    0x20
#define TCSVAL    0x90
#define TCRESET   0x40
#define TCSETCONF 0x60
#define TCREQCONF 0x80

#define TTVAL     0x14
#define TTRETCONF 0x34
#define TTGVAL    0x24
#define TTSVAL    0x94
#define TTRESET   0x44
#define TTSETCONF 0x64
#define TTREQCONF 0x84

#define _RQMODE  0x50  // Toggle request mode (only send count value if requested)

// Communication format ids
#define _STX     0xAA
#define _ETX     0x55

// EEPROM defines
#define CONFIG_DATA_START_REGISTER 0x10
#define TORQUE_CONFIG_DATA_START_REGISTER 0x30

// The message protocol
// We have four messages of which two only differ in cmd id.
// TCVAL is FROM TC
// TCGVAL, TCSVAL, TCRESET and TCCONF is TO TC

// Send Turns counter value and torque value
typedef struct {
  unsigned char start;  // TCSTX
  unsigned char cmd;    // TCVAL
  int turnsValue;       // Current Turns counter value, 0 = UINT_MAX/2
  int torqueValue;      // Current raw torque value
  unsigned char flags;  // status flage
  unsigned char end;    // TCETX
} TC_Value_;            // 7 bytes

// Request Turns counter value and Reset message
typedef struct {
  unsigned char start;  // TCSTX
  unsigned char cmd;    // TCRESET, TCGVAL or TCRGR
  unsigned char end;    // TCETX
} TC_Cmd_;              // 3 bytes

// Configuration message
typedef struct {
  unsigned char start;  // TCSTX
  unsigned char cmd;    // TCCONF
  float ratio;          // Number of pulses per turn multiplied with gear ratio
  unsigned char end;    // TCETX
} TC_Configuration_;    // 7 bytes

typedef struct {
  unsigned char start;  // TCSTX
  unsigned char cmd;    // TCCONF
  unsigned char idx;    // Index in EEPROM of this item
  long scaledVal;      // int value, stored by topside application
  long lVal;           // int value, fetched from current raw value
  unsigned char end;    // TCETX
} TT_Configuration_;    // 12 bytes
/*
typedef struct {
  unsigned char start;  // TCSTX
  unsigned char cmd;    // TTCONF
  unsigned char idx;    // Index in EEPROM of this item - idx = 0 => lVal gives count items stored
  long scaledVal;
  unsigned char end;    // TCSTX
} TT_Configuration_Rx_;    // 8 bytes
*/

#define false 0
#define true !false

// Variables to hold current messages
TC_Configuration_ tcConf;
TT_Configuration_ tqConf;
TC_Value_ tcVal;
//TT_Configuration_Rx_ tqRxCnf;

#define MSG_MAX_LEN 10

unsigned char Tx[MSG_MAX_LEN], Rx[MSG_MAX_LEN];
unsigned char Ex_power, Itf_box;
unsigned char rxIdx, txIdx;
unsigned char txSize;
unsigned char oldFlags;
unsigned char receivingMsg = false;

#ifdef NO_RCU_MODE
unsigned char ForceTaring;
unsigned char DoneTaring = 0x0;
long ForceWaitCount = 0;
#endif

// Logging of torque, turns and timestamp
unsigned char logPointer[3];  // Address of next data to log
unsigned char logStart[3] = {0x00, 0x01, 0x00}; // First position used for log data
unsigned char logEnd[3] = {0x1f, 0xff, 0xff};   // Last position used for log data

// Filter Torque readings
int torqueRawIdx = 0;
int torqueReadCount = 0;
#define TORQUE_AVG_COUNT 200
int torqueRaw[TORQUE_AVG_COUNT];
long lTmp;
char useSplitFilter; // boolean test, use Split Filter or Average Filter

// Scaling of torque values
char useScaling; // boolean Use Scaling or just display raw values
typedef struct {
long rawIn;     // raw input value
long scaledOut; // corresponding output value
} TorqueConfig_;
#define TORQUE_SCALEPAIR_COUNT 20

#ifdef NOEEPROM  

int countTTConfIdx = 12; // Hardcoded - should match number of used points

#if SERIAL_NO == 10
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 11
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2984, -2699},
    { -2553, -2309},
    { -1689, -1526},
    {  -903,  -811},
    {  -293,  -256},
    {   -26,   -33},
    {    47,    34},
    {   287,   257},
    {   963,   849},
    {  1772,  1562},
    {  2669,  2339},
    {  3109,  2734},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 12
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 13
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 14
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2900, -2692},
    { -2411, -2238},
    { -1520, -1490},
    {  -843,  -862},
    {  -241,  -273},
    {   -13,   -28},
    {    53,    30},
    {   274,   249},
    {   947,   854},
    {  1710,  1545},
    {  2538,  2300},
    {  3010,  2645},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 15
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 16
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -3017, -2702},
    { -2562, -2287},
    { -1669, -1491},
    {  -955,  -828},
    {  -324,  -254},
    {   -41,   -29},
    {    24,    29},
    {   288,   248},
    {   975,   818},
    {  1826,  1550},
    {  2694,  2352},
    {  3099,  2695},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 17
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 18
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 19
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 20
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 21
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 22
TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    /*  raw, scaled */ 
    { -2938, -2700},
    { -2579, -2355},
    { -1733, -1573},
    {  -891,  -817},
    {  -263,  -254},
    {   -29,   -31},
    {    46,    31},
    {   326,   271},
    {   996,   865},
    {  1801,  1543},
    {  2735,  2374},
    {  3150,  2744},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0},
    {     0,     0}
  };
#endif

#if SERIAL_NO == 99 

/* Basic configuration */

TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT] = {
    { 0, 0},{ 5, 5},{10,10},{15,15},{20,20},
    {25,25},{30,30},{35,35},{40,40},{45,45},
    {50,50},{55,55},{60,60},{65,65},{70,70},
    {75,75},{80,80},{85,85},{90,90},{95,95}
  };
#endif

#else

TorqueConfig_ ttConf[TORQUE_SCALEPAIR_COUNT]; // maximum 10 TorqueConfig_ pairs
int countTTConfIdx; // Number of TT Configurations, stored at idx 0

#endif
// used in readTorque function
long scaledValue;
long lastScaledValue;
char useMultiCalPoints;
char newVal = false;
int lowerIdx;
int upperIdx;
double deltaRaw;
double deltaScaled;
double deltaOffset;
double rawValue;
double tmpRaw;
double _a_;
double _b_;
//int countTTConfIdx; // Number of TT Configurations, stored at idx 0
int lastTTConfIdx;
/*
// Defined in ATF26DF161.h
typedef struct {
  int time;      // for now 1000
  int torque;    // value from display
  int turns;     // value from display
} LogDataBlock_; // 6 bytes
*/

LogDataBlock_ logDataBlock;
LogDataBlock_ lastlogDataBlock; // last item stored to flash

unsigned char digits [13]= {0x7E,   /* 0 */
                            0x30,   /* 1 */
                            0x6D,   /* 2 */
                            0x79,   /* 3 */
                            0x33,   /* 4 */
                            0x5B,   /* 5 */
                            0x5F,   /* 6 */
                            0x70,   /* 7 */
                            0x7F,   /* 8 */
                            0x7B,   /* 9 */
                            0x7C,   /* L */
                            0x5C,   /* o */
                            0x38};  /* b */

char ASCII [11] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.'};

char next_state, last_state;
unsigned char decimal, ones, tens, hundreds;
unsigned long power_down;
int intervalWriteCom;
unsigned char toggle;
unsigned long irqCount;

#define valIdx 0
#define rawIdx 1
#define lastRawIdx 2
#define pulsIdx 3
#define oldpulsIdx 4
#define torqueTarIdx 3
#define valTaredIdx 4
#define valBeforeScaledIdx 5
#define valScaledIdx 6

// Contains all input data
// raw and scaled values
typedef struct {
long turns[5];
long torque[7];
} SensorInput_;

SensorInput_ inp;

#define reqValIdx 0
#define reqConfIdx 1
#define storeConfIdx 2
#define minusIdx 3

char turnsCmd[4];
char torqueCmd[4];

unsigned char Data_Flash, dummy;
//unsigned char updateTorqueLed;

//char bReqValue = false; // turnsCmd[reqVal]
//char bReqConf = false;  // turnsCmd[reqConf]
//char bStoreCnf = false;   // turnsCmd[storeConf]
char bOnChangeMode = true; // default to transmit value onChange mode
char bDoTara = false;

signed char matrise[4][4] = {{0, 1, -1, 0},
                             {-1, 0, 0, 1},
                             {1, 0, 0, -1},
                             {0, -1, 1 ,0}};



//////////////////////
// Function prototypes
//////////////////////
void Write_Display(unsigned char Disp_data_H, unsigned char Disp_data_L);
void initHW(void);
unsigned char readCom(void);
unsigned char writeCom(void);
void checkPower(void);
void activateCom(void);
void powerDown(void);
void updateTurnsLED(void);
void updateTorqueLED(void);
void loadTurnsConfig(void);
void storeTurnsConfig(void);
#ifndef NOEEPROM
void loadTorqueConfig(void);
void storeTorqueConfig(void);
#endif
// Added from ToolControl\test.c 20070130 - so
void operation_mode_PS021(unsigned op_code);
void read_PS021(unsigned op_code);
void write_PS021(unsigned char op_code, unsigned char byte0, unsigned char byte1, unsigned char byte2);
void readTorque();
void readTorque2();
void scaleTorque();
void scaleTorque2();
void scaleTorque3();
void readFlags();
void writeLog();
//unsigned char valueChanged();

#ifdef NO_RCU_MODE
void checkForceTaring(void);
#endif


//////////////////////
// Interrupt handlers
//////////////////////
#pragma vector=INT0_vect
 __interrupt void INT0_interrupt()
{
}

#pragma vector=INT1_vect
 __interrupt void INT1_interrupt()
{
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////
//*Timer/counter 1 interrupt compare match. With 16MHz clock, this interupt will be executed every:
//*Ex-time = 1/16MHz*256*16 = 409.6us.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma vector=TIMER1_COMPA_vect
 __interrupt void TIMER1_COMPA_interrupt()
{
 /* Sample PortD at xxxHz*/
 /* CPU runs at 16MHz = 16*1000*1000 = 16000000 Hz */
 /* Interrupt is clkIO/256 => 16MHz/256 = 62500 Hz */
 /* A counter here increments turns every second*/

  // Read Turns Count
   next_state = PIND;
   next_state^= 0x0C;
   next_state&= 0x0C;
   next_state>>=  2;
   if(last_state != next_state)
   {
      inp.turns[rawIdx] = inp.turns[rawIdx] + matrise[last_state][next_state];
      inp.turns[valIdx] = inp.turns[rawIdx] * 100 / 872;
      /* 4 count on one magnet detection, 4 magnets on the weel */
      /* The gear is 1/5,45 (29,75),(29,83). */
      /* Count=4*4*5,45=87.2 (476),(477,78) count/rotation of the shaft */
      /* One rotation shall give 10 count, 1,0 on the display. */
      tcVal.turnsValue = (int)inp.turns[valIdx];
      turnsCmd[minusIdx] = inp.turns[valIdx] < 0;
      inp.turns[valIdx] *= ((turnsCmd[minusIdx]) ? -1 : 1);

      last_state = next_state;
      power_down = 0;
   }
   else
   {
      power_down++;
   }
    // interrupt test - inc counter every second
//    irqCount++;
//    if(62500 < irqCount)
//    {
//      logDataBlock.time++;
//      irqCount = 0;
//    }
//    turns[valIdx] = logDataBlock.time;
}

void main(void)
{
  int i;
  irqCount = 0;

  txSize = 0;
  toggle = 0;
  intervalWriteCom = 0;  // Try to force sending with interval if nothing has happened for a while

  tcVal.start = _STX;
  tcVal.cmd = TCVAL;
  tcVal.end = _ETX;

  tcConf.start = _STX;
  tcConf.ratio = ((16*5.45)*10);  // default value
  tcConf.end = _ETX;

  tqConf.start = _STX;
  tqConf.scaledVal = 0;
  tqConf.lVal = .0;
  tqConf.end = _ETX;

  turnsCmd[reqValIdx] = false;
  turnsCmd[reqConfIdx] = false;
  turnsCmd[storeConfIdx] = false;

  logDataBlock.address[0] = logStart[0];
  logDataBlock.address[1] = logStart[1];
  logDataBlock.address[2] = logStart[2];
  logDataBlock.time = 0;
  logDataBlock.torque = 0;
  logDataBlock.turns = 0;

  lastlogDataBlock.time = 0;
  lastlogDataBlock.torque = 0;
  lastlogDataBlock.turns = 0;

  inp.torque[torqueTarIdx] = 0;

//  updateTorqueLed = true;

  initHW();

  initPS021Regs( &ps021reg, SERIAL_NO );
// Added from ToolControl\test.c 20071030 - so
// block start
  //Power On Reset
  operation_mode_PS021(0x50);

  //PS021 Init Registers
  for(i=0;i<15;i++)
  {
    write_PS021(ps021reg.reg[i][0],ps021reg.reg[i][1],ps021reg.reg[i][2],ps021reg.reg[i][3]);
  };

  //Init
  operation_mode_PS021(0xC0);

  write_Config_Flash(0x06);

  write_Status_Flash(0x01, 0x02);
  write_Config_Flash(0x06);
  read_Status_Flash(0x05);

  write_Data_Flash(0x02, 0x00, 0x00, 0x04, 0x22);
  while(Data_Flash & 0x01)
    read_Status_Flash(0x05); //While busy
// block end

  __delay_cycles(5);
  loadTurnsConfig();
  
#ifndef NOEEPROM  
  
  /******************************************
  * Read torque configuration from EEPROM
  **/
  
  __delay_cycles(5);
  lastTTConfIdx = 0;
  loadTorqueConfig();  // Get countTTConfIdx
  __delay_cycles(5);
  for(i=1; i < countTTConfIdx; i++ )
  {
    lastTTConfIdx = i; // Increment pointer
    loadTorqueConfig(); // Get config value at position lastTTConfIdx
    __delay_cycles(5);
  }
  
#endif

  lastTTConfIdx = 0;
  __delay_cycles(5);

  Write_Display(0x04,0x01); //Configuration
  Write_Display(0x01,0x00); //Decode mode
  Write_Display(0x02,0x00); //Intensity
  Write_Display(0x03,0x07); //scan Limit
  //Write_Display(0x07,0x01); //Display test

  // Set Average Torque values to zero
  for(i=0; i<TORQUE_AVG_COUNT; i++)
  {
    torqueRaw[i] = 0;
  }

  // Set default operation
  useSplitFilter = false;    // Filter Torque using SplitFilter or Average Filter
  useScaling = true;         // Scale torque values or just display raw readings
  useMultiCalPoints = true;  // Scale using only two values ore ttConf arrary

  operation_mode_PS021(0x01); // Start new measurement
#ifdef NO_RCU_MODE
  ForceWaitCount = 0;
#endif  
  _SEI();              // Enable interupt

  while (1)
  {
    readFlags();
    checkPower();

#ifdef NO_RCU_MODE
    checkForceTaring();
#endif    
//#else
    writeCom();
    readCom();
//#endif

    updateTurnsLED();
    if(500 < intervalWriteCom )
    {
      updateTorqueLED();
      writeLog();
    }

    powerDown();
//    activateCom();

    if(turnsCmd[storeConfIdx])
      storeTurnsConfig();

#ifndef NOEEPROM
    if(torqueCmd[storeConfIdx])
      storeTorqueConfig();
#endif
    newVal = false;
    if(false == receivingMsg)
    {
      //torqueReadCount = torqueRawIdx;
      if(0 == intervalWriteCom%3)
      {
        readTorque2();
      }
    }

    if( 500 < intervalWriteCom)
    {
      intervalWriteCom = 0;
    }
    intervalWriteCom++;
  }
}


void readFlags()
{
  tcVal.flags = 0x0; // clear
  // Check Status Lights
  if(!(PINA & Comp_1))
  {
    tcVal.flags |= Comp_1;
    PORTA&= 0x7F;
  }
  else
  {
    PORTA|= 0x80;
  }

  if(!(PINA & Comp_2))
  {
    tcVal.flags |= Comp_2;
    PORTA&= 0xBF;
  }
  else
  {
    PORTA|= 0x40;
  }

#ifndef TESTING_NORCU
  
  if(!(PINA & High))
  {
    tcVal.flags |= High;
    PORTA&= 0xDF;
  }
  else
  {
    PORTA|= 0x20;
  }

// Use Low status to check if we're able to turn on or off the pin
  
  if(!(PINA & Low))
  {
    tcVal.flags |= Low;
    PORTA&= 0xEF;
  }
  else
  {
    PORTA|= 0x10;
  }
  
#endif
  
}

void scaleTorque()
{
  int k;

  inp.torque[valBeforeScaledIdx] = inp.torque[valTaredIdx];

  rawValue = inp.torque[valBeforeScaledIdx];

  useMultiCalPoints = true;  // Select whether to use 2 points or several points

  if(false == useMultiCalPoints)
  {
    // NOTE These values are approximates
    if(0 < rawValue)
    {
      // Negative axis, but the number in rawValue is positive
      scaledValue = (int)(rawValue * 4.376950895);
    }
    else
    {
      // NOTE
      // Positive axis, but the number in rawValue is negative
      scaledValue = (int)(rawValue * 4.12553271);
    }
  }
  else
  {
    // Must get limits at either side of rawValue
    // check if value is positive
    // Note this value is inverted (negative results in positive)
    tmpRaw = rawValue * -1;

    if(0 < rawValue)
    {
      // Negative axis, but the number in rawValue is positive
      upperIdx = 0; // Set both to lowest calibration point
      lowerIdx = 1;
      // Locate limit below and abov rawvalue
      //   values are:
      //    idx 0 => lowest negative calibration point
      //    idx countTTConfIdx -1 => highest positive calibration point
      for(k = 0; k < countTTConfIdx; k++)
      {
        if(  tmpRaw >ttConf[k].rawIn)
        {
          // Select points at either side of tmpRaw
          lowerIdx = k+1;
          upperIdx = k;
        }
      }

      if(lowerIdx >= countTTConfIdx-1)
      {
        lowerIdx = countTTConfIdx-1; // last possible index
      }
    }
    else
    {
      // Positive axis, but the number in rawValue is negative
      upperIdx = countTTConfIdx -1; // Set both to highest calibration point
      lowerIdx = upperIdx -1;
      // Locate limit below and abov rawvalue
      //   values are:
      //    idx 0 => highest positive calibration point
      //    idx countTTConfIdx -1 => lowest negative calibration point
      for(k = countTTConfIdx -1; k > -1; k--) // Step down from last position
      {
        if( tmpRaw < ttConf[k].rawIn)
        {
          upperIdx = k;
          lowerIdx = k-1;
        }
      }
      if(lowerIdx <= 0)
      {
        lowerIdx = 0; // first possible index
      }
    }

    // Linear scaling
    deltaRaw = ttConf[upperIdx].rawIn - ttConf[lowerIdx].rawIn;
    deltaScaled = ttConf[upperIdx].scaledOut - ttConf[lowerIdx].scaledOut;
    deltaOffset = ( ttConf[lowerIdx].scaledOut * ttConf[upperIdx].rawIn ) -
                  ( ttConf[upperIdx].scaledOut * ttConf[lowerIdx].rawIn);

    // Note: If value is outside calibration points, get factor from outer point only
    if(0 == deltaRaw)
    {
      deltaRaw = ttConf[upperIdx].rawIn;
    }
    if(0 == deltaScaled)
    {
      deltaScaled = ttConf[upperIdx].scaledOut;
    }

    _a_ = (deltaScaled / deltaRaw);
    _b_ = (deltaOffset / (deltaRaw));
    scaledValue = (long)((_a_ * rawValue) + _b_);
  }
  inp.torque[valScaledIdx] = scaledValue;
}

void scaleTorque2()
{
  int k;

  inp.torque[valBeforeScaledIdx] = inp.torque[valTaredIdx];

  rawValue = inp.torque[valBeforeScaledIdx];

  useMultiCalPoints = true;  // Select whether to use 2 points or several points

  if(false == useMultiCalPoints)
  {
    // NOTE These values are approximates
    if(0 < rawValue)
    {
      // Negative axis, but the number in rawValue is positive
      scaledValue = (int)(rawValue * 4.376950895);
    }
    else
    {
      // NOTE
      // Positive axis, but the number in rawValue is negative
      scaledValue = (int)(rawValue * 4.12553271);
    }
  }
  else
  {
    // Must get limits at either side of rawValue
    // Locate limit below and abov rawvalue
    //   values are:
    //    idx 0 => highest positive calibration point
    //    idx countTTConfIdx -1 => lowest negative calibration point

    // invert all values ---

    upperIdx = 0; // Set both to lowest calibration point
    lowerIdx = 1;

    for(k = 0; k < countTTConfIdx; k++)
    {
      if( rawValue < ttConf[k].rawIn )
      {
        // Select points at either side of tmpRaw
        upperIdx = k;
        lowerIdx = k+1;

        if(lowerIdx == countTTConfIdx)
        {
          // Keep within range
          lowerIdx--;
          upperIdx--;
        }
        // let loweidx be the smallest value
        if(ttConf[lowerIdx].rawIn > ttConf[upperIdx].rawIn)
        {
          // swap
          upperIdx = k+1;
          lowerIdx = k;
        }
        if(upperIdx == countTTConfIdx)
        {
          // Keep within range
          lowerIdx--;
          upperIdx--;
        }
      }
    }

    // Linear scaling
    deltaRaw = (ttConf[upperIdx].rawIn) - (ttConf[lowerIdx].rawIn);

    deltaScaled = (ttConf[upperIdx].scaledOut) - (ttConf[lowerIdx].scaledOut);

    deltaOffset = ( ttConf[lowerIdx].scaledOut * ttConf[upperIdx].rawIn) -
                  ( ttConf[upperIdx].scaledOut * ttConf[lowerIdx].rawIn);

    // Note: If value is outside calibration points, get factor from outer point only
    if(0 == deltaRaw)
    {
      deltaRaw = ttConf[upperIdx].rawIn;
    }

    _a_ = (deltaScaled / deltaRaw);
    _b_ = (deltaOffset / deltaRaw);

    scaledValue = (long)((_a_ * rawValue) + _b_);
  }
  inp.torque[valScaledIdx] = scaledValue;
}

void scaleTorque3()
{
  int k;
  //int tmp;

  inp.torque[valBeforeScaledIdx] = inp.torque[valTaredIdx];
  rawValue = inp.torque[valBeforeScaledIdx];

  // Must get limits at either side of rawValue
  // Locate limit below and abov rawvalue

  upperIdx = 0; // Set both to lowest calibration point
  lowerIdx = 1;

  for(k = 0; k < countTTConfIdx; k++)
  {
    if( inp.torque[valBeforeScaledIdx] > ttConf[k].rawIn )
    {
      // Select points at either side of tmpRaw
      upperIdx = k;
      lowerIdx = k+1;
    }
    else
    {
      break;
    }
  }
  
  if(lowerIdx == countTTConfIdx)
  {
    // Keep within range
    lowerIdx--;
    upperIdx--;
  }  

  // Linear scaling
  deltaRaw = (ttConf[upperIdx].rawIn) - (ttConf[lowerIdx].rawIn);

  deltaScaled = (ttConf[upperIdx].scaledOut - ttConf[lowerIdx].scaledOut);

  deltaOffset = ( ttConf[lowerIdx].scaledOut * ttConf[upperIdx].rawIn) -
                ( ttConf[upperIdx].scaledOut * ttConf[lowerIdx].rawIn);

  // Note: If value is outside calibration points, get factor from outer point only
  if(0 == deltaRaw)
  {
    deltaRaw = ttConf[upperIdx].rawIn;
  }

  _a_ = (deltaScaled / deltaRaw);
  _b_ = (deltaOffset / deltaRaw);

  scaledValue = (long)((_a_ * (rawValue)) + _b_);

  inp.torque[valScaledIdx] = scaledValue;

  lastScaledValue = scaledValue;
}

// Read Torque
void readTorque2()
{
  int k;
  long tmpTorque = 0;

  if(!(PINC & 0x40))
  {
    read_PS021(0xB0);  // Updates inp.torque[rawIdx]
    operation_mode_PS021(0x01); // Start new measurement
  }

  // Test with values
  //inp.torque[rawIdx] = 300;
  
  // Invert the value
//  tmpTorque = inp.torque[rawIdx] * -1;
//  inp.torque[rawIdx] = tmpTorque;

  // Use average filter
  torqueRaw[torqueRawIdx] = inp.torque[rawIdx];

  lTmp = 0;

  for(k=0; k<TORQUE_AVG_COUNT; k++)
  {
    lTmp += torqueRaw[k];
  }

//  inp.torque[valIdx] = (int)(( lTmp / TORQUE_AVG_COUNT) * -1);
  inp.torque[valIdx] = (int)( lTmp / TORQUE_AVG_COUNT);
  // Invert torque value
  tmpTorque = inp.torque[valIdx];
  tmpTorque = tmpTorque -1;
  tmpTorque = ~tmpTorque;  
  inp.torque[valIdx] = tmpTorque;
  
  torqueRawIdx++;

  if(TORQUE_AVG_COUNT <= torqueRawIdx )
  {
    torqueRawIdx = 0;
  }

  if(true == bDoTara)
  {
    // set tara value
    inp.torque[torqueTarIdx] = inp.torque[valIdx];
    inp.torque[valTaredIdx] = 0;
    bDoTara = false;
  }
  else
  {
    // subtract tara value
//    inp.torque[valTaredIdx] = inp.torque[torqueTarIdx] - inp.torque[valIdx];
    inp.torque[valTaredIdx] = inp.torque[valIdx] - inp.torque[torqueTarIdx];
  }

  useScaling = ((0 == countTTConfIdx) ? false : true) ;

  if(true == useScaling)
  {
    scaleTorque3();
  }
  else // if( true == useScaling )
  {
    // just transfer raw values
    inp.torque[valScaledIdx] = inp.torque[valTaredIdx];
  }

  if((0 == countTTConfIdx))
  {
    // just transfer raw values
    inp.torque[valScaledIdx] = inp.torque[valTaredIdx];
  }

}


// Read Torque
void readTorque()
{
  int splitfactor;
  splitfactor = 200;
  int k;

  if(!(PINC & 0x40))
  {
    read_PS021(0xB0);  // Updates inp.torque[rawIdx]
    newVal = true;
  }
  operation_mode_PS021(0x01);

  if(true == newVal)
  {
    newVal = false;
    useSplitFilter = false;

    if(true == useSplitFilter)
    {
      // reduce flicker in display
      inp.torque[valIdx] = (int)(
          (
            ( inp.torque[valIdx] * (splitfactor -1) ) + (inp.torque[rawIdx] * 1)
          ) / splitfactor
        );
    }
    else
    {
      // Use average filter
      torqueRaw[torqueRawIdx] = inp.torque[rawIdx];

      lTmp = 0;

      for(k=0; k<TORQUE_AVG_COUNT; k++)
      {
        lTmp += torqueRaw[k];
      }

      inp.torque[valIdx] = (int)( lTmp / TORQUE_AVG_COUNT);

      torqueRawIdx++;

      if(TORQUE_AVG_COUNT <= torqueRawIdx )
      {
        torqueRawIdx = 0;
      }
    }

    if(true == bDoTara)
    {
      // set tara value
      inp.torque[torqueTarIdx] = inp.torque[valIdx];
      inp.torque[valTaredIdx] = 0;
      bDoTara = false;
    }
    else
    {
      // subtract tara value
      inp.torque[valTaredIdx] = inp.torque[torqueTarIdx] - inp.torque[valIdx];
    }

    useScaling = ((0 == countTTConfIdx) ? false : true) ;

    if(true == useScaling)
    {
      scaleTorque3();
    }
    else // if( true == useScaling )
    {
      // just transfer raw values
      inp.torque[valScaledIdx] = inp.torque[valTaredIdx];
    }
  }
}

void writeLog()
{
  unsigned char *pData;
  unsigned char idx;

  // Get new timestamp from Real Time Clock
  logDataBlock.time++;

  // compare Timestamp, if equal or greater write log
  // and update address for next write operation
  if(((lastlogDataBlock.time + 1) <= logDataBlock.time) )
  {
    // First three items are just address - skip pointer past these
    pData = (unsigned char*)&logDataBlock.time; // Set pointer to first item in block

    for(idx = 0; idx < (sizeof(LogDataBlock_)-3); idx++)  // address is three bytes
    {
      // write Log data to flash
      write_Data_Flash(0x02,
        logDataBlock.address[0],
        logDataBlock.address[1],
        logDataBlock.address[2] + idx,
        *pData);
    }
    // set next position
    logDataBlock.address[2] += idx;

    // copy written data to lastLog
    lastlogDataBlock.time = logDataBlock.time;
    lastlogDataBlock.torque = logDataBlock.torque;
    lastlogDataBlock.turns = logDataBlock.turns;

    // Verify that next pos have room for new datablock
    // if not recalc position
    if((logEnd[2] - (sizeof(LogDataBlock_) - 3)) < (logDataBlock.address[2]))  // address is three bytes
    {
      // last byte exceeds registers
      if(logEnd[1] > logDataBlock.address[1])
      {
        logDataBlock.address[1]++;
        logDataBlock.address[2] = 0x00;
      }
      else
      {
        if(logEnd[0] > logDataBlock.address[0])
        {
          logDataBlock.address[0]++;
          logDataBlock.address[1] = 0x00;
          logDataBlock.address[2] = 0x00;
        }
        else
        {
          // no more space in flash
          // reset pointer to first position
          logDataBlock.address[0] = logStart[0];
          logDataBlock.address[1] = logStart[1];
          logDataBlock.address[2] = logStart[2];
        }
      }
    }
  }
}

/////////////////////////////////////////////////////////////////////////////////////
//* Function that write data too PS021                                            *//
//  Function copied from ToolControl\test.c 20070130 - so
/////////////////////////////////////////////////////////////////////////////////////
void write_PS021(unsigned char op_code, unsigned char byte0, unsigned char byte1, unsigned char byte2)
{
  SPCR = 0x55;      //Enable ISP, Master, set SPCR register, fosc/8
  SPSR = 0x01;      //SPI freq*2
  PORTE&=0xFB;      //PS021 CS =0
  SPSR&=0xBF;       //WCOL set to 0

  SPDR = op_code;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero

  SPDR = byte0; //0xD4;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero

  SPDR = byte1; //0x09;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero

  SPDR = byte2; //0x22;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero
  dummy = SPDR;

  PORTE|=0x04;     //PS021 CS =1

  __delay_cycles(10);
}

/////////////////////////////////////////////////////////////////////////////////////
//* Function that read data on PS021                                              *//
//  Function copied from ToolControl\test.c 20070130 - so
/////////////////////////////////////////////////////////////////////////////////////
void read_PS021(unsigned op_code)
{
  unsigned char oldState;
  unsigned char torque_byte[4];

  SPCR = 0x55;      //Enable ISP, Master, set SPCR register, fosc/8
  SPSR = 0x01;      //SPI freq*2
  PORTE&=0xFB;      //PS021 CS =0
  SPSR&=0xBF;       //WCOL set to 0

  oldState = __save_interrupt();
  __disable_interrupt();   // Interrupts are disabled

  SPDR = op_code;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero
  dummy = SPDR;

  SPDR = op_code;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero
  torque_byte[0] = SPDR; // Most sig byte

  SPDR = op_code;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero
  torque_byte[1] = SPDR;

  SPDR = op_code;
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero
  torque_byte[2] = SPDR; // Least sig byte

  __restore_interrupt(oldState);

  // Transfer torque value to global input variable
  inp.torque[rawIdx] = ((torque_byte[0] << 8) + torque_byte[1]);

  PORTE|=0x04;     //PS021 CS =1
  __delay_cycles(3);
}
/////////////////////////////////////////////////////////////////////////////////////
//* Function that start diferent operation mode on PS021                                              *//
//  Function copied from ToolControl\test.c 20070130 - so
/////////////////////////////////////////////////////////////////////////////////////
void operation_mode_PS021(unsigned op_code)
{
  SPCR = 0x55;      //Enable ISP, Master, set SPCR register, fosc/8
  SPSR = 0x01;      //SPI freq*2
  PORTE&=0xFB;           //PS021 CS =0
  SPDR = op_code;        //Operation code
  while(!(SPSR & 0x80)); // Wait until SPIF bit in SPI Status register SPSR is zero
  dummy = SPDR;
  PORTE|=0x04;           //PS021 CS =1
  __delay_cycles(10);
}


/*
* Read communications port
* Return number of bytes received
*/
unsigned char readCom(void)
{

  unsigned char Size = 0;

  //UART read and store next byte
  if(UCSR0A & 0x80) {

    Rx[rxIdx]=UDR0;
    if(Rx[0] == _STX){
      receivingMsg = true;
      rxIdx++; // Correct start character ?
      switch(Rx[1]){  // Get size of msg
        case TCGVAL:
        case TTGVAL:
          Size = sizeof(TC_Cmd_); break;
        case TCSVAL:
        case TTSVAL:
          Size = sizeof(TC_Value_); break;
        case TCRESET:
        case TTRESET:
          Size = sizeof(TC_Cmd_); break;
        case _RQMODE:
          Size = sizeof(TC_Cmd_); break;
        case TCSETCONF:
          Size = sizeof(TC_Configuration_); break;
        case TTSETCONF:
//          Size = sizeof(TT_Configuration_Rx_); break;
          Size = 8; break;
        case TCREQCONF:
        case TTREQCONF:
          Size = sizeof(TC_Cmd_); break;
        default:
          Size = rxIdx-1; break; // still reading bytes
      }
    }
    else {
      rxIdx = 0; // waiting for start character
    }

    if(rxIdx == Size) {
      rxIdx = 0;  // reset index
      receivingMsg = false;
      // Get last Rx message
      switch(Rx[1]){  // Get size of msg
        case TCGVAL:
          inp.turns[lastRawIdx]--;
          turnsCmd[reqValIdx] = true;
          break;
        case TTGVAL:
          inp.torque[lastRawIdx]--;
          torqueCmd[reqValIdx] = true;
          break;
        case TCSVAL:
          memcpy(&tcVal, Rx, Size);
          inp.turns[valIdx] = tcVal.turnsValue;
          break;
        case TTSVAL:
          memcpy(&tcVal, Rx, Size);
          inp.torque[valIdx] = tcVal.torqueValue;
          break;
        case TCRESET:
          inp.turns[valIdx] = inp.turns[rawIdx] = inp.turns[pulsIdx] = inp.turns[oldpulsIdx] = 0;
          turnsCmd[minusIdx] = false;
          tcVal.turnsValue = inp.turns[rawIdx];
          break;
        case TTRESET:
          bDoTara = true;
          break;
        case TCSETCONF:
          memcpy(&tcConf, Rx, Size);
          turnsCmd[storeConfIdx] = true;
          break;
        case TTSETCONF:
          memcpy(&tqConf, Rx, Size); // Note that object in Rx buffer is smaller than tqConf
          torqueCmd[storeConfIdx] = true;
          break;
        case TCREQCONF:
          turnsCmd[reqConfIdx] = true;
          break;
        case TTREQCONF:
          torqueCmd[reqConfIdx] = true;
          break;
        case _RQMODE:  // Turn off transmit value onChange
          bOnChangeMode = false;
          break;
      }
    }
  }
  return Size;
}

/*
* Write data to serial port
* return index of last written byte, 0 if first or no bytes to write
*/
unsigned char writeCom(void)
{
  unsigned char valChanged = 0;
  valChanged = ( ( oldFlags != tcVal.flags )
                 || (inp.turns[lastRawIdx] != inp.turns[rawIdx])  // Use raw changes for sending turns
                 || 500 < intervalWriteCom );

  if( valChanged && (0 == txIdx) )
  {
    if(turnsCmd[reqConfIdx]){
      // TCREQCONF received
      turnsCmd[reqConfIdx] = false;
      tcConf.cmd = TCRETCONF;
      txSize = sizeof(tcConf);
      memcpy(Tx,&tcConf,txSize);
    }
    else{
      // Normal send current turns counter value
      txSize = sizeof(tcVal);
      tcVal.torqueValue = inp.torque[valScaledIdx];
      memcpy(Tx,&tcVal,txSize);

#ifdef NO_RCU_MODE      
      if(ForceTaring)
      {
        if(0 == DoneTaring)
        {
          ForceWaitCount++;
        }
      }
#endif      
    }
  }

  if( (  (txIdx != 0)   || valChanged )
      && (bOnChangeMode || turnsCmd[reqValIdx])
    )
  {
    /* Only send if empty transmit buffer */
    if( UCSR0A & (1<<UDRE0))  /*UART write*/
    {
      UDR0 = Tx[txIdx];
      txIdx++;
      UCSR0A=UCSR0A;
      if( txIdx >= 8) {
        txIdx = 0;
        inp.turns[lastRawIdx] = inp.turns[rawIdx];
        oldFlags = tcVal.flags;
      }

      if((turnsCmd[reqValIdx]) &&(txIdx == 0)) {
        turnsCmd[reqValIdx] = false;
      }

    }
  }
  return txIdx;
}

/**
* storeConfig()
* simple task; stores configuration in EEPROM
*/
void storeTurnsConfig(void){

  unsigned char oldState;
  unsigned int i=0;
  unsigned char *pData = (unsigned char *) &tcConf;
  unsigned int uiReg = CONFIG_DATA_START_REGISTER;
  oldState = __save_interrupt();
  __disable_interrupt();   // Interrupts are disabled

  // Write data to EEPROM
  for(i=0;i<sizeof(tcConf);i++) {
    // Wait for previous write to complete
    while(EECR & (1<<EEWE))
      ;
    // Set up address and data register
    uiReg = i + CONFIG_DATA_START_REGISTER;
    EEAR = uiReg;
    EEDR = *pData;

    // Write logical one to EEMWE
    EECR |= (1<<EEMWE);
		
    // Start eeprom write by setting EEWE
    EECR |= (1<<EEWE);
    pData++;
  }
	
  // Wait for previous write to complete
  while(EECR & (1<<EEWE))
    ;	

  turnsCmd[storeConfIdx] = false;
  __restore_interrupt(oldState);
}

/**
* loadConfig()
* simple task; loads configuration from EEPROM
* NOTE: only reads configuration if first byte equals TCSTX
*/
void loadTurnsConfig(void){
  unsigned int i;
  unsigned int uiReg;
  unsigned char *pData = (unsigned char *) &tcConf;
  unsigned char Tmp;
  unsigned char oldState;
  oldState = __save_interrupt();
  __disable_interrupt();  // Interrupts are disabled

  // Wait for previous write to complete
  while(EECR & (1<<EEWE))
    ;	

  // First byte should be TCSTX
  uiReg = CONFIG_DATA_START_REGISTER;
  EEAR = uiReg;
  // Start eeprom read by setting EERE
  EECR |= (1<<EERE);
  // Get Data
  Tmp = EEDR;

  // Check that first byte is valid
  if (_STX == Tmp) {
    for(i=0; i<sizeof(tcConf); i++) {
      while(EECR & (1<<EEWE))
        ;	
      // Set up address and data register
      uiReg = i + CONFIG_DATA_START_REGISTER;
      EEAR = uiReg;

      // Start eeprom read by setting EERE
      EECR |= (1<<EERE);

      // Get Data
      *pData = EEDR;
      pData++;
    }
  }
  __restore_interrupt(oldState);
}

#ifndef NOEEPROM

/**
* storeTorqueConfig()
* simple task; stores configuration in EEPROM
*
* Sample config as stored in EEPROM file
* :10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
* :100030000 00C0000009EF9FFFFFFFFFFFFFFFFFF26
* idx: 00, lVal: 0C000000, scaledVal: 9EF9FFFF
*                12                   
* :10004000 01 5BF5FFFF 12F4FFFF FFFFFFFFFFFFFF64
* :10005000 02 FAF6FFFF A3F5FFFF FFFFFFFFFFFFFF21
* :10006000 03 E8F9FFFF 1EF9FFFF FFFFFFFFFFFFFFA0
* :10007000 04 DBFCFFFF 77FCFFFF FFFFFFFFFFFFFF3D
* :10008000 05 F2FEFFFF FDFEFFFF FFFFFFFFFFFFFF8B
* :10009000 06 E2FFFFFF E3FFFFFF FFFFFFFFFFFFFFA2
* :1000A000 07 1E000000 26000000 FFFFFFFFFFFFFF0C
* :1000B000 08 0E010000 3C010000 FFFFFFFFFFFFFFF3
* :1000C000 09 34030000 C4030000 FFFFFFFFFFFFFF30
* :1000D000 0A 22060000 76070000 FFFFFFFFFFFFFF78
* :1000E000 0B 1A090000 D50A0000 FFFFFFFFFFFFFF0A
* :1000F000 0C AF0A0000 A40C0000 FFFFFFFFFFFFFF92
*
* :10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
*/
void storeTorqueConfig(void){

  unsigned char oldState;
  unsigned int i=0;
  unsigned char *pData = (unsigned char *) &tqConf.idx;
  unsigned int uiReg = TORQUE_CONFIG_DATA_START_REGISTER;
  unsigned int blockSize = sizeof(tqConf.scaledVal) + sizeof(tqConf.lVal) + sizeof(tqConf.idx);
  unsigned int startReg = 0;

//  lastTTConfIdx = tqConf.idx;
  tqConf.lVal = inp.torque[valTaredIdx];

  //tqConf.lVal *= -1;

  if(0 < tqConf.idx)
  {
    ttConf[tqConf.idx -1].rawIn = tqConf.lVal;
    ttConf[tqConf.idx -1].scaledOut = tqConf.scaledVal;
  }

  startReg = (tqConf.idx * 16) + TORQUE_CONFIG_DATA_START_REGISTER;

  oldState = __save_interrupt();
  __disable_interrupt();          // Interrupts are disabled

  // Write data to EEPROM
  for(i=0; i < blockSize; i++) {
    // Wait for previous write to complete
    while(EECR & (1<<EEWE))
      ;
    // Set up address and data register
    uiReg = i + startReg;
    EEAR = uiReg;
    EEDR = *pData;

    // Write logical one to EEMWE
    EECR |= (1<<EEMWE);
		
    // Start eeprom write by setting EEWE
    EECR |= (1<<EEWE);
    pData++;
  }
	
  // Wait for previous write to complete
  while(EECR & (1<<EEWE))
    ;	

  __restore_interrupt(oldState);

  torqueCmd[storeConfIdx] = false;

  if(0 == tqConf.idx)
  {
    countTTConfIdx = tqConf.scaledVal;
    if(TORQUE_SCALEPAIR_COUNT < countTTConfIdx)
    {
      countTTConfIdx = TORQUE_SCALEPAIR_COUNT;
    }
  }
}


/**
* loadTorqueConfig()
* simple task; loads configuration from EEPROM
* NOTE: only reads configuration if first byte equals TCSTX
*/
void loadTorqueConfig(void){
  unsigned int i;
  unsigned int uiReg;
  TT_Configuration_ tmpTqConf;
  unsigned char *pData = (unsigned char *) &tmpTqConf.idx;
  unsigned char oldState;
  unsigned char tmp;
  unsigned int blockSize = sizeof(tmpTqConf.scaledVal) + sizeof(tmpTqConf.lVal) + sizeof(tmpTqConf.idx);
  unsigned char startReg = 0;

  startReg = (lastTTConfIdx * 16) + TORQUE_CONFIG_DATA_START_REGISTER;

  oldState = __save_interrupt();
  __disable_interrupt();      // Interrupts are disabled

  // Wait for previous write to complete
  while(EECR & (1<<EEWE))
    ;	

  // Check if EEPROM is blank, first item should be 0x00
  uiReg = TORQUE_CONFIG_DATA_START_REGISTER;
  EEAR = uiReg;

  // Start eeprom read by setting EERE
  EECR |= (1<<EERE);

  // Get Data
  tmp = EEDR;

  if((0x0 == tmp) )
  {
    // Read config stored at lastTTConfIdx
    for(i=0; i<blockSize; i++)
    {
      while(EECR & (1<<EEWE))
        ;	
      // Set up address and data register
      uiReg = i + startReg;
      EEAR = uiReg;

      // Start eeprom read by setting EERE
      EECR |= (1<<EERE);

      // Get Data
      *pData = EEDR;
      pData++;
    }

    if(0 == lastTTConfIdx) // Reading at index 0, update counter
    {
      countTTConfIdx = tmpTqConf.scaledVal;
    }
    else
    {
      ttConf[lastTTConfIdx -1].rawIn = tmpTqConf.lVal;
      ttConf[lastTTConfIdx -1].scaledOut = tmpTqConf.scaledVal;
    }
  }
  __restore_interrupt(oldState);
}

#endif

void updateTurnsLED(void)
{


    decimal = inp.turns[valIdx]%10;
    ones = (inp.turns[valIdx]/10)%10;
    tens = (inp.turns[valIdx]/100)%10;
    hundreds = (inp.turns[valIdx]/1000)%10;
/*
    decimal = torqueReadCount%10;
    ones = (torqueReadCount/10)%10;
    tens = (torqueReadCount/100)%10;
    hundreds = (torqueReadCount/1000)%10;
*/
    Write_Display(Digit0_turn,digits[decimal]);
    Write_Display(Digit1_turn,(digits[ones]|0x80));
    Write_Display(Digit2_turn,digits[tens]);
    Write_Display(Digit3_turn,digits[hundreds]);

    if(turnsCmd[minusIdx])
      PORTB&= 0xFE;
    else
      PORTB|=0x01;
}

void updateTorqueLED(void)
{
    long torqueVal = inp.torque[valScaledIdx];

    if(0 > inp.torque[valScaledIdx])
    {
      PORTB&= 0xFD; // Turn on
      torqueVal = torqueVal -1;
      torqueVal = ~torqueVal;
    }
    else
      PORTB|=0x02;  // Turn off

    decimal = torqueVal%10;
    ones = (torqueVal/10)%10;
    tens = (torqueVal/100)%10;
    hundreds = (torqueVal/1000)%10;

    Write_Display(Digit0_torque,digits[decimal]); //Rx[0]
    Write_Display(Digit1_torque,(digits[ones])); //|0x80
    Write_Display(Digit2_torque,digits[tens]);
    Write_Display(Digit3_torque,digits[hundreds]);
}

void powerDown(void)
{
  if((power_down > 600000) && !Ex_power) {

    Write_Display(0x04,0x00); //Configuration
    //PORTE = 0xFF;
    //PORTA = 0xFF;
    //PORTC|= 0x80;
    //PORTC&=0xF0;
    TIMSK = 0x00;  /* Timer1 compareA match interrup disable, Timer0 overflow disable */
    switch(next_state){/* Sleep enable, idle mode, iNT0 and iNT1 on the rising edge */
      case 3:MCUCR = 0x2F; break;
      case 2:MCUCR = 0x2C; break;
      case 1:MCUCR = 0x23; break;
      case 0:MCUCR = 0x2A; break;
    }

    GICR = 0xC0;        /* iNT0 and iNT1 enable */
    _SLEEP();
    GICR = 0x00;        /* iNT0 and iNT1 disable */
    TIMSK = 0x42;        /* Timer1 compareA match interrup enable, Timer0 overflow enable */
    Write_Display(0x04,0x01); //Configuration

//    PORTC|=0x02;
    power_down = 0;
  }
}

void activateCom(void)
{
//  PORTC = ((Ex_power)? (Comm_ON) : (Comm_OFF));
}

void checkPower(void)
{
    Ex_power = ACSR & 0x20;
    //Itf_box = (0 == (PIND & 0x40)); // Interface box at PORTD pin6
}

#ifdef NO_RCU_MODE
// Check if the pins are shorted
void checkForceTaring(void)
{
    ForceTaring = (0 == (PIND & 0x80)); // Short circuited
    
#ifdef TESTING_NORCU
  
  if(ForceTaring)
  {
    PORTA&= 0xEF;
  }
  else
  {
    PORTA|= 0x10;
  }
  
#endif

  // If ForceTaring is true
  // Wait some time and allow reading to stabilize
  // then set 
  // bDoTara = true;
  // in order to initiate and stora tara reading

  if(ForceTaring)
  {
    if(0 == DoneTaring)
    {
    
#ifdef TESTING_NORCU
      
    ForceWaitCount++; // Counted up in WriteCom
      if(0 == ForceWaitCount%2)
      {
        if(0==(PORTA & 0xDF))
        {
          PORTA|= 0x20;
        }
        else
        {
          PORTA&= 0xDF;
        }
      }
#endif
      
      if(200 < ForceWaitCount)
      {
        bDoTara = true;
        ForceWaitCount = 0;
        DoneTaring = 1;
      }
    }
  }
  
}
#endif

/////////////////////////////////////////////////////////////////////////////////////
//* Function that write data to the display*
/////////////////////////////////////////////////////////////////////////////////////
void Write_Display(unsigned char Disp_data_H, unsigned char Disp_data_L)
{
  SPCR = 0x51;      //Enable ISP, Master, set SPCR register, fosc/16
  SPSR = 0x00;

  PORTC&= 0xEF; //(0 << PORTC4);      // DISP-CS = 0 PORTC=PORTC & 0xEF; //
  _NOP();
  _NOP();
  SPDR = Disp_data_H; //Data high byte
  while(!(SPSR & 0x80))
    ; // Wait until SPIF bit in SPI Status register SPSR is zero
  SPDR = Disp_data_L; //Data low byte
  while(!(SPSR & 0x80))
    ; // Wait until SPIF bit in SPI Status register SPSR is zero
  _NOP();
  _NOP();
  PORTC|= 0x10; //(1 << PORTC4);      // DISP-CS = 1
}


void initHW(void)
{
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600 @ f=16,000MHz
UCSR0A=0x00;
UCSR0B=0x18;
UCSR0C=0x86;
UBRR0L=119;

// Crystal Oscillator division factor: 1
//CLKPR=0x80;
CLKPR=0x00;

// Input/Output Ports initialization
// Port A initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T
PORTA=0xFF;
DDRA=0xF0;

// Port B initialization
// Func0=Out Func1=In Func2=In Func3=In Func4=In Func5=Out Func6=In Func7=Out
// State0=Out State1=Out State2=T State3=T State4=P State5=0 State6=P State7=0
DDRB=0xA3;
PORTB=0x53;


// Port C initialization
// Func0=Out Func1=Out Func2=Out Func3=In Func4=Out Func5=In Func6=In Func7=In
// State0=0 State1=0 State2=1 State3=T State4=1 State5=T State6=T State7=T
PORTC=0x5C;
DDRC=0x9F;

// Port D initialization
// Func0=In Func1=Out Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In
// State0=T State1=0 State2=P State3=P State4=T State5=T State6=T State7=T
PORTD=0x0C;
DDRD=0x02;

#ifdef NO_RCU_MODE
PORTD |=0x80; // Activate pull up: PORTD7
#endif


// Port E initialization
// Func0=In Func1=In Func2=In
// State0=T State1=T State2=T
PORTE=0x07;
DDRE=0x06;

// Crystal Oscillator division factor: 1
CLKPR=0x80;
CLKPR=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x0C; // clkIO/256 (From prescaler)
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x10;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// Timer/Counter 3 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR3A=0x00;
TCCR3B=0x00;
TCNT3H=0x00;
TCNT3L=0x00;
OCR3AH=0x00;
OCR3AL=0x00;
OCR3BH=0x00;
OCR3BL=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-15: Off
GICR|=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;
ETIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x00;

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 1000,000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
//SPCR=0x55;
//SPSR=0x00;

// Added from ToolControl\test.c 20070130 - so
PORTE&=0xFB;      //PS021 CS =0
__delay_cycles(10);
PORTE|=0x04;     //PS021 CS =1
__delay_cycles(10);

}
Editor is loading...
Leave a Comment