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

Revision 8111, 4.1 kB (checked in by mootoh, 6 years ago)

lang/cplusplus/gainer++: implemented din for MODE_1.

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