root/lang/cplusplus/gainer++/gainer.cc

Revision 8189, 4.9 kB (checked in by mootoh, 10 months ago)

lang/cplusplus/gainer++: add continuos analog input example.

Line 
1#include <termios.h>
2#include <iostream>
3#include <string>
4#include <sstream>
5#include <fcntl.h>
6#include <sys/select.h>
7#include <pthread.h>
8#include "gainer.h"
9#include <iomanip>
10
11#define ABORT_UNLESS(stmt) \
12if (!((stmt))) { \
13  std::stringstream msg(""); \
14  msg << "failed in L" <<  __LINE__ << ": "; \
15  perror(msg.str().c_str()); \
16  abort(); \
17}
18
19#ifdef DEBUG
20#define DEBUG_PRINT(msg) std::cerr << msg << std::endl;
21#else
22#define DEBUG_PRINT(msg) ;
23#endif // DEBUG
24
25void *Gainer::receiver(void *arg) {
26  Gainer *self(reinterpret_cast<Gainer *>(arg));
27
28  struct timeval timeout;
29  timeout.tv_sec  = 1;
30  timeout.tv_usec = 0;
31
32  while (not self->end_) {
33    //DEBUG_PRINT("next_event...");
34
35    fd_set fds;
36    FD_ZERO(&fds);
37    FD_SET(self->io_, &fds);
38
39    int ret(select(self->io_+1, &fds, NULL, NULL, &timeout));
40    if (0 != ret) {
41      //DEBUG_PRINT("receiver: selected");
42      const size_t SIZE(80);
43      char buf[SIZE];
44      char ch(' ');
45      size_t i(0);
46      while ('*' != ch and i<SIZE) {
47        read(self->io_, &ch, 1);
48        buf[i++] = ch;
49      }
50      //read(self->io_, buf, SIZE);
51      //DEBUG_PRINT(buf);
52      std::string s(buf);
53
54      self->process_event(s);
55    }
56  }
57  return NULL;
58}
59
60namespace Gainer {
61  Gainer::Gainer(const std::string &path, int config) :
62      led_(false)
63    , config_(config)
64    , end_(false)
65    , on_pressed(NULL)
66    , on_released(NULL)
67  {
68    ABORT_UNLESS(-1 != (io_ = open(path.c_str(), O_RDWR)));
69    ABORT_UNLESS(-1 != fsync(io_));
70    setup_port();
71    pthread_create(&thread_, NULL, receiver, this);
72    reboot();
73    set_configuration(config_);
74  }
75
76  Gainer::~Gainer() {
77    reboot();
78    end_ = true;
79    pthread_join(thread_, NULL);
80    close(io_);
81  }
82
83  void Gainer::setup_port() {
84    struct termios term;
85    ABORT_UNLESS(0 == tcgetattr(io_, &term));
86    ABORT_UNLESS(0 == cfsetispeed(&term, B38400));
87    ABORT_UNLESS(0 == cfsetospeed(&term, B38400));
88    term.c_cflag |= CS8;
89    ABORT_UNLESS(0 == tcsetattr(io_, TCSANOW, &term));
90  }
91
92  void Gainer::set_configuration(int number) {
93    if (1 > number or number > 7)
94      throw GainerInternal::Exception();
95
96    config_ = number;
97    std::stringstream ss("");
98    ss << "KONFIGURATION_" << number;
99    command(ss.str(), 1);
100
101    for (int i(0); i<CONFIG[config_][AIN]; i++) // create analog inputs
102      analog_inputs.push_back(0);
103
104    for (int i(0); i<CONFIG[config_][DIN]; i++) // create digital inputs
105      digital_inputs.push_back(false);
106  }
107
108  // void Gainer::set_matrix(ary) // TODO
109
110  void Gainer::set_led(bool flag)          { command(flag ? "h" : "l"); }
111  void Gainer::reboot()                    { command("Q", 2); }
112  void Gainer::peek_digital_inputs()       { command("R"); }
113  void Gainer::peek_analog_inputs()        { command("I"); }
114  void Gainer::continuous_digital_inputs() { command("r"); }
115  void Gainer::continuous_analog_inputs()  { command("i"); }
116  void Gainer::exit_continuos()            { command("E"); }
117
118  void Gainer::set_digital_output(int n) {
119    std::stringstream ss("D");
120    for (int i(0); i< CONFIG[config_][DOUT]-1; i++)
121      ss << ' ';
122    ss << n;
123    command(ss.str());
124  }
125
126  void Gainer::command(const std::string &cmd, int wait) {
127    command_send(cmd + '*');
128    sleep(wait);
129  }
130
131  void Gainer::command_send(const std::string &cmd) {
132    write(io_, cmd.c_str(), cmd.size());
133  }
134
135  void Gainer::process_event(std::string &event) {
136    //DEBUG_PRINT("event: " << event);
137    switch(event[0]) {
138      case '!': // something wrong
139        throw GainerInternal::Exception();
140      case 'h': // led on
141        led_ = true;
142        break;
143      case 'l': // led off
144        led_ = false;
145        break;
146      case 'N': // button pressed
147        on_pressed();
148        break;
149      case 'F': // button released
150        on_released();
151        break;
152      case 'i':
153      case 'I': { // analog_input
154                  std::string::size_type ast(event.find('*'));
155                  std::string s(event.substr(1, ast-1));
156                  sscanf(s.c_str(), "%02X%02X%02X%02X*",
157                      &analog_inputs[0], &analog_inputs[1],
158                      &analog_inputs[2], &analog_inputs[3]);
159                  break;
160                }
161      case 'r':
162      case 'R': { // digital input
163                  std::string::size_type ast(event.find('*'));
164                  std::stringstream ss(event.substr(1, ast-1));
165                  int num;
166                  ss >> std::hex >> num;
167                  for (size_t i(0); i<digital_inputs.size(); i++)
168                    digital_inputs[i] = num & (1<<i);
169                  break;
170                }
171      default:
172                break;
173    }
174  }
175
176  const int Gainer::CONFIG[][4] = {
177    // N_AIN, N_DIN, N_AOUT, N_DOUT
178    {0,},         // dummy
179    {4, 4, 4, 4}, // 1
180    {8, 0, 4, 4}, // 2
181    {4, 4, 8, 0}, // 3
182    {8, 0, 8, 0}, // 4
183    {0,16, 0, 0}, // 5
184    {0, 0, 0,16}, // 6
185    {0,}          // 7 for matrix LED
186  };
187
188} // Gainer
Note: See TracBrowser for help on using the browser.