5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
22 #include "pulses/pxx1.h"
24 template <class PxxTransport
>
25 void Pxx1Pulses
<PxxTransport
>::addFlag1(uint8_t module
, uint8_t sendFailsafe
)
27 uint8_t flag1
= (g_model
.moduleData
[module
].subType
<< 6);
29 if (moduleState
[module
].mode
== MODULE_MODE_BIND
) {
30 flag1
|= (g_eeGeneral
.countryCode
<< 1) | PXX_SEND_BIND
;
32 else if (moduleState
[module
].mode
== MODULE_MODE_RANGECHECK
) {
33 flag1
|= PXX_SEND_RANGECHECK
;
36 if (sendFailsafe
&& g_model
.moduleData
[module
].failsafeMode
!= FAILSAFE_NOT_SET
&& g_model
.moduleData
[module
].failsafeMode
!= FAILSAFE_RECEIVER
) {
37 flag1
|= PXX_SEND_FAILSAFE
;
40 PxxTransport::addByte(flag1
);
43 template <class PxxTransport
>
44 void Pxx1Pulses
<PxxTransport
>::addExtraFlags(uint8_t module
)
46 // Ext. flag (holds antenna selection on Horus internal module, 0x00 otherwise)
47 uint8_t extraFlags
= 0;
49 #if defined(EXTERNAL_ANTENNA)
50 if (module
== INTERNAL_MODULE
&& isExternalAntennaEnabled()) {
51 extraFlags
|= (1 << 0);
55 extraFlags
|= (g_model
.moduleData
[module
].pxx
.receiverTelemetryOff
<< 1);
56 extraFlags
|= (g_model
.moduleData
[module
].pxx
.receiverHigherChannels
<< 2);
57 if (isModuleR9MNonAccess(module
)) {
58 extraFlags
|= (min
<uint8_t>(g_model
.moduleData
[module
].pxx
.power
, isModuleR9M_FCC_VARIANT(module
) ? (uint8_t)R9M_FCC_POWER_MAX
: (uint8_t)R9M_LBT_POWER_MAX
) << 3);
59 if (isModuleR9M_EUPLUS(module
))
60 extraFlags
|= (1 << 6);
63 // Disable S.PORT if internal module is active
64 if (module
== EXTERNAL_MODULE
&& isSportLineUsedByInternalModule()) {
65 extraFlags
|= (1 << 5);
68 PxxTransport::addByte(extraFlags
);
71 template <class PxxTransport
>
72 void Pxx1Pulses
<PxxTransport
>::addChannels(uint8_t port
, uint8_t sendFailsafe
, uint8_t sendUpperChannels
)
74 uint16_t pulseValue
= 0;
75 uint16_t pulseValueLow
= 0;
77 for (int8_t i
=0; i
<8; i
++) {
79 if (g_model
.moduleData
[port
].failsafeMode
== FAILSAFE_HOLD
) {
80 pulseValue
= (i
< sendUpperChannels
? 4095 : 2047);
82 else if (g_model
.moduleData
[port
].failsafeMode
== FAILSAFE_NOPULSES
) {
83 pulseValue
= (i
< sendUpperChannels
? 2048 : 0);
86 if (i
< sendUpperChannels
) {
87 int16_t failsafeValue
= g_model
.failsafeChannels
[8+i
];
88 if (failsafeValue
== FAILSAFE_CHANNEL_HOLD
) {
91 else if (failsafeValue
== FAILSAFE_CHANNEL_NOPULSE
) {
95 failsafeValue
+= 2*PPM_CH_CENTER(8+g_model
.moduleData
[port
].channelsStart
+i
) - 2*PPM_CENTER
;
96 pulseValue
= limit(2049, (failsafeValue
* 512 / 682) + 3072, 4094);
100 int16_t failsafeValue
= g_model
.failsafeChannels
[i
];
101 if (failsafeValue
== FAILSAFE_CHANNEL_HOLD
) {
104 else if (failsafeValue
== FAILSAFE_CHANNEL_NOPULSE
) {
108 failsafeValue
+= 2*PPM_CH_CENTER(g_model
.moduleData
[port
].channelsStart
+i
) - 2*PPM_CENTER
;
109 pulseValue
= limit(1, (failsafeValue
* 512 / 682) + 1024, 2046);
115 if (i
< sendUpperChannels
) {
116 int channel
= 8 + g_model
.moduleData
[port
].channelsStart
+ i
;
117 int value
= channelOutputs
[channel
] + 2*PPM_CH_CENTER(channel
) - 2*PPM_CENTER
;
118 pulseValue
= limit(2049, (value
* 512 / 682) + 3072, 4094);
120 else if (i
< sentModuleChannels(port
)) {
121 int channel
= g_model
.moduleData
[port
].channelsStart
+ i
;
122 int value
= channelOutputs
[channel
] + 2*PPM_CH_CENTER(channel
) - 2*PPM_CENTER
;
123 pulseValue
= limit(1, (value
* 512 / 682) + 1024, 2046);
131 PxxTransport::addByte(pulseValueLow
); // Low byte of channel
132 PxxTransport::addByte(((pulseValueLow
>> 8) & 0x0F) | (pulseValue
<< 4)); // 4 bits each from 2 channels
133 PxxTransport::addByte(pulseValue
>> 4); // High byte of channel
136 pulseValueLow
= pulseValue
;
141 template <class PxxTransport
>
142 void Pxx1Pulses
<PxxTransport
>::add8ChannelsFrame(uint8_t module
, uint8_t sendUpperChannels
, uint8_t sendFailsafe
)
144 PxxTransport::initCrc();
150 PxxTransport::addByte(g_model
.header
.modelId
[module
]);
153 addFlag1(module
, sendFailsafe
);
156 PxxTransport::addByte(0);
159 addChannels(module
, sendFailsafe
, sendUpperChannels
);
162 addExtraFlags(module
);
171 PxxTransport::addTail();
174 template <class PxxTransport
>
175 void Pxx1Pulses
<PxxTransport
>::setupFrame(uint8_t module
)
177 uint8_t sendUpperChannels
= 0;
178 uint8_t sendFailsafe
= 0;
180 PxxTransport::initFrame(PXX_PULSES_PERIOD
);
182 #if defined(PXX_FREQUENCY_HIGH)
183 if (moduleState
[module
].protocol
== PROTOCOL_CHANNELS_PXX1_SERIAL
) {
184 if (moduleState
[module
].counter
-- == 0) {
186 moduleState
[module
].counter
= 1000;
188 add8ChannelsFrame(module
, 0, sendFailsafe
);
189 if (sentModuleChannels(module
) > 8) {
190 add8ChannelsFrame(module
, 8, sendFailsafe
);
196 if (moduleState
[module
].counter
& 0x01) {
197 sendUpperChannels
= g_model
.moduleData
[module
].channelsCount
;
198 if (sendUpperChannels
&& moduleState
[module
].counter
== 1) {
203 if (moduleState
[module
].counter
== 0) {
208 add8ChannelsFrame(module
, sendUpperChannels
, sendFailsafe
);
210 if (moduleState
[module
].counter
-- == 0) {
211 moduleState
[module
].counter
= 1000;
215 template class Pxx1Pulses
<StandardPxx1Transport
<PwmPxxBitTransport
> >;
216 template class Pxx1Pulses
<StandardPxx1Transport
<SerialPxxBitTransport
> >;
217 template class Pxx1Pulses
<UartPxx1Transport
>;