Newer
Older
#include <atmel_start.h>
#include <stdlib.h>
#include <i2c_slave.h>
#include <flash_utils.h>
#include <float_utils.h>
#include <usb_debug.h>
#define STATUS_BYTE_CML_SHIFT 1
const char MFR_ID[] = "CERN (BE/CO)";
const char MFR_MDL[] = "DI/OT MoniMod";
#if defined MMRTSB
const char MFR_REV[] = "0.2p-RTSB";
#elif defined MMFANT
const char MFR_REV[] = "0.2p-FANT";
#elif defined MMRATO
const char MFR_REV[] = "0.2p-RATO";
#elif defined MMPROT
const char MFR_REV[] = "0.2p-PROT";
#else
const char MFR_REV[] = "0.2p-ERRO";
#error Exactly one of MMRTSB, MMFANT, MMRATO or MMPROT has to be defined
#endif
const char MFR_LOC[] = "Geneva";
const char MFR_SER[] = "123456789";
const char IC_DEVICE_REV[] = __GIT_VER__;
#ifdef USE_LINEAR16
const uint8_t vout_mode = 0x16; // linear mode, fixed 2^10 exponent
#else
const uint8_t vout_mode = 0xe0; // not compliant to the standard, set mode bits to (invalid) 3'b111
#endif
void page_chk();
uint16_t page __xMR;
extern uint16_t use_pec __xMR;
void set_pec();
void read_status_b(void);
void get_status_cml(void);
void write_status_cml(void);
extern uint8_t status_b;
extern uint8_t status_cml;
static uint8_t status_cml_tmp;
void accvolt();
void acccurr();
void accpowr();
uint16_t curpage_volt;
uint16_t curpage_curr;
void query_prp();
void query_cln();
#ifdef MMRTSB
#define MAX_PAGE 3
#else
#define MAX_PAGE 2
#endif
extern uint16_t volts_lin[MAX_PAGE+1];
extern uint16_t currs_lin[MAX_PAGE+1];
extern uint16_t powrs_lin[MAX_PAGE+1];
extern uint16_t temps_lin[3];
extern uint16_t frpms_lin[3];
extern uint32_t seconds_up;
uint32_t TMR_ERROR_CNT;
static uint8_t dummy_byte;
void set_frpms();
uint16_t setfrpms_lin[3];
extern uint16_t setfrpms[3] __xMR;
void set_tc_curve();
uint16_t temp_curve_points_data[7];
extern float temp_curve_points_x[3][3] __xMR;
extern float temp_curve_points_y[3][3] __xMR;
void set_tc_matrix();
void set_tc_onoff();
uint16_t temp_matrix_row[3]; // these rows mix the 3 temps separately for each fan
uint8_t tc_on;
extern float temp_matrix[3][3] __xMR;
extern uint16_t temp_control_on __xMR;
uint8_t fan_config_1_2;
uint8_t fan_config_3_4;
void fan_config();
void get_fan_configs();
extern uint16_t fan_installed[3] __xMR;
extern uint16_t fan_cmdrpm[3] __xMR;
extern uint16_t fan_ppr[3] __xMR;
void uc_reset();
void boot_new_fw();
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
enum {
cmd_0x00 = 0,
cmd_0x1A,
cmd_0x20,
cmd_0x3A,
cmd_0x3B,
cmd_0x3C,
cmd_0x3D,
cmd_0x3E,
cmd_0x78,
cmd_0x7E,
cmd_0x8B,
cmd_0x8C,
cmd_0x8D,
cmd_0x8E,
cmd_0x8F,
cmd_0x90,
cmd_0x91,
cmd_0x92,
cmd_0x96,
cmd_0x99,
cmd_0x9A,
cmd_0x9B,
cmd_0x9C,
cmd_0x9D,
cmd_0x9E,
cmd_0xAE,
/* extended commands */
cmd_0xFF05,
cmd_0xFF06,
cmd_0xFF10,
cmd_0xFFA0,
cmd_0xFFB0,
cmd_0xFFC0,
cmd_0xFFC1,
cmd_0xFFC4,
};
/* "- 1" to avoid adding null char at the end of a string */
static const int8_t cmd_data_lengths[] = {
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
[cmd_0x00] = 1,
[cmd_0x1A] = -1,
[cmd_0x20] = 1,
[cmd_0x3A] = 1,
[cmd_0x3B] = 2,
[cmd_0x3C] = 2,
[cmd_0x3D] = 1,
[cmd_0x3E] = 2,
[cmd_0x78] = 1,
[cmd_0x7E] = 1,
[cmd_0x8B] = 2,
[cmd_0x8C] = 2,
[cmd_0x8D] = 2,
[cmd_0x8E] = 2,
[cmd_0x8F] = 2,
[cmd_0x90] = 2,
[cmd_0x91] = 2,
[cmd_0x92] = 2,
[cmd_0x96] = 2,
[cmd_0x99] = -((int8_t)sizeof(MFR_ID) - 1),
[cmd_0x9A] = -((int8_t)sizeof(MFR_MDL) - 1),
[cmd_0x9B] = -((int8_t)sizeof(MFR_REV) - 1),
[cmd_0x9C] = -((int8_t)sizeof(MFR_LOC) - 1),
[cmd_0x9D] = -((int8_t)sizeof(MFR_DAT) - 1),
[cmd_0x9E] = -((int8_t)sizeof(MFR_SER) - 1),
[cmd_0xAE] = -((int8_t)sizeof(IC_DEVICE_REV) - 1),
/* extended commands */
[cmd_0xFF05] = 1,
[cmd_0xFF06] = 1,
[cmd_0xFF10] = 4,
[cmd_0xFFA0] = 4,
[cmd_0xFFB0] = 1,
[cmd_0xFFC0] = 13,
[cmd_0xFFC1] = 7,
[cmd_0xFFC4] = 1
// only block write-block read process calls modify the length
static int8_t cmd_data_length_query = -1;
static const cmd_t cmds_cmds[] = (cmd_t[]){
{0x0000, (int8_t *)&cmd_data_lengths[cmd_0x00], (uint8_t *)&page_tmp, (fp_t)NULL, &page_chk, (fp_t)NULL, QUERY_WR | QUERY_RD | QUERY_FMT_8B, 0},
{0x001A, (int8_t *)&cmd_data_length_query, (uint8_t *)&query_r, (fp_t)NULL, &query_prp, (fp_t)NULL, QUERY_SUP, 1},
{0x0020, (int8_t *)&cmd_data_lengths[cmd_0x20], (uint8_t *)&vout_mode, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD, 1},
{0x003A, (int8_t *)&cmd_data_lengths[cmd_0x3A], (uint8_t *)&fan_config_1_2, &get_fan_configs, &fan_config, (fp_t)NULL, QUERY_WR | QUERY_FMT_NAN, 0},
{0x003B, (int8_t *)&cmd_data_lengths[cmd_0x3B], (uint8_t *)&setfrpms_lin[0], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0},
{0x003C, (int8_t *)&cmd_data_lengths[cmd_0x3C], (uint8_t *)&setfrpms_lin[1], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0},
{0x003D, (int8_t *)&cmd_data_lengths[cmd_0x3D], (uint8_t *)&fan_config_3_4, &get_fan_configs, &fan_config, (fp_t)NULL, QUERY_WR | QUERY_FMT_NAN, 0},
{0x003E, (int8_t *)&cmd_data_lengths[cmd_0x3E], (uint8_t *)&setfrpms_lin[2], (fp_t)NULL, &set_frpms, (fp_t)NULL, QUERY_WR | QUERY_FMT_LIN, 0},
{0x0078, (int8_t *)&cmd_data_lengths[cmd_0x78], (uint8_t *)&status_b, &read_status_b, (fp_t)NULL, (fp_t)NULL, QUERY_RD, 0},
{0x007E, (int8_t *)&cmd_data_lengths[cmd_0x7E], (uint8_t *)&status_cml_tmp, &get_status_cml, &write_status_cml, (fp_t)NULL, QUERY_WR | QUERY_RD, 0},
{0x008B, (int8_t *)&cmd_data_lengths[cmd_0x8B], (uint8_t *)&curpage_volt, &accvolt, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x008C, (int8_t *)&cmd_data_lengths[cmd_0x8C], (uint8_t *)&curpage_curr, &acccurr, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x008D, (int8_t *)&cmd_data_lengths[cmd_0x8D], (uint8_t *)&temps_lin[0], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x008E, (int8_t *)&cmd_data_lengths[cmd_0x8E], (uint8_t *)&temps_lin[1], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x008F, (int8_t *)&cmd_data_lengths[cmd_0x8F], (uint8_t *)&temps_lin[2], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x0090, (int8_t *)&cmd_data_lengths[cmd_0x90], (uint8_t *)&frpms_lin[0], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x0091, (int8_t *)&cmd_data_lengths[cmd_0x91], (uint8_t *)&frpms_lin[1], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x0092, (int8_t *)&cmd_data_lengths[cmd_0x92], (uint8_t *)&frpms_lin[2], (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x0096, (int8_t *)&cmd_data_lengths[cmd_0x96], (uint8_t *)&curpage_powr, &accpowr, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_LIN, 0},
{0x0099, (int8_t *)&cmd_data_lengths[cmd_0x99], (uint8_t *)&MFR_ID, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x009A, (int8_t *)&cmd_data_lengths[cmd_0x9A], (uint8_t *)&MFR_MDL, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x009B, (int8_t *)&cmd_data_lengths[cmd_0x9B], (uint8_t *)&MFR_REV, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x009C, (int8_t *)&cmd_data_lengths[cmd_0x9C], (uint8_t *)&MFR_LOC, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x009D, (int8_t *)&cmd_data_lengths[cmd_0x9D], (uint8_t *)&MFR_DAT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x009E, (int8_t *)&cmd_data_lengths[cmd_0x9E], (uint8_t *)&MFR_SER, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0x00AE, (int8_t *)&cmd_data_lengths[cmd_0xAE], (uint8_t *)&IC_DEVICE_REV, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, QUERY_RD | QUERY_FMT_NAN, 0},
{0xFF05, (int8_t *)&cmd_data_lengths[cmd_0xFF05], (uint8_t *)&dummy_byte, (fp_t)NULL, &boot_new_fw, (fp_t)NULL, 0, 0},
{0xFF06, (int8_t *)&cmd_data_lengths[cmd_0xFF06], (uint8_t *)&dummy_byte, (fp_t)NULL, &uc_reset, (fp_t)NULL, 0, 0},
{0xFF10, (int8_t *)&cmd_data_lengths[cmd_0xFF10], (uint8_t *)&seconds_up, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, 0, 0},
{0xFFA0, (int8_t *)&cmd_data_lengths[cmd_0xFFA0], (uint8_t *)&TMR_ERROR_CNT, (fp_t)NULL, (fp_t)NULL, (fp_t)NULL, 0, 0},
{0xFFB0, (int8_t *)&cmd_data_lengths[cmd_0xFFB0], (uint8_t *)&use_pec_tmp, (fp_t)NULL, &set_pec, (fp_t)NULL, 0, 1},
{0xFFC0, (int8_t *)&cmd_data_lengths[cmd_0xFFC0], (uint8_t *)&temp_curve_points_data, (fp_t)NULL, &set_tc_curve, (fp_t)NULL, 0, 0},
{0xFFC1, (int8_t *)&cmd_data_lengths[cmd_0xFFC1], (uint8_t *)&temp_matrix_row, (fp_t)NULL, &set_tc_matrix, (fp_t)NULL, 0, 0},
{0xFFC4, (int8_t *)&cmd_data_lengths[cmd_0xFFC4], (uint8_t *)&tc_on, (fp_t)NULL, &set_tc_onoff, (fp_t)NULL, 0, 0}
};
cmd_space_t cmds = {
sizeof(cmds_cmds)/sizeof(cmd_t),
cmds_cmds
static uint32_t fw_write_buf[FLASH_ROW_SIZE/4];
void uc_reset()
{
#ifdef USB_ENABLE
usbdc_detach();
usbdc_stop();
usbdc_deinit();
NVIC_SystemReset();
}
void boot_new_fw()
{
uint32_t *char_user_flash = (uint32_t *)&user_flash;
user_flash_t *tmp_user_flash = (user_flash_t *)&fw_write_buf;
/* backup existing user data */
for (uint8_t i = 0; i < FLASH_ROW_SIZE/4; ++i)
fw_write_buf[i] = char_user_flash[i];
/* set 0xBEC0ABCD copy FW code */
tmp_user_flash->copy_fw = 0xbec0abcd;
/* copy modified block back to the flash */
flash_write_row((uint32_t *)&user_flash, (uint32_t *)fw_write_buf);
/* reset the uC */
uc_reset();
}
void __xMR page_chk()
if (page_tmp > MAX_PAGE)
page = MAX_PAGE;
else
page = page_tmp;
}
void __xMR accvolt()
curpage_volt = volts_lin[page];
}
void __xMR acccurr()
curpage_curr = currs_lin[page];
}
void __xMR accpowr()
curpage_powr = powrs_lin[page];
void query_prp()
int16_t cmd_idx = in_addr_space(&cmds, query_r);
if (cmd_idx != -1)
query_r = QUERY_SUP | cmds.cmds[cmd_idx].query_byte;
void __xMR set_pec()
{
use_pec = use_pec_tmp;
}
void read_status_b(void)
{
status_b = status_cml ? 1 << STATUS_BYTE_CML_SHIFT : 0;
}
void get_status_cml(void)
status_cml_tmp = status_cml;
}
void write_status_cml(void)
/* clear only bits set to 1 */
status_cml &= ~status_cml_tmp;
}
#if defined(MMFANT) || defined(MMPROT)
void __xMR fan_config()
{
fan_installed[0] = (fan_config_1_2 >> 7) & 0x1;
fan_cmdrpm[0] = (fan_config_1_2 >> 6) & 0x1;
fan_ppr[0] = (fan_config_1_2 >> 4) & 0x3;
fan_installed[1] = (fan_config_1_2 >> 3) & 0x1;
fan_cmdrpm[1] = (fan_config_1_2 >> 2) & 0x1;
fan_ppr[1] = fan_config_1_2 & 0x3;
fan_installed[2] = (fan_config_3_4 >> 7) & 0x1;
fan_cmdrpm[2] = (fan_config_3_4 >> 6) & 0x1;
fan_ppr[2] = (fan_config_3_4 >> 4) & 0x3;
uint32_t *char_user_flash = (uint32_t *)&user_flash;
user_flash_t *tmp_user_flash = (user_flash_t *)&fw_write_buf;
/* backup existing user data */
for (uint8_t i = 0; i < FLASH_ROW_SIZE/4; ++i)
fw_write_buf[i] = char_user_flash[i];
/* set 0xBEC0ABCD copy FW code */
for (uint8_t i = 0; i < 3; ++i) {
tmp_user_flash->fan_installed[i] = fan_installed[i];
tmp_user_flash->fan_cmdrpm[i] = fan_cmdrpm[i];
tmp_user_flash->fan_ppr[i] = fan_ppr[i];
}
/* copy modified block back to the flash */
flash_write_row((uint32_t *)&user_flash, (uint32_t *)fw_write_buf);
}
void __xMR get_fan_configs()
{
fan_config_1_2 = (fan_installed[0] << 7) | (fan_cmdrpm[0] << 6) | (fan_ppr[0] << 4) |
(fan_installed[1] << 3) | (fan_cmdrpm[1] << 2) | (fan_ppr[1]);
fan_config_3_4 = (fan_installed[2] << 7) | (fan_cmdrpm[2] << 6) | (fan_ppr[2] << 4);
}
void __xMR set_frpms()
{
setfrpms[0] = linear_to_float(setfrpms_lin[0]);
setfrpms[1] = linear_to_float(setfrpms_lin[1]);
setfrpms[2] = linear_to_float(setfrpms_lin[2]);
uint32_t *char_user_flash = (uint32_t *)&user_flash;
user_flash_t *tmp_user_flash = (user_flash_t *)&fw_write_buf;
/* backup existing user data */
for (uint8_t i = 0; i < FLASH_ROW_SIZE/4; ++i)
fw_write_buf[i] = char_user_flash[i];
/* set 0xBEC0ABCD copy FW code */
for (uint8_t i = 0; i < 3; ++i)
tmp_user_flash->setfrpms[i] = setfrpms[i];
/* copy modified block back to the flash */
flash_write_row((uint32_t *)&user_flash, (uint32_t *)fw_write_buf);
void __xMR set_tc_curve()
uint8_t fan_n = temp_curve_points_data[0];
for (uint8_t i = 0; i < 3; ++i) {
temp_curve_points_x[fan_n][i] = linear_to_float(temp_curve_points_data[1 + 2*i]);
temp_curve_points_y[fan_n][i] = linear_to_float(temp_curve_points_data[1 + 2*i + 1]);
}
}
void __xMR set_tc_matrix()
uint8_t fan_n = temp_matrix_row[0];
for (uint8_t i = 0; i < 3; ++i) {
temp_matrix[fan_n][i] = linear_to_float(temp_matrix_row[1 + i]);
}
}
void __xMR set_tc_onoff()
{
temp_control_on = tc_on;
}
#else
void fan_config()
{
}
void get_fan_configs()
{
}