|
@@ -0,0 +1,525 @@
|
|
|
+/*
|
|
|
+ * Phihong_PsuCommObj.c
|
|
|
+ *
|
|
|
+ * Created on: 2019年7月2日
|
|
|
+ * Author: 7564
|
|
|
+ */
|
|
|
+
|
|
|
+#include "Phihong_PsuCommObj.h"
|
|
|
+
|
|
|
+struct Current_cmd_Proc Psu_cmd={
|
|
|
+ 0,
|
|
|
+ 0x02000200,
|
|
|
+ 0x01000300,
|
|
|
+ 0x01000400,
|
|
|
+ 0x01000500,
|
|
|
+ 0x01000600,
|
|
|
+ 0x01000700,
|
|
|
+ 0x01000800,
|
|
|
+ 0x01000900,
|
|
|
+ 0x02000A00,
|
|
|
+
|
|
|
+ 0x02000B00,
|
|
|
+ 0x01000C00,
|
|
|
+ 0x02000F00,
|
|
|
+ 0x02001000,
|
|
|
+ 0x02001100,
|
|
|
+ 0x02001200,
|
|
|
+
|
|
|
+ 0x01001300,
|
|
|
+ 0x02001400,
|
|
|
+ 0x01001500,
|
|
|
+ 0x01001600,
|
|
|
+ 0x02001700,
|
|
|
+
|
|
|
+ 0x01001800,
|
|
|
+ 0x01001900,
|
|
|
+ 0x01001A00,
|
|
|
+
|
|
|
+ 0x02001B00,
|
|
|
+ 0x0E001C00,
|
|
|
+};
|
|
|
+
|
|
|
+//================================================
|
|
|
+// Callback function
|
|
|
+//================================================
|
|
|
+void GetPsuAddressReq(void *func)
|
|
|
+{
|
|
|
+ get_psu_addr_req = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshStatus(void *func)
|
|
|
+{
|
|
|
+ return_status = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshFWVersion(void *func)
|
|
|
+{
|
|
|
+ return_fw_version = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshFanSpeed(void *func)
|
|
|
+{
|
|
|
+ return_fan_speed = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshTemp(void *func)
|
|
|
+{
|
|
|
+ return_temp = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshInputVol(void *func)
|
|
|
+{
|
|
|
+ return_input_vol = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshGetOutput(void *func)
|
|
|
+{
|
|
|
+ return_get_output = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshInputCur(void *func)
|
|
|
+{
|
|
|
+ return_input_cur = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshHWVersion(void *func)
|
|
|
+{
|
|
|
+ //return_hw_version = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshAvailableCap(void *func)
|
|
|
+{
|
|
|
+ return_available_cap = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshAlarmNotify(void *func)
|
|
|
+{
|
|
|
+ return_alarm_code = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshFaultNotify(void *func)
|
|
|
+{
|
|
|
+ return_fault_code = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshStatusNotify(void *func)
|
|
|
+{
|
|
|
+ return_status_code = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshSerialNumber(void *func)
|
|
|
+{
|
|
|
+ return_get_serial_number = func;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshOutputPowerSwitch(void *func)
|
|
|
+{
|
|
|
+ return_output_pow_switch = func;
|
|
|
+}
|
|
|
+//================================================
|
|
|
+// CANBUS initialization
|
|
|
+//================================================
|
|
|
+int InitCanBus()
|
|
|
+{
|
|
|
+ int s0,nbytes;
|
|
|
+ struct timeval tv;
|
|
|
+ struct ifreq ifr0;
|
|
|
+ struct sockaddr_can addr0;
|
|
|
+
|
|
|
+ system("/sbin/ip link set can1 down");
|
|
|
+ system("/sbin/ip link set can1 type can bitrate 500000 restart-ms 100");
|
|
|
+ system("/sbin/ip link set can1 up");
|
|
|
+
|
|
|
+ s0 = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
|
|
+
|
|
|
+ tv.tv_sec = 0;
|
|
|
+ tv.tv_usec = 10000;
|
|
|
+ if (setsockopt(s0, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)) < 0)
|
|
|
+ {
|
|
|
+ #ifdef SystemLogMessage
|
|
|
+ printf("Set SO_RCVTIMEO NG");
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+ nbytes=40960;
|
|
|
+ if (setsockopt(s0, SOL_SOCKET, SO_RCVBUF, &nbytes, sizeof(int)) < 0)
|
|
|
+ {
|
|
|
+ #ifdef SystemLogMessage
|
|
|
+ printf("Set SO_RCVBUF NG");
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+ nbytes=40960;
|
|
|
+ if (setsockopt(s0, SOL_SOCKET, SO_SNDBUF, &nbytes, sizeof(int)) < 0)
|
|
|
+ {
|
|
|
+ #ifdef SystemLogMessage
|
|
|
+ printf("Set SO_SNDBUF NG");
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+
|
|
|
+ strcpy(ifr0.ifr_name, "can1" );
|
|
|
+ ioctl(s0, SIOCGIFINDEX, &ifr0); /* ifr.ifr_ifindex gets filled with that device's index */
|
|
|
+ addr0.can_family = AF_CAN;
|
|
|
+ addr0.can_ifindex = ifr0.ifr_ifindex;
|
|
|
+ bind(s0, (struct sockaddr *)&addr0, sizeof(addr0));
|
|
|
+ return s0;
|
|
|
+}
|
|
|
+
|
|
|
+//================================================
|
|
|
+// Receive Cmd from canbus
|
|
|
+//================================================
|
|
|
+void ReceiveDataFromCanBus()
|
|
|
+{
|
|
|
+ int nbytes;
|
|
|
+ struct can_frame frame;
|
|
|
+ int intCmd;
|
|
|
+ byte target, group, address;
|
|
|
+
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ memset(&frame, 0, sizeof(struct can_frame));
|
|
|
+ nbytes = read(CanFd, &frame, sizeof(struct can_frame));
|
|
|
+
|
|
|
+ if (nbytes > 0)
|
|
|
+ {
|
|
|
+ frame.can_id = frame.can_id & CAN_EFF_MASK;
|
|
|
+ intCmd = (int) (frame.can_id & 0xFFFFFF00);
|
|
|
+ target = (byte) (frame.can_id & 0x000000FF);
|
|
|
+ group = (byte) (target >> 6);
|
|
|
+ address = (byte) (target & 0x3F);
|
|
|
+
|
|
|
+ switch (intCmd)
|
|
|
+ {
|
|
|
+ case ADDRESS_REQ:
|
|
|
+ {
|
|
|
+ byte phy_addr;
|
|
|
+ char sn[7];
|
|
|
+
|
|
|
+ phy_addr = frame.data[0];
|
|
|
+ memcpy(sn, (char *)frame.data + 1, 7);
|
|
|
+ get_psu_addr_req(phy_addr, sn);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_ADDRESS_ASSINGMENT:
|
|
|
+ { }
|
|
|
+ break;
|
|
|
+ case ACK_STATUS:
|
|
|
+ {
|
|
|
+ return_status(group, address,
|
|
|
+ ((int) frame.data[3] << 24) + ((int) frame.data[2] << 16) + ((int) frame.data[1] << 8) + (int) frame.data[0],
|
|
|
+ ((int) frame.data[7] << 24) + ((int) frame.data[6] << 16) + ((int) frame.data[5] << 8) + (int) frame.data[4]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_FIRMWARE_VERSION:
|
|
|
+ {
|
|
|
+ return_fw_version(group, address, frame.data[0], frame.data[1], frame.data + 2);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_FAN_SPEED:
|
|
|
+ {
|
|
|
+ return_fan_speed(group, address,
|
|
|
+ ((short) frame.data[1] << 8) + (short) frame.data[0],
|
|
|
+ ((short) frame.data[3] << 8) + (short) frame.data[2],
|
|
|
+ ((short) frame.data[5] << 8) + (short) frame.data[4],
|
|
|
+ ((short) frame.data[7] << 8) + (short) frame.data[6]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_TEMPERATURE:
|
|
|
+ {
|
|
|
+ return_temp(group, address,
|
|
|
+ frame.data[0],
|
|
|
+ frame.data[1],
|
|
|
+ frame.data[2],
|
|
|
+ frame.data[3],
|
|
|
+ frame.data[4],
|
|
|
+ frame.data[5],
|
|
|
+ frame.data[6]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_PRESENT_INPUT_VOLTAGE:
|
|
|
+ {
|
|
|
+ return_input_vol(group, address,
|
|
|
+ frame.data[0],
|
|
|
+ ((short) frame.data[2] << 8) + (short) frame.data[1],
|
|
|
+ ((short) frame.data[4] << 8) + (short) frame.data[3],
|
|
|
+ ((short) frame.data[6] << 8) + (short) frame.data[5]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_GET_PRESENT_OUTPUT:
|
|
|
+ {
|
|
|
+ return_get_output(group, address,
|
|
|
+ (((short) frame.data[1] << 8) + (short) frame.data[0]),
|
|
|
+ (((short) frame.data[3] << 8) + (short) frame.data[2]));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_GET_SERIAL_NUMBER:
|
|
|
+ {
|
|
|
+ return_get_serial_number(group, address, frame.data[0], frame.data + 1);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_COOLING_WATER_TEMP:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_PRESENT_INPUT_CURRENT:
|
|
|
+ {
|
|
|
+ return_input_cur(group, address,
|
|
|
+ (((short) frame.data[1] << 8) + (short) frame.data[0]),
|
|
|
+ (((short) frame.data[3] << 8) + (short) frame.data[2]),
|
|
|
+ (((short) frame.data[5] << 8) + (short) frame.data[4]));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_HARDWARE_VERSION:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_PFC_OUTPUT_SWITCH:
|
|
|
+ case ACK_LOG_SIZE:
|
|
|
+ case ACK_LOG_BLOCK_CHECKSUM:
|
|
|
+ case ACK_LOG_BLOCK_DATA:
|
|
|
+ case ACK_CUSTOM_INFO_TRANSFER_SWITCH:
|
|
|
+ case ACK_SET_FAN_SPEED:
|
|
|
+ break;
|
|
|
+ case ACK_AVAILABLE_CAP:
|
|
|
+ {
|
|
|
+ return_available_cap(group, address,
|
|
|
+ (((short) frame.data[1] << 8) + (short) frame.data[0]),
|
|
|
+ (((short) frame.data[3] << 8) + (short) frame.data[2]));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_OUTPUT_POWER_SWITCH:
|
|
|
+ {
|
|
|
+ return_output_pow_switch(group, address, frame.data[0]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_SET_PRESENT_OUTPUT:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case ACK_UPGRADE_REQ:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_START_BLOCK_TRANS:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ACK_UPGRADE_FINISH:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CUSTOM_LOG_INFO:
|
|
|
+ {
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case ALARM_NOTIFICATION:
|
|
|
+ {
|
|
|
+ return_alarm_code(group, address, frame.data);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case FAULT_NOTIFICATION:
|
|
|
+ {
|
|
|
+ return_fault_code(group, address,
|
|
|
+ ((int) frame.data[3] << 24) + ((int) frame.data[2] << 16) + ((int) frame.data[1] << 8) + (int) frame.data[0]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case STATUS_NOTIFICATION:
|
|
|
+ {
|
|
|
+ return_status_code(group, address,
|
|
|
+ frame.data[0],
|
|
|
+ ((short) frame.data[2] << 8) + (short) frame.data[1],
|
|
|
+ ((short) frame.data[4] << 8) + (short) frame.data[3]);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ usleep(10000);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//================================================
|
|
|
+// Private Function
|
|
|
+//================================================
|
|
|
+int PackageIdCmd(int cmd)
|
|
|
+{
|
|
|
+ return cmd | 0x80000000;
|
|
|
+}
|
|
|
+
|
|
|
+void SendCmdToPsu(int cmd, byte *data, byte dataLen)
|
|
|
+{
|
|
|
+ struct can_frame frame;
|
|
|
+
|
|
|
+ frame.can_id = cmd;
|
|
|
+ frame.can_dlc = dataLen;
|
|
|
+ memcpy(frame.data, data, dataLen);
|
|
|
+
|
|
|
+ write(CanFd, &frame, sizeof(struct can_frame));
|
|
|
+}
|
|
|
+
|
|
|
+//================================================
|
|
|
+// API Function
|
|
|
+//================================================
|
|
|
+bool InitialCommunication()
|
|
|
+{
|
|
|
+ CanFd = InitCanBus();
|
|
|
+
|
|
|
+ if(CanFd < 0)
|
|
|
+ {
|
|
|
+ printf("Init can bus fail.\n");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ recFork = fork();
|
|
|
+ if(recFork > 0)
|
|
|
+ {
|
|
|
+ ReceiveDataFromCanBus();
|
|
|
+ }
|
|
|
+ else if(recFork > 0)
|
|
|
+ {
|
|
|
+ printf("fork fail\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+void PsuAddressAssignment(byte phy_addr, char *serial_number, byte real_addr, byte group)
|
|
|
+{
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._address_assignment);
|
|
|
+
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ data[0] = (group << 6) + real_addr;
|
|
|
+ memcpy(data + 1, serial_number, 7);
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetStatus(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetStatus. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_status + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetFwVersion(byte group, byte address, byte type)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetFwVersion. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_fw_ver + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ data[0] = type;
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetSerialNumber(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetSerialNumber. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_serial_number + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetFanSpeed(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetFanSpeed. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_fan_speed + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetTemperature(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetTemperature. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_temperature + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetPresentInputVol(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetPresentInputVol. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_present_input_vol + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetPresentOutput(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetPresentOutput. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_present_output + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetPresentInputCurrent(byte group, byte address)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetPresentInputCurrent. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_presnet_input_cur + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void GetAvailableCap(byte group, byte address, short _outputVol)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : GetAvailableCap. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._get_available_cap + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ memset(data, 0x00, ARRAY_SIZE(data));
|
|
|
+ data[0] = _outputVol & 0xff;
|
|
|
+ data[1] = (_outputVol >> 8) & 0xff;
|
|
|
+
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void SetPresentOutput(byte group, byte address, short vol, short cur, unsigned short AvailableCur, byte derating)
|
|
|
+{
|
|
|
+ //printf("PSU_C_DLL : SetPresentOutput. group = %x, address = %x \n", group, address);
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._set_present_output + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ // 電壓
|
|
|
+ data[0] = vol & 0xff;
|
|
|
+ data[1] = (vol >> 8) & 0xff;
|
|
|
+ // 電流 (%) : 先算出總能夠輸出的電流當 100 %, 在與現在的希望輸出的電流比對,比出來的值為希望模塊輸出電流的比率
|
|
|
+ if (cur >= AvailableCur)
|
|
|
+ cur = AvailableCur;
|
|
|
+
|
|
|
+ short percent = ((float) cur / AvailableCur) * 10000;
|
|
|
+ data[2] = percent & 0xff;
|
|
|
+ data[3] = (percent >> 8) & 0xff;
|
|
|
+ data[4] = derating;
|
|
|
+
|
|
|
+ printf("vol = %d, tot_Amp = %d, need_cur = %d, percent = %d \n", vol, AvailableCur, cur, percent);
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|
|
|
+
|
|
|
+void EnableOutputPower(byte group, byte address, byte value)
|
|
|
+{
|
|
|
+ int cmd = PackageIdCmd(Psu_cmd._switch_output_pow + (group << 6) + address);
|
|
|
+ byte data[8];
|
|
|
+
|
|
|
+ //printf("cmd = %x \n", cmd);
|
|
|
+ data[0] = value;
|
|
|
+ SendCmdToPsu(cmd, data, sizeof(data));
|
|
|
+}
|