浏览代码

Load/Save config on EEPROM

Thomas Buck 8 年前
父节点
当前提交
c52539eed7
共有 7 个文件被更改,包括 214 次插入52 次删除
  1. 3
    0
      Saitek-X52-PPM.ino
  2. 128
    0
      config.cpp
  3. 51
    0
      config.h
  4. 3
    5
      cppm.h
  5. 14
    23
      events.h
  6. 9
    1
      events_buttons.cpp
  7. 6
    23
      events_cppm.cpp

+ 3
- 0
Saitek-X52-PPM.ino 查看文件

@@ -20,6 +20,7 @@
20 20
 #include "x52.h"
21 21
 #include "cppm.h"
22 22
 #include "frsky.h"
23
+#include "config.h"
23 24
 
24 25
 #define ENABLE_SERIAL_PORT
25 26
 //#define DEBUG_OUTPUT Serial
@@ -74,6 +75,8 @@ void setup() {
74 75
     pinMode(13, OUTPUT);
75 76
     digitalWrite(13, LOW);
76 77
 
78
+    eepromRead();
79
+
77 80
     if (usb.Init() == -1) {
78 81
         digitalWrite(13, HIGH);
79 82
 #ifdef DEBUG_OUTPUT

+ 128
- 0
config.cpp 查看文件

@@ -0,0 +1,128 @@
1
+/*
2
+ * EEPROM configuration storage utility
3
+ * Copyright 2016 by Thomas Buck <xythobuz@xythobuz.de>
4
+ *
5
+ * This program is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU General Public License as
7
+ * published by the Free Software Foundation, version 2.
8
+ */
9
+#include <EEPROM.h>
10
+#include "cppm.h"
11
+#include "events.h"
12
+#include "config.h"
13
+
14
+//#define DEBUG_OUTPUT Serial
15
+
16
+static void toEEPROM(const ConfigData& data) {
17
+    for (uint8_t i = 0; i < CONFIG_VERSION_LENGTH; i++) {
18
+        EEPROM.write(i, CONFIG_VERSION[i]);
19
+    }
20
+
21
+    const uint8_t* buffer = (const uint8_t*)((const void*)&data);
22
+    uint8_t sum = 0;
23
+    for (uint8_t i = 0; i < CONFIG_DATA_LENGTH; i++) {
24
+        EEPROM.write(CONFIG_VERSION_LENGTH + i, buffer[i]);
25
+        sum ^= buffer[i];
26
+    }
27
+
28
+    EEPROM.write(CONFIG_VERSION_LENGTH + CONFIG_DATA_LENGTH, sum);
29
+
30
+#ifdef DEBUG_OUTPUT
31
+    DEBUG_OUTPUT.println("EEPROM write success!");
32
+#endif
33
+}
34
+
35
+// Return 0 on valid data, otherwise header or checksum wrong
36
+static uint8_t fromEEPROM(ConfigData& data) {
37
+    for (uint8_t i = 0; i < CONFIG_VERSION_LENGTH; i++) {
38
+        if (EEPROM.read(i) != CONFIG_VERSION[i]) {
39
+#ifdef DEBUG_OUTPUT
40
+            DEBUG_OUTPUT.println("EEPROM header wrong!");
41
+#endif
42
+            return 1;
43
+        }
44
+    }
45
+
46
+    uint8_t* buffer = (uint8_t*)((void*)&data);
47
+    uint8_t sum = 0;
48
+    for (uint8_t i = 0; i < CONFIG_DATA_LENGTH; i++) {
49
+        buffer[i] = EEPROM.read(CONFIG_VERSION_LENGTH + i);
50
+        sum ^= buffer[i];
51
+    }
52
+
53
+    uint8_t storedSum = EEPROM.read(CONFIG_VERSION_LENGTH + CONFIG_DATA_LENGTH);
54
+    if (storedSum != sum) {
55
+#ifdef DEBUG_OUTPUT
56
+        DEBUG_OUTPUT.println("EEPROM checksum wrong!");
57
+#endif
58
+        return 2;
59
+    }
60
+
61
+#ifdef DEBUG_OUTPUT
62
+    DEBUG_OUTPUT.println("EEPROM read success!");
63
+#endif
64
+
65
+    return 0;
66
+}
67
+
68
+void eepromRead() {
69
+    ConfigData data;
70
+    if (fromEEPROM(data) != 0) {
71
+        data.channels = DEFAULT_CHANNELS;
72
+        data.frameLength = DEFAULT_FRAME_LENGTH;
73
+        data.pulseLength = DEFAULT_PULSE_LENGTH;
74
+        data.inverted = DEFAULT_INVERT_STATE;
75
+        for (uint8_t i = 0; i < CHANNELS_MAX; i++) {
76
+            data.invert[i] = 0;
77
+            data.minimum[i] = CHANNEL_MINIMUM_VALUE;
78
+            data.maximum[i] = CHANNEL_MAXIMUM_VALUE;
79
+            data.trim[i] = 0;
80
+        }
81
+
82
+        /*
83
+         * Default values to match my personal setup.
84
+         * Can be changed using the on-screen menu.
85
+         */
86
+        data.invert[CHANNEL_THROTTLE] = 1;
87
+        data.invert[CHANNEL_PITCH] = 1;
88
+        data.minimum[CHANNEL_THROTTLE] = 1010;
89
+        data.maximum[CHANNEL_THROTTLE] = 1950;
90
+        data.minimum[CHANNEL_ROLL] = 1050;
91
+        data.maximum[CHANNEL_ROLL] = 1950;
92
+        data.minimum[CHANNEL_PITCH] = 1080;
93
+        data.maximum[CHANNEL_PITCH] = 1890;
94
+        data.minimum[CHANNEL_AUX1] = 990;
95
+        data.maximum[CHANNEL_AUX1] = 2100;
96
+        data.minimum[CHANNEL_AUX2] = 990;
97
+        data.maximum[CHANNEL_AUX2] = 1990;
98
+
99
+        toEEPROM(data);
100
+    }
101
+
102
+    CPPM::instance().setChannels(data.channels);
103
+    CPPM::instance().setFrameLength(data.frameLength);
104
+    CPPM::instance().setPulseLength(data.pulseLength);
105
+    CPPM::instance().setInvert(data.inverted);
106
+    for (uint8_t i = 0; i < CHANNELS_MAX; i++) {
107
+        joyCPPM.setInvert(i, data.invert[i]);
108
+        joyCPPM.setMinimum(i, data.minimum[i]);
109
+        joyCPPM.setMaximum(i, data.maximum[i]);
110
+        joyCPPM.setTrim(i, data.trim[i]);
111
+    }
112
+}
113
+
114
+void eepromWrite() {
115
+    ConfigData data;
116
+    data.channels = CPPM::instance().getChannels();
117
+    data.frameLength = CPPM::instance().getFrameLength();
118
+    data.pulseLength = CPPM::instance().getPulseLength();
119
+    data.inverted = CPPM::instance().getInvert();
120
+    for (uint8_t i = 0; i < CHANNELS_MAX; i++) {
121
+        data.invert[i] = joyCPPM.getInvert(i);
122
+        data.minimum[i] = joyCPPM.getMinimum(i);
123
+        data.maximum[i] = joyCPPM.getMaximum(i);
124
+        data.trim[i] = joyCPPM.getTrim(i);
125
+    }
126
+    toEEPROM(data);
127
+}
128
+

+ 51
- 0
config.h 查看文件

@@ -0,0 +1,51 @@
1
+/*
2
+ * EEPROM configuration storage utility
3
+ * Copyright 2016 by Thomas Buck <xythobuz@xythobuz.de>
4
+ *
5
+ * This program is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU General Public License as
7
+ * published by the Free Software Foundation, version 2.
8
+ */
9
+
10
+#ifndef __CONFIG_H__
11
+#define __CONFIG_H__
12
+
13
+#include <stdint.h>
14
+
15
+#define CPPM_OUTPUT_PIN 4
16
+#define CHANNEL_MINIMUM_VALUE 1000
17
+#define CHANNEL_DEFAULT_VALUE 1500
18
+#define CHANNEL_MAXIMUM_VALUE 2000
19
+#define CHANNELS_MAX 12
20
+#define DEFAULT_CHANNELS 6
21
+#define DEFAULT_FRAME_LENGTH 20000
22
+#define DEFAULT_PULSE_LENGTH 300
23
+#define DEFAULT_INVERT_STATE 0
24
+
25
+enum RxChannels {
26
+    CHANNEL_ROLL = 0,
27
+    CHANNEL_PITCH = 1,
28
+    CHANNEL_THROTTLE = 2,
29
+    CHANNEL_YAW = 3,
30
+    CHANNEL_AUX1 = 4,
31
+    CHANNEL_AUX2 = 5
32
+};
33
+
34
+// Increase string number when struct changes!
35
+#define CONFIG_VERSION "USBCPPM-01"
36
+#define CONFIG_VERSION_LENGTH (sizeof(CONFIG_VERSION) - 1)
37
+
38
+struct ConfigData {
39
+    uint16_t channels, frameLength, pulseLength, inverted;
40
+    uint16_t minimum[CHANNELS_MAX];
41
+    uint16_t maximum[CHANNELS_MAX];
42
+    uint16_t invert[CHANNELS_MAX];
43
+    int16_t trim[CHANNELS_MAX];
44
+};
45
+#define CONFIG_DATA_LENGTH (sizeof(ConfigData))
46
+
47
+void eepromRead();
48
+void eepromWrite();
49
+
50
+#endif // __CONFIG_H__
51
+

+ 3
- 5
cppm.h 查看文件

@@ -12,10 +12,7 @@
12 12
 
13 13
 #include <stdint.h>
14 14
 #include <avr/interrupt.h>
15
-
16
-#define CPPM_OUTPUT_PIN 4
17
-#define CHANNEL_DEFAULT_VALUE 1500
18
-#define CHANNELS_MAX 12
15
+#include "config.h"
19 16
 
20 17
 ISR(TIMER1_COMPA_vect);
21 18
 
@@ -48,7 +45,8 @@ class CPPM {
48 45
     inline void setInvert(uint8_t i) { onState = !i; }
49 46
 
50 47
   private:
51
-    CPPM() : channels(6), frameLength(20000), pulseLength(300), onState(1) { }
48
+    CPPM() : channels(DEFAULT_CHANNELS), frameLength(DEFAULT_FRAME_LENGTH),
49
+            pulseLength(DEFAULT_PULSE_LENGTH), onState(!DEFAULT_INVERT_STATE) { }
52 50
     CPPM(CPPM&) { }
53 51
 
54 52
     volatile uint16_t channels;

+ 14
- 23
events.h 查看文件

@@ -14,18 +14,10 @@
14 14
 #define __JOYSTICK_EVENTS_H__
15 15
 
16 16
 #include <stdint.h>
17
+#include "config.h"
17 18
 
18 19
 class GamePadEventData;
19 20
 
20
-enum RxChannels {
21
-    CHANNEL_ROLL = 0,
22
-    CHANNEL_PITCH = 1,
23
-    CHANNEL_THROTTLE = 2,
24
-    CHANNEL_YAW = 3,
25
-    CHANNEL_AUX1 = 4,
26
-    CHANNEL_AUX2 = 5
27
-};
28
-
29 21
 class JoystickEvents {
30 22
   public:
31 23
     JoystickEvents(JoystickEvents* _client = 0) : client(_client) { }
@@ -59,51 +51,50 @@ class JoystickEventsCPPM : public JoystickEvents {
59 51
     virtual void OnGamePadChanged(const GamePadEventData& evt);
60 52
 
61 53
     uint8_t getInvert(uint8_t ch) {
62
-        if (ch < channels) return invert[ch];
54
+        if (ch < CHANNELS_MAX) return invert[ch];
63 55
         else return 0;
64 56
     }
65 57
 
66 58
     void setInvert(uint8_t ch, uint8_t i) {
67
-        if (ch < channels) invert[ch] = i;
59
+        if (ch < CHANNELS_MAX) invert[ch] = i;
68 60
     }
69 61
 
70 62
     uint16_t getMinimum(uint8_t ch) {
71
-        if (ch < channels) return minimum[ch];
63
+        if (ch < CHANNELS_MAX) return minimum[ch];
72 64
         else return 0;
73 65
     }
74 66
 
75 67
     void setMinimum(uint8_t ch, uint16_t i) {
76
-        if (ch < channels) minimum[ch] = i;
68
+        if (ch < CHANNELS_MAX) minimum[ch] = i;
77 69
     }
78 70
 
79 71
     uint16_t getMaximum(uint8_t ch) {
80
-        if (ch < channels) return maximum[ch];
72
+        if (ch < CHANNELS_MAX) return maximum[ch];
81 73
         else return 0;
82 74
     }
83 75
 
84 76
     void setMaximum(uint8_t ch, uint16_t i) {
85
-        if (ch < channels) maximum[ch] = i;
77
+        if (ch < CHANNELS_MAX) maximum[ch] = i;
86 78
     }
87 79
 
88 80
     int16_t getTrim(uint8_t ch) {
89
-        if (ch < channels) return trim[ch];
81
+        if (ch < CHANNELS_MAX) return trim[ch];
90 82
         else return 0;
91 83
     }
92 84
 
93 85
     void setTrim(uint8_t ch, int16_t i) {
94
-        if (ch < channels) trim[ch] = i;
86
+        if (ch < CHANNELS_MAX) trim[ch] = i;
95 87
     }
96 88
 
97 89
   private:
98 90
     uint16_t getJoystickAxis(const GamePadEventData& evt, uint8_t ch);
99 91
     uint16_t getJoystickMax(uint8_t ch);
100 92
 
101
-    const static uint8_t channels = 12;
102
-    uint16_t values[channels];
103
-    uint8_t invert[channels];
104
-    uint16_t minimum[channels];
105
-    uint16_t maximum[channels];
106
-    int16_t trim[channels];
93
+    uint16_t values[CHANNELS_MAX];
94
+    uint8_t invert[CHANNELS_MAX];
95
+    uint16_t minimum[CHANNELS_MAX];
96
+    uint16_t maximum[CHANNELS_MAX];
97
+    int16_t trim[CHANNELS_MAX];
107 98
 };
108 99
 
109 100
 class JoystickEventsButtons : public JoystickEvents {

+ 9
- 1
events_buttons.cpp 查看文件

@@ -15,6 +15,7 @@
15 15
 #include "x52.h"
16 16
 #include "cppm.h"
17 17
 #include "events.h"
18
+#include "config.h"
18 19
 
19 20
 //#define DEBUG_OUTPUT Serial
20 21
 //#define DEBUG_BUTTON_MFD
@@ -47,7 +48,8 @@ JoystickEventsButtons::JoystickEventsButtons(JoystickEvents* client)
47 48
 
48 49
 void JoystickEventsButtons::printMenu() {
49 50
     static const char* mainMenu[] = {
50
-        "Status", "Trim Axis", "Trim Endpoint", "Invert Axis", "CPPM Config"
51
+        "Status", "Trim Axis", "Trim Endpoint", "Invert Axis", "CPPM Config",
52
+        "Save EEPROM", "Load EEPROM"
51 53
     };
52 54
     static const uint8_t mainMenuCount = sizeof(mainMenu) / sizeof(mainMenu[0]);
53 55
 
@@ -141,6 +143,12 @@ void JoystickEventsButtons::OnButtonDown(uint8_t but_id) {
141 143
             } else if (index == 4) {
142 144
                 state = CPPMMENU;
143 145
                 index = 0;
146
+            } else if (index == 5) {
147
+                eepromWrite();
148
+                index = 0;
149
+            } else if (index == 6) {
150
+                eepromRead();
151
+                index = 0;
144 152
             }
145 153
         } else if (state == TRIMAXISMENU) {
146 154
             if (index == 0) {

+ 6
- 23
events_cppm.cpp 查看文件

@@ -16,11 +16,11 @@
16 16
 #include "events.h"
17 17
 
18 18
 JoystickEventsCPPM::JoystickEventsCPPM(JoystickEvents* client) : JoystickEvents(client) {
19
-    for (uint8_t i = 0; i < channels; i++) {
20
-        values[i] = 1500;
19
+    for (uint8_t i = 0; i < CHANNELS_MAX; i++) {
20
+        values[i] = CHANNEL_DEFAULT_VALUE;
21 21
         invert[i] = 0;
22
-        minimum[i] = 1000;
23
-        maximum[i] = 2000;
22
+        minimum[i] = CHANNEL_MINIMUM_VALUE;
23
+        maximum[i] = CHANNEL_MAXIMUM_VALUE;
24 24
         trim[i] = 0;
25 25
     }
26 26
 
@@ -29,25 +29,8 @@ JoystickEventsCPPM::JoystickEventsCPPM(JoystickEvents* client) : JoystickEvents(
29 29
      * Ensure we're not sending high values when
30 30
      * no joystick has been connected...
31 31
      */
32
-    values[CHANNEL_AUX1] = 1000;
33
-    values[CHANNEL_AUX2] = 1000;
34
-
35
-    /*
36
-     * Default values to match my personal setup.
37
-     * Can be changed using the on-screen menu.
38
-     */
39
-    invert[CHANNEL_THROTTLE] = 1;
40
-    invert[CHANNEL_PITCH] = 1;
41
-    minimum[CHANNEL_THROTTLE] = 1010;
42
-    maximum[CHANNEL_THROTTLE] = 1950;
43
-    minimum[CHANNEL_ROLL] = 1050;
44
-    maximum[CHANNEL_ROLL] = 1950;
45
-    minimum[CHANNEL_PITCH] = 1080;
46
-    maximum[CHANNEL_PITCH] = 1890;
47
-    minimum[CHANNEL_AUX1] = 990;
48
-    maximum[CHANNEL_AUX1] = 2100;
49
-    minimum[CHANNEL_AUX2] = 990;
50
-    maximum[CHANNEL_AUX2] = 1990;
32
+    values[CHANNEL_AUX1] = CHANNEL_MINIMUM_VALUE;
33
+    values[CHANNEL_AUX2] = CHANNEL_MINIMUM_VALUE;
51 34
 
52 35
     CPPM::instance().copy(values);
53 36
 }

正在加载...
取消
保存