text: /**
   * \file
   * Register structures - the actual register
   * assignments are in the autogenerated file regsauto.h
   */
  
  
  #ifndef __REGS_H
  #define __REGS_H
  
  #include <stdint.h>
  
  #include "hwconfig.h"
  
  
  /// on the master, things marked as MAYBEPROGMEM go into program
  /// memory. This has no effect on other platforms - either PC or
  /// slave (though I may modify the code to make the slave do this too.)
  /// It's used for register tables.
  
  #if defined(MASTER)
  #define MAYBEPROGMEM const PROGMEM
  #else
  #define MAYBEPROGMEM const
  #endif
  
  /// how many devices we can have
  #define MAXDEVICES 12
  
  // bits in REG_RESET
  
  /// reset any exception
  #define RESET_EXCEPTIONS 1
  /// hard reset; causes a reboot
  #define RESET_HARD 2
  /// reset drive motor odometry
  #define RESET_ODO 4
  
  
  // status bits in REG_STATUS
  
  /// REG_STATUS bit: an exception has occurred
  #define ST_EXCEPTION	1
  /// REG_STATUS bit: driver is an LL board
  #define ST_LL		4
  /// REG_STATUS bit: driver is an DS board
  #define ST_DS		8
  
  /// maximum number of read sets
  #define READSETS	8
  /// the maximum size of a read set (larger uses up valuable master memory!)
  #define READSETSIZE     24
  
  /// a register table entry, used to initialise both master and slave.
  /// An array of these is terminated by an entry with -ve size.
  /// Registers are transmitted and received as 1 or 2 byte values, but
  /// have an optional mapping onto a float range. This is done via minval-maxval,
  /// which map from 0-255 or 0-65535.
  
  struct Register {
      uint8_t sizeAndFlags; 	//!< width of the register in bytes, 64 set if writable
      float minval; //!< minimum value of range
      float maxval;
      
      int getSize() const{
          return sizeAndFlags&0x3f;
      }
      bool writable() const{
          return (sizeAndFlags & 0x40)?true:false;
      }
            
      
      
      /// is this float in the mapped range of the register?
      bool isInRange(float v) const {
          if(minval==maxval) return v<=65535.0f && v>=0.0f;
          else return v<=maxval && v>=minval;
      }
      
      /// Map the received unsigned int value back onto a float
      /// only valid if the register is mapped. 
      float unmap(uint16_t i) const {
          if(minval==maxval)return (float)i;
          float v = i;
          v *= (maxval-minval);
          // -2 so that maxval maps onto 254/65534. Not -1; -2 means that
          // 0 maps and unmaps correctly.
          v /= (1L<<(getSize()*8L))-2; 
          v += minval;
          return v;
      }
      
      /// Map a float value onto a register. Will clip to range.
      /// only valid if the register is mapped.
      
      uint16_t map(float v) const {
          if(minval==maxval)return (uint16_t)v;
          if(v<minval)v=minval;
          if(v>maxval)v=maxval;
          v -= minval;
          // see note in unmap
          v *= (1L<<(getSize()*8L))-2;
          v /= (maxval-minval);
          return (uint16_t)v;
      }
  };
  
  #endif /* __REGS_H */
  