forked from ckolivas/cgminer
-
Notifications
You must be signed in to change notification settings - Fork 30
/
dm_temp_ctrl.c
203 lines (176 loc) · 6.5 KB
/
dm_temp_ctrl.c
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
* Copyright 2018 Duan Hao
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version. See COPYING for more details.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "dragonmint_t1.h"
#include "dm_temp_ctrl.h"
/******************************************************************************
* Macros & Constants
******************************************************************************/
#define INVALID_TEMP (9999)
/******************************************************************************
* Global variables
******************************************************************************/
volatile c_temp_cfg g_tmp_cfg; // configs of temperature control
volatile c_temp g_chain_tmp[MAX_CHAIN_NUM]; // current temperature per chain
volatile int g_tmp_last_upd_time[MAX_CHAIN_NUM];
static uint32_t g_temp_status[MAX_CHAIN_NUM];
/******************************************************************************
* Prototypes
******************************************************************************/
/******************************************************************************
* Implementations
******************************************************************************/
/******************************************************************************
* Function: dm_tempctrl_get_defcfg
* Description: get default configs for temerature control
* Arguments: p_cfg temperature configs
* Return: none
******************************************************************************/
void dm_tempctrl_get_defcfg(c_temp_cfg *p_cfg)
{
p_cfg->tmp_min = -40;
p_cfg->tmp_max = 125;
p_cfg->tmp_target = 75;
p_cfg->tmp_thr_lo = 30;
p_cfg->tmp_thr_hi = 95;
p_cfg->tmp_thr_warn = 105;
p_cfg->tmp_thr_pd = 115;
p_cfg->tmp_exp_time = 2000; // 2s
}
void dm_tempctrl_set(c_temp_cfg *p_cfg)
{
g_tmp_cfg = *p_cfg;
}
/******************************************************************************
* Function: dm_tempctrl_init
* Description: temperature control initializition
* Arguments: p_cfg temperature configs
* Return: none
******************************************************************************/
void dm_tempctrl_init(c_temp_cfg *p_cfg)
{
int i;
// FIXME: add mutex here
if (NULL == p_cfg) {
c_temp_cfg cfg;
dm_tempctrl_get_defcfg(&cfg); // avoid to pass volatile pointer directly
dm_tempctrl_set(&cfg);
} else
dm_tempctrl_set(p_cfg);
for(i = 0; i < MAX_CHAIN_NUM; ++i) {
g_chain_tmp[i].tmp_lo = g_chain_tmp[i].tmp_hi
= g_chain_tmp[i].tmp_avg = INVALID_TEMP;
}
}
#ifndef USE_AUTOCMD0A
static void dm_tempctrl_get_chain_temp(int *chip_temp, c_temp *chain_temp)
{
int i, cnt, avg, index = -1;
int compr_desc(const void *a, const void *b) {
return (*(int*)b - *(int*)a);
}
/* Sort descending */
qsort(chip_temp, g_chip_num, sizeof(int), compr_desc);
cnt = avg = 0;
for (i = 0; i < g_chip_num; ++i) {
if (chip_temp[i] < g_tmp_cfg.tmp_max && chip_temp[i] > g_tmp_cfg.tmp_min) {
/* Find the first valid temperature */
if (index == -1)
index = i;
/* Get the average temperature */
avg += chip_temp[i];
cnt++;
}
}
if (cnt > 6) {
/* Ignore the highest one and get average of maximal two tempertures */
chain_temp->tmp_hi = (chip_temp[index + 1] + chip_temp[index + 2]) >> 1;
/* Ignore the lowest one and get average of minimal two tempertures */
chain_temp->tmp_lo = (chip_temp[g_chip_num - 2] + chip_temp[g_chip_num - 3]) >> 1;
chain_temp->tmp_avg = avg / cnt;
} else {
chain_temp->tmp_hi = INVALID_TEMP;
chain_temp->tmp_lo = INVALID_TEMP;
chain_temp->tmp_avg = INVALID_TEMP;
}
}
#endif
/******************************************************************************
* Function: dm_tempctrl_update_chain_temp
* Description: update temperature of single chain
* Arguments: chain_id chain id
* Return: device temperature state
******************************************************************************/
uint32_t dm_tempctrl_update_chain_temp(int chain_id)
{
uint32_t *tstatus = &g_temp_status[chain_id];
c_temp chain_temp;
/* Do not read temperature unless given time has passed or the last
* reading was invalid. Return the last value in that case. */
int curr_time = get_current_ms();
if (curr_time - g_tmp_last_upd_time[chain_id] < g_tmp_cfg.tmp_exp_time &&
*tstatus != (uint32_t)TEMP_INVALID)
goto out;
g_tmp_last_upd_time[chain_id] = curr_time;
// FIXME: add mutex here
#ifdef USE_AUTOCMD0A
if (!mcompat_get_chain_temp(chain_id, &chain_temp))
applog(LOG_ERR, "chain%d: failed to read chain temperature", chain_id);
#else
int chip_temp[MCOMPAT_CONFIG_MAX_CHIP_NUM];
mcompat_get_chip_temp(chain_id, chip_temp);
dm_tempctrl_get_chain_temp(chip_temp, &chain_temp);
#endif
applog(LOG_DEBUG, "chain%d: Tmax=%d, Tmin=%d, Tavg=%d",
chain_id, chain_temp.tmp_hi, chain_temp.tmp_lo, chain_temp.tmp_avg);
if (chain_temp.tmp_hi > g_tmp_cfg.tmp_max || chain_temp.tmp_hi < g_tmp_cfg.tmp_min
|| chain_temp.tmp_lo > g_tmp_cfg.tmp_max || chain_temp.tmp_lo < g_tmp_cfg.tmp_min
|| chain_temp.tmp_avg > g_tmp_cfg.tmp_max || chain_temp.tmp_avg < g_tmp_cfg.tmp_min) {
applog(LOG_ERR, "error temperature ignored: Tmax=%d, Tmin=%d, Tavg=%d",
chain_temp.tmp_hi, chain_temp.tmp_lo, chain_temp.tmp_avg);
*tstatus = TEMP_INVALID;
goto out;
}
g_chain_tmp[chain_id] = chain_temp;
g_chain_tmp[chain_id].optimal = false;
if (g_chain_tmp[chain_id].tmp_hi >= g_tmp_cfg.tmp_thr_pd)
*tstatus = TEMP_SHUTDOWN;
else if (g_chain_tmp[chain_id].tmp_hi >= g_tmp_cfg.tmp_thr_warn)
*tstatus = TEMP_WARNING;
else if (g_chain_tmp[chain_id].tmp_hi >= g_tmp_cfg.tmp_thr_hi)
*tstatus = TEMP_TOO_HIGH;
else if (g_chain_tmp[chain_id].tmp_lo < g_tmp_cfg.tmp_thr_lo)
*tstatus = TEMP_TOO_LOW;
else {
if (g_chain_tmp[chain_id].tmp_avg > g_tmp_cfg.tmp_target - TEMP_TOLERANCE)
g_chain_tmp[chain_id].optimal = true;
*tstatus = TEMP_NORMAL;
}
out:
return *tstatus;
}
/******************************************************************************
* Function: dm_tempctrl_update_temp
* Description: update temperature of one or more chains
* Arguments: chain_mask chain id mask
* Return: device temperture state
******************************************************************************/
void dm_tempctrl_update_temp(uint8_t chain_mask)
{
int i;
for (i = 0; i < MAX_CHAIN_NUM; ++i)
{
if(chain_mask & (1 << i))
{
dm_tempctrl_update_chain_temp(i);
}
}
}