aboutsummaryrefslogtreecommitdiff
path: root/src/voltronic/device.h
blob: 6584585e7a429aebeccae3c1e84d4f9048ad03f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// SPDX-License-Identifier: BSD-3-Clause

#ifndef INVERTER_TOOLS_VOLTRONIC_DEVICE_H
#define INVERTER_TOOLS_VOLTRONIC_DEVICE_H

#include <string>
#include <memory>
#include <hidapi/hidapi.h>
#include <libserialport.h>

#include "../numeric_types.h"

namespace voltronic {

enum {
    FLAG_WRITE_CRC = 1,
    FLAG_READ_CRC = 2,
    FLAG_VERIFY_CRC = 4,
};


/**
 * Common device
 */

class Device {
protected:
    int flags_;
    u64 timeout_;
    u64 timeStarted_;
    bool verbose_;

    void send(const u8* buf, size_t bufSize);
    size_t recv(u8* buf, size_t bufSize);

    void writeLoop(const u8* data, size_t dataSize);
    size_t readLoop(u8* buf, size_t bufSize);

    u64 getElapsedTime() const;
    u64 getTimeLeft() const;

public:
    static const u64 TIMEOUT = 1000;

    Device();

    virtual size_t read(u8* buf, size_t bufSize) = 0;
    virtual size_t write(const u8* data, size_t dataSize) = 0;

    void setTimeout(u64 timeout);
    size_t run(const u8* inbuf, size_t inbufSize, u8* outbuf, size_t outbufSize);

    void setFlags(int flags);
    int getFlags() const;

    void setVerbose(bool verbose);
};


/**
 * USB device
 */

class USBDevice : public Device {
private:
    hid_device* device_;

public:
    static const u16 VENDOR_ID = 0x0665;
    static const u16 PRODUCT_ID = 0x5161;
    static const u16 HID_REPORT_SIZE = 8;
    static u16 GET_HID_REPORT_SIZE(size_t size);

    USBDevice(u16 vendorId, u16 productId);
    ~USBDevice();

    size_t read(u8* buf, size_t bufSize) override;
    size_t write(const u8* data, size_t dataSize) override;
};


/**
 * Serial device
 */

typedef unsigned SerialBaudRate;

enum class SerialDataBits {
    Five = 5,
    Six = 6,
    Seven = 7,
    Eight = 8,
};

enum class SerialStopBits {
    One = 1,
    OneAndHalf = 3,
    Two = 2
};

enum class SerialParity {
    Invalid = SP_PARITY_INVALID,
    None = SP_PARITY_NONE,
    Odd = SP_PARITY_ODD,
    Even = SP_PARITY_EVEN,
    Mark = SP_PARITY_MARK,
    Space = SP_PARITY_SPACE,
};

class SerialDevice : public Device {
private:
    struct sp_port* port_;
    SerialBaudRate baudRate_;
    SerialDataBits dataBits_;
    SerialStopBits stopBits_;
    SerialParity parity_;
    std::string name_;

    unsigned getTimeout();

public:
    static const char* DEVICE_NAME;
    static const SerialBaudRate BAUD_RATE = 2400;
    static const SerialDataBits DATA_BITS = SerialDataBits::Eight;
    static const SerialStopBits STOP_BITS = SerialStopBits::One;
    static const SerialParity PARITY = SerialParity::None;

    explicit SerialDevice(std::string& name,
                 SerialBaudRate baudRate,
                 SerialDataBits dataBits,
                 SerialStopBits stopBits,
                 SerialParity parity);
    ~SerialDevice();

    [[nodiscard]] inline struct sp_port* getPort() const {
        return port_;
    }

    size_t read(u8* buf, size_t bufSize) override;
    size_t write(const u8* data, size_t dataSize) override;
};

class SerialPortConfiguration {
private:
    struct sp_port_config* config_;
    SerialDevice& device_;

public:
    explicit SerialPortConfiguration(SerialDevice& device);
    ~SerialPortConfiguration();

    void setConfiguration(SerialBaudRate baudRate, SerialDataBits dataBits, SerialStopBits stopBits, SerialParity parity);
};

bool is_serial_baud_rate_valid(SerialBaudRate baudRate);
bool is_serial_data_bits_valid(SerialDataBits dataBits);
bool is_serial_stop_bits_valid(SerialStopBits stopBits);
bool is_serial_parity_valid(SerialParity parity);


/**
 * Pseudo device
 */

class PseudoDevice : public Device {
public:
    PseudoDevice() = default;
    ~PseudoDevice() = default;

    size_t read(u8* buf, size_t bufSize) override;
    size_t write(const u8* data, size_t dataSize) override;
};

}

#endif //INVERTER_TOOLS_VOLTRONIC_DEVICE_H