home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_03 / 1003054b < prev    next >
Text File  |  1991-10-07  |  7KB  |  269 lines

  1. /* ----------------------------------------------------
  2.  *  LISTING 5
  3.  *
  4.  *  Filename:           tape.c
  5.  *  Summary:            State machine constructs for
  6.  *                      tape device
  7.  *  Author:             T.W. Nelson
  8.  *  Compile options:    
  9.  *  Version:            1.00
  10.  *  Date:               07-Oct-1991
  11.  *  Notes:
  12.  *
  13.  *  Source code Copyright (c) 1991 T.W. Nelson.
  14.  *  May be used only with appropriate
  15.  *  acknowledgement of copyright.
  16.  * ------------------------------------------------- */
  17.  
  18. #include "driver.h"
  19. #include "tape.h"
  20.  
  21. extern void putstr( const char *str );
  22.  
  23. extern int initialize(), status(), eject(), record(),
  24.     play(), fforward(), rewind(), stop(), cstate(),
  25.     shutdown();
  26.  
  27. //Arrays of function pointers to be executed
  28. //in the order listed, to effect transition from
  29. //the current state to next desired state.....
  30. //
  31. int (*f_init[])() = { initialize, cstate, 0 };
  32.  
  33. int (*f_stat[])() = { status, cstate, 0 };
  34.  
  35. int (*f_off[])() = { shutdown, cstate, 0 };
  36.  
  37. int (*f_ejoff[])() = { eject, shutdown, cstate, 0 };
  38.  
  39. int (*f_eject[])() = { eject, cstate, 0    };
  40.  
  41. int (*f_rec[])() = { record, cstate, 0     };
  42.  
  43. int (*f_play[])() = { play, cstate, 0     };
  44.  
  45. int (*f_ffwd[])() = { fforward, cstate, 0   };
  46.  
  47. int (*f_rwnd[])() = { rewind, cstate, 0    };
  48.  
  49. int (*f_stop[])() = { stop, cstate, 0    };
  50.  
  51. int (*f_steject[])() = { stop, eject, cstate, 0   };
  52.  
  53. int (*f_strec[])() = { stop, record, cstate, 0    };
  54.  
  55. int (*f_stplay[])() = { stop, play, cstate, 0    };
  56.  
  57. int (*f_stffwd[])() = { stop, fforward, cstate, 0  };
  58.  
  59. int (*f_strwnd[])() = { stop, rewind, cstate, 0    };
  60.  
  61. //Event (Command) Tables describing valid events for a
  62. //state, the next state to transition to, as well as
  63. //the functions to effect the transition......
  64. //
  65. S_TAB s_off[] = {
  66. /*  command         n_state funcs
  67.   --------------------------------- */
  68.     CMD_POWER_ON,   ON,     f_init,
  69.     CMD_CHK_STATUS, OFF,    f_stat,
  70.     END,            END,    0,    };
  71.  
  72. S_TAB s_on[] = {
  73. /*  command         n_state     funcs
  74.   ------------------------------------ */
  75.     CMD_POWER_OFF,  OFF  ,      f_off,
  76.     CMD_INSERT   ,  READY,      f_stat,
  77.     CMD_CHK_STATUS, ON,         f_stat,
  78.     END          ,  END  ,      0,    };
  79.  
  80. S_TAB s_ready[] = {
  81. /*  command         n_state     funcs
  82.   ------------------------------------ */
  83.     CMD_POWER_OFF , OFF     ,   f_ejoff,
  84.     CMD_EJECT     , ON      ,   f_eject,
  85.     CMD_RECORD    , RECORD  ,   f_rec,
  86.     CMD_PLAY      , PLAY    ,   f_play,
  87.     CMD_FFORWARD  , FFORWARD,   f_ffwd,
  88.     CMD_REWIND    , REWIND  ,   f_rwnd,
  89.     CMD_CHK_STATUS, READY   ,   f_stat,
  90.     END           , END     ,   0,    };
  91.  
  92. S_TAB s_record[] = {
  93. /*  command         n_state     funcs
  94.   ------------------------------------ */
  95.     CMD_STOP      , READY   ,   f_stop,
  96.     CMD_EJECT     , ON      ,   f_steject,
  97.     CMD_FFORWARD  , FFORWARD,   f_stffwd,
  98.     CMD_PLAY      , PLAY    ,   f_stplay,
  99.     CMD_REWIND    , REWIND  ,   f_strwnd,
  100.     CMD_CHK_STATUS, RECORD  ,   f_stat,
  101.     END           , END     ,   0,    };
  102.  
  103. S_TAB s_play[] = {
  104. /*  command         n_state     funcs
  105.   ------------------------------------ */
  106.     CMD_STOP      , READY   ,   f_stop,
  107.     CMD_EJECT     , ON      ,   f_steject,
  108.     CMD_FFORWARD  , FFORWARD,   f_stffwd,
  109.     CMD_REWIND    , REWIND  ,   f_strwnd,
  110.     CMD_RECORD    , RECORD  ,   f_strec,
  111.     CMD_CHK_STATUS, PLAY    ,   f_stat,
  112.     END           , END     ,   0,    };
  113.  
  114. S_TAB s_fforward[] = {
  115. /*  command         n_state     funcs
  116.   ------------------------------------ */
  117.     CMD_STOP      , READY   ,   f_stop,
  118.     CMD_EJECT     , ON      ,   f_steject,
  119.     CMD_PLAY      , PLAY    ,   f_stplay,
  120.     CMD_REWIND    , REWIND  ,   f_strwnd,
  121.     CMD_RECORD    , RECORD  ,   f_strec,
  122.     CMD_CHK_STATUS, FFORWARD,   f_stat,
  123.     END           , END     ,   0,    };
  124.  
  125. S_TAB s_rewind[] = {
  126. /*  command         n_state     funcs
  127.   ------------------------------------ */
  128.     CMD_STOP      , READY   ,   f_stop,
  129.     CMD_EJECT     , ON      ,   f_steject,
  130.     CMD_PLAY      , PLAY    ,   f_stplay,
  131.     CMD_RECORD    , RECORD  ,   f_strec,
  132.     CMD_FFORWARD  , FFORWARD,   f_stffwd,
  133.     CMD_CHK_STATUS, REWIND  ,   f_stat,
  134.     END           , END     ,   0,    };
  135.  
  136. //The actual "state table" that connects all
  137. //the foregoing initialized data into one.  enum
  138. //'device_states' is an index into this array
  139. //of struct pointers. These MUST be in same order
  140. //as the enum in 'tape.h' ........
  141. //
  142. S_TAB *s_table[] = {
  143.     s_off, s_on, s_ready, s_record, s_play,
  144.     s_fforward, s_rewind,
  145.     };
  146.  
  147. unsigned tape_io( CMDARG far *arg )
  148. {
  149.    /* State Machine Driver. Called by DOS thru driver
  150.     * interrupt routine, command codes 3 & 12.
  151.     */
  152.  
  153.     int i;
  154.     S_TAB *pcmd;        //-> event (cmd) table
  155.     int (**pfun)(CMDARG far *arg);  //-> function list
  156.  
  157.     //point to the correct event table .....
  158.     if( arg->c_state >= MAX_STATE )
  159.             return IS_ERROR + INV_COMMAND;
  160.  
  161.     pcmd = s_table[arg->c_state];
  162.  
  163.     //find the specified command in the event table...
  164.     for( i = 0; pcmd[i].event != END; i++ )
  165.             if( pcmd[i].event == arg->cmd )
  166.                     break;
  167.  
  168.     //check for invalid command .....
  169.     if( pcmd[i].event == END ) {
  170.             putstr("Invalid command specified\r\n");
  171.             return IS_ERROR + INV_COMMAND;
  172.     }
  173.  
  174.     //indicate next state for application .......
  175.     arg->c_state = pcmd[i].n_state;
  176.  
  177.     //execute the function list ........
  178.     pfun = pcmd[i].procs;
  179.  
  180.     for( i = 0; pfun[i]; i++ )
  181.         (*pfun[i])(arg);
  182.  
  183.     return 0;
  184. }
  185.  
  186. int status(CMDARG far *arg)
  187. {
  188.     arg->status = OK;
  189.     return 0;
  190. }
  191.  
  192. int initialize(CMDARG far *arg)
  193. {
  194.     putstr("Device initialized\r\n" );
  195.     status(arg);
  196.     return 0;
  197. }
  198.  
  199. int eject(CMDARG far *arg)
  200. {
  201.     putstr( "Cassette ejected\r\n" );
  202.     status(arg);
  203.     return 0;
  204. }
  205.  
  206. int record(CMDARG far *arg)
  207. {
  208.     putstr( "Recording\r\n" );
  209.     status(arg);
  210.     return 0;
  211. }
  212.  
  213. int play(CMDARG far *arg)
  214. {
  215.     putstr( "Playing\r\n" );
  216.     status(arg);
  217.     return 0;
  218. }
  219.  
  220. int fforward(CMDARG far *arg)
  221. {
  222.     putstr( "Fast forwarding\r\n" );
  223.     status(arg);
  224.     return 0;
  225. }
  226.  
  227. int rewind(CMDARG far *arg)
  228. {
  229.     putstr( "Rewinding\r\n" );
  230.     status(arg);
  231.     return 0;
  232. }
  233.  
  234. int stop(CMDARG far *arg)
  235. {
  236.     putstr( "Stopping\r\n" );
  237.     status(arg);
  238.     return 0;
  239. }
  240.  
  241. int shutdown(CMDARG far *arg)
  242. {
  243.     putstr( "Powered down\r\n" );
  244.     status(arg);
  245.     return 0;
  246. }
  247.  
  248. int cstate(CMDARG far *arg)
  249. {
  250.    /* Print current state, after transition .... */
  251.  
  252.     static char *s_name[] = {
  253.         "OFF",        //0
  254.         "ON",         //1
  255.         "READY",      //2
  256.         "RECORD",     //3
  257.         "PLAY",       //4
  258.         "FFORWARD",   //5
  259.         "REWIND",     //6
  260.         };
  261.  
  262.     putstr( "Current state is " );
  263.     putstr( s_name[arg->c_state] );
  264.     putstr( "\r\n" );
  265.     return 0;
  266. }
  267.  
  268. /* ----- End of File ------------------------------- */
  269.