comp.lang.ada
 help / color / mirror / Atom feed
* Problem to dramatize packed-array/rep-clause difficulties (long)
@ 1996-03-27  0:00 Doug Rogers
  0 siblings, 0 replies; only message in thread
From: Doug Rogers @ 1996-03-27  0:00 UTC (permalink / raw)


In lieu of more discussion of the difficulties of doing low-level bit access
and binary file i/o in Ada83, I'm posting a little, much-simplified problem
for the Ada community at large.  I'm honestly stumped on this one.  I've
tried countless ways (ok, aleph-naught ways!) to solve the problem
elegantly.

For the most elegant solution completely coded in Ada83 (you may use the DEC
standard Sequential_Mixed_IO package, as described below), I offer as a
prize... um... a heartfelt "Thanks!".  Sorry, that's all I can afford
(unless you live in the Washington DC or Colorado Springs CO area, in which
case I'll take you out to lunch).

Without further ado, I begin:

Suppose your job is to read in a stream of data (hey, that's MY job,
too!), and that data represents analog to digital convertor values from
some sensors.  Each sensor runs in two modes: low resolution, producing 12
samples of 6-bit values, and high resolution, producing 8 samples of 9-bit
values.  Assume the data comes from a binary file.

The first record in the file is the header.  It contains a 12-bit sensor
count and a four-bit timetag.  Each sensor contains a list of sensor data,
whose format varies according to the mode bit (Mod).  When Mod is set to 0,
low precision data is present.  When 1, high precision data is present.

For convenience, assume you have a byte-addressable machine with a 32-bit
wordsize.  Note that I'm being pretty nice about all the boundaries except
the arrays.

Okay, here's the format to be supported:

           bytes _7_._6_._5_._4_._3_._2_._1_._0_  lsb  (intel order)
  Header =>  0  |---------sensor count--------->|
             1  |<--time tag--->|<---(cont'd)---|

  A sensor record follows for each sensor count.

             bytes    _7_._6_._5_._4_._3_._2_._1_._0_  lsb  (intel order)
  Sensor =>    0     |<-------unused bits------->|Mod|
   (Data)    1 .. 9  | sensor data, according to Mod | see below

  case Mod is
    when 0 =>  -- low resolution, 12 samples of 6-bit values
             bytes _7_._6_._5_._4_._3_._2_._1_._0_  lsb  (intel order)
      Low  =>  0  |-(#1)->|<-------low #0-------->|
      Res      1  |----low #2---->|<----low #1----|
      Data     2  |<-------low #3-------->|<-(#2)-|
               3  |-(#5)->|<-------low #4-------->|
               4  |----low #6---->|<----low #5----|
               5  |<-------low #7-------->|<-(#6)-|
               6  |-(#9)->|<-------low #8-------->|
               7  |----low #10--->|<----low #9----|
               8  |<-------low #11------->|<-(10)-|

    when 1 =>  -- high resolution, 8 samples of 12-bit values
             bytes _7_._6_._5_._4_._3_._2_._1_._0_  lsb  (intel order)
      Data =>  0  |---------hi res #0------------>|
               1  |---------hi res #1-------->|<--|
               2  |---------hi res #2---->|<-(#1)-|
               3  |----hi res #3----->|<---(#2)---|
               4  |------(#4)---->|<------(#3)----|
               5  |---(#5)--->|<----hi res #4-----|
               6  |-(#6)->|<--------hi res #5-----|
               7  |-->|<--------hi res #6---------|
               8  |<------------hi res #7---------|
  end case;

Your mission, should you choose to accept it, is to read in a file with a
header (just one per file is ok) and at least 2 of each type of sensor   
record.  Then print out the contents using Text_IO/.Integer_IO. All this 
must be done in Ada83 (Ada95 solutions welcome, too, but I can not use them
*sigh*).  The difficulty is getting around the packed arrays of 6-bit and  
9-bit values.

Here's my dream-world solution:

  Natural_Language.Esperanto.Execute ("montru sensilajn datumojn.");

Just kidding.  Here's my if-Ada-honored-representations-as-well-as-the-
language-allows-them-to-be-specified solution:

--------[start "show_sensor_data.adb"]------------------------------------
--  Please excuse any shortcuts.  It's late, and it's only an example.
--
with Sequential_Mixed_IO;  -- DEC standard mixed-IO package providing
                           --    generic gets/puts to/from a file for
                           --    differently-typed data elements.
                           --    Further discussion below.
with Text_IO;

use Text_IO;

procedure Dump_Sensor_Data is

  package Int_IO is new Integer_IO (Natural);
  use Int_IO;

  subtype Natural12 is Natural range 0 .. (2 ** 12) - 1;
  for Natural12'size use 12;

  subtype Natural9  is Natural range 0 .. (2 **  9) - 1;
  for Natural9'size use 9;

  subtype Natural7  is Natural range 0 .. (2 **  7) - 1;
  for Natural7'size use 7;

  subtype Natural6  is Natural range 0 .. (2 **  6) - 1;
  for Natural6'size use 6;

  subtype Natural4  is Natural range 0 .. (2 **  4) - 1;
  for Natural4'size use 4;

  type Resolutions is (Low, High);
  for Resolutions use (Low => 0, High => 1);
  for Resolutions'size use 1;

  type Headers is record
    Sensor_Count : Natural12;
    Time_Tag     : Natural4  
  end record;

  for Headers use record
    Sensor_Count at 0 range  0 .. 11;
    Time_Tag     at 0 range 12 .. 15;
  end record;

  --
  --  !!!!  Here's the tricky stuff  !!!!
  --
  type Low_Res_Data is array (Natural range 0 .. 11) of Natural6;
  pragma Pack (Low_Res_Data);   -- right!

  type High_Res_Data is array (Natural range 0 .. 7) of Natural9;
  pragma Pack (High_Res_Data);  -- now I'm really dreaming!

  type Sensor_Data (Mode : Resolutions := Low) is record
    Unused : Natural7;
    case Mode is
      when Low  => Low_Res  : Low_Res_Data;
      when High => High_Res : High_Res_Data;
    end case;
  end record;

  for Sensor_Data use record
    Mode     at 0 range 0 .. 0;
    Unused   at 0 range 1 .. 7;
    Low_Res  at 1 range 0 .. 71;
    High_Res at 1 range 0 .. 71;
  end record;

  --
  --  The following are instances of:
  --    package Sequential_Mixed_IO is
  --      ...
  --      generic
  --        type Element_Type is private;
  --      procedure Get
  --          (File : in     File_Type;
  --           Item :    out Element_Type);
  --  The standard exceptions and Open/Close procedures are provided, too.
  --
  procedure Get_Header is new Sequential_Mixed_IO.Get (Headers);
  procedure Get_Sensor_Data is new Sequential_Mixed_IO.Get (Sensor_Data);

  procedure Put (H : in Headers) is
  begin -- Put
    Put ("Number of sensor records => ");
    Put (Natural (H.Sensor_Count), Width => 1);
    New_Line;
    Put ("Time tag => ");
    Put (Natural (H.Time_Tag), Width => 1);
    New_Line;
  end Put;   
  
  procedure Put (S : in Sensor_Data) is
  begin -- Put
    Put ("Sensor mode => ");
    Put (Resolutions'image (S.Mode));
    New_Line;
    case S.Mode is
      when Low => 
        for Index in Low_Res_Data'range loop
          Put ("  Data (");
          Put (Natural (Index), Width => 1);
          Put (") => ");
          Put (Natural (S.Low_Res (Index)));
          New_Line;
        end loop;  
      when High => 
        for Index in High_Res_Data'range loop
          Put ("  Data (");
          Put (Natural (Index), Width => 1);
          Put (") => ");
          Put (Natural (S.High_Res (Index)));
          New_Line;
        end loop;
    end case;
  end Put;

  Header : Headers;
  Data   : Sensor_Data;
  File   : Sequential_Mixed_IO.File_Type;   

begin -- Show_Sensor_Data
  Put_Line ("============================================================");
  Sequential_Mixed_IO.Open (File, "sensor.dat");
  Get_Header (File, Item => Header);
  Put (Header);    
  for Index in Natural12 range 1 .. Header.Sensor_Count loop
    Put ("Loading data for sensor #");
    Put (Natural (Index), Width => 1);
    New_Line;
    Get_Sensor_Data (File, Item => Data);
    Put (Data);
  end loop;
  Sequential_Mixed_IO.Close (File);
  Put_Line ("Done.");
end Show_Sensor_Data;
--------[end "show_sensor_data.adb"]--------------------------------------

Wouldn't that be nice? 

Doug
 
=------cxiuj-opinioj-estas-sole-miaj.-----any-opinions-are-mine-alone.------=
= Doug Rogers      vocxe/voice = 1.703.893.2007  fakse/fax = 1.703.893.5890 =
= Innovative Concepts Inc; 8200 Greensboro Drive Suite 801; McLean VA 22102 =
= PGP ID: pub  1024/016DE91D 1994/11/14   Doug Rogers  <rogers@innocon.com> =
=senemankasalvimultodatempolernulaanglan-ifyouvegotalittletimelearnesperanto=





^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1996-03-27  0:00 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-03-27  0:00 Problem to dramatize packed-array/rep-clause difficulties (long) Doug Rogers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox