@@ -17,7 +17,7 @@ bool isChangeChannelCmd(CommandAbstract &cmd) {
17
17
18
18
uint32_t FrequencyManager_CMT::getTXFrequency (CommandAbstract& cmd) {
19
19
uint32_t freq = this ->_getFrequency (cmd);
20
- if (isChangeChannelCmd (cmd) && freq == Hoymiles.getRadioCmt ()->getInverterTargetFrequency ()) {
20
+ if (isChangeChannelCmd (cmd) && freq == Hoymiles.getRadioCmt ()->getInverterTargetFrequency ()) {
21
21
return Hoymiles.getRadioCmt ()->getInvBootFrequency ();
22
22
}
23
23
return freq;
@@ -30,27 +30,46 @@ uint32_t FrequencyManager_CMT::getRXFrequency(CommandAbstract& cmd) {
30
30
return this ->_getFrequency (cmd);
31
31
}
32
32
33
- uint32_t _get_cmt_search_frequency (int failed_fetch_count, uint8_t cmd_send_count, uint32_t inverter_target_frequency, uint32_t min_frequency, uint32_t max_frequency, uint32_t legal_min_frequency, uint32_t legal_max_frequency, uint32_t channel_width) {
34
- uint8_t cmd_retransmit_count = cmd_send_count-1 ;
35
- int8_t offset = ((failed_fetch_count + cmd_retransmit_count) % 20 ) * (cmd_retransmit_count%2 ==0 ?-1 :1 );
36
-
33
+ // https://stackoverflow.com/a/14997413
34
+ inline int positive_modulo (int i, int n) {
35
+ return (i % n + n) % n;
36
+ }
37
+
38
+ uint32_t _get_cmt_search_frequency (int failed_fetch_count, int cmd_send_count, uint32_t inverter_target_frequency, uint32_t min_frequency, uint32_t max_frequency, uint32_t legal_min_frequency, uint32_t legal_max_frequency, uint32_t channel_width) {
39
+ // cmt_send_count gets incremented in sendEsbPacket just before we are called; we do -1 to undo this
40
+ // _getFrequency also grabs the first transmission, setting it to inverterTargetFrequency. we do -1 to undo this as well
41
+ int cmd_transmissions_we_did = cmd_send_count-2 ; // how often this particular command has already been sent on a freq determined by this function
42
+
43
+ // failed_fetch_count starts at 1, due to how startsNextFetch counts
44
+ int fetches_we_did = failed_fetch_count - 1 ;
45
+
46
+ int offset2 = (fetches_we_did + (cmd_transmissions_we_did/2 )) % 20 ;
47
+ int offset3 = offset2 * (cmd_transmissions_we_did%2 ==0 ?-1 :1 );
48
+
37
49
uint32_t min_usable_freq = max (min_frequency, legal_min_frequency);
38
50
uint32_t max_usable_freq = min (max_frequency, legal_max_frequency);
39
- int8_t min_offset = -((inverter_target_frequency - min_usable_freq)/channel_width);
40
- int8_t max_offset = (max_usable_freq - inverter_target_frequency)/channel_width;
51
+ int min_offset = -((inverter_target_frequency - min_usable_freq)/channel_width);
52
+ int max_offset = (max_usable_freq - inverter_target_frequency)/channel_width;
53
+
54
+ int final_offset = (positive_modulo (offset3 - min_offset, max_offset + 1 - min_offset)) + min_offset;
41
55
42
- offset = ((offset - min_offset) % (max_offset - min_offset)) + min_offset;
43
-
44
- return inverter_target_frequency + (offset*channel_width);
56
+ int ret = inverter_target_frequency + (final_offset*channel_width);
57
+ Hoymiles.getMessageOutput ()->printf (" cmt_search_frequency min_offset=%" PRId32 " max_offset=%" PRId32 " \r\n " , min_offset, max_offset);
58
+ Hoymiles.getMessageOutput ()->printf (" cmt_search_frequency failed_fetch_count=%" PRId32 " cmd_send_count=%" PRId32 " now trying %.3f MHz\r\n " , failed_fetch_count, cmd_send_count, ret / 1000000.0 );
59
+ Hoymiles.getMessageOutput ()->printf (" cmt_search_frequency offset2 %" PRId32 " offset3 %" PRId32 " final_offset %" PRId32 " \r\n " , offset2, offset3, final_offset);
60
+ return ret;
45
61
}
46
62
47
63
uint32_t FrequencyManager_CMT::_getFrequency (CommandAbstract& cmd) {
48
64
HoymilesRadio_CMT *radio = Hoymiles.getRadioCmt ();
49
65
uint32_t tgt_freq = radio->getInverterTargetFrequency ();
50
- uint8_t cmd_retransmit_count = cmd.getSendCount ()-1 ;
66
+ int cmd_retransmit_count = cmd.getSendCount ()-1 ;
51
67
52
- if (this ->_inv ->isReachable () || this ->_failedFetchCount == -1 ) {
53
- // _lastWorkingFrequency was apparently working
68
+ if (_lastWorkingFrequency == 0 ) {
69
+ return tgt_freq; // see shouldSendChangeChannelCommand
70
+ }
71
+ if (this ->_inv ->isReachable () || this ->_failedFetchCount <= 0 ) {
72
+ // _lastWorkingFrequency was working
54
73
bool isOnTgtFreq = this ->_lastWorkingFrequency == tgt_freq;
55
74
if (isOnTgtFreq) {
56
75
return tgt_freq;
@@ -86,7 +105,14 @@ void FrequencyManager_CMT::processRXResult(CommandAbstract *cmd, uint8_t verify_
86
105
87
106
88
107
bool FrequencyManager_CMT::shouldSendChangeChannelCommand () {
89
- return this ->_lastWorkingFrequency != Hoymiles.getRadioCmt ()->getInverterTargetFrequency () || (!this ->_inv ->isReachable ());
108
+ if (!this ->_inv ->isReachable ()) {
109
+ return true ;
110
+ } else {
111
+ if (this ->_lastWorkingFrequency == 0 ) {
112
+ return false ; // 0 means FRAGMENT_OK was never received, i.e. no packet since OpenDTU boot. return false to preserve old startup sequence
113
+ }
114
+ return this ->_lastWorkingFrequency != Hoymiles.getRadioCmt ()->getInverterTargetFrequency ();
115
+ }
90
116
}
91
117
92
118
void FrequencyManager_CMT::startNextFetch () {
@@ -95,4 +121,4 @@ void FrequencyManager_CMT::startNextFetch() {
95
121
} else {
96
122
this ->_failedFetchCount ++;
97
123
}
98
- }
124
+ }
0 commit comments