diff --git a/BOdisplay.c b/BOdisplay.c index 6d7edb17..8b94befd 100644 --- a/BOdisplay.c +++ b/BOdisplay.c @@ -384,7 +384,11 @@ void digestConfigRequest(uint8_t configAddress, uint8_t requestedCodeLowByte, ui } -void processBoMessage() { +void display_init() { + // noop just here to have a common interface +} + +void display_update() { uart_fill_rx_packet_buffer(ui8_rx_buffer, 17, &ui8_rx_buffer_counter); diff --git a/BOdisplay.h b/BOdisplay.h index 94bec93d..d999077a 100644 --- a/BOdisplay.h +++ b/BOdisplay.h @@ -124,6 +124,7 @@ typedef enum { ERROR_ADDRESS = ((uint8_t) 0x66) } BO_ADDRESS_CODES; -void processBoMessage(); +void display_update(); +void display_init(); #endif /* BODISPLAY_H */ \ No newline at end of file diff --git a/display.c b/display.c index e529d50b..02471e8e 100644 --- a/display.c +++ b/display.c @@ -17,7 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ + */ #include #include "stm8s.h" @@ -30,24 +30,21 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "brake.h" #include "ACAeeprom.h" #include "interrupts.h" -//#include "update_setpoint.h" // FIXME, not needed any more? #include "ACAcontrollerState.h" -display_view_type display_view; +#ifdef DISPLAY_TYPE_KT_LCD3 +display_view_type display_view; display_mode_type display_mode; //currently display mode - - float current_display; -uint8_t battery_percent_fromcapacity=11; //hier nur als Konstante um Batterie normal zu senden.... +uint8_t battery_percent_fromcapacity = 11; //hier nur als Konstante um Batterie normal zu senden.... -#ifdef DISPLAY_TYPE_KT_LCD3 uint8_t ui8_tx_buffer[12]; uint8_t ui8_j; uint8_t ui8_crc; -uint16_t ui16_wheel_period_ms =4500; -uint16_t ui16_battery_volts= 36; +uint16_t ui16_wheel_period_ms = 4500; +uint16_t ui16_battery_volts = 36; uint8_t ui8_battery_soc = 12; uint8_t ui16_error; uint8_t ui8_rx_buffer[13]; @@ -55,357 +52,174 @@ uint8_t ui8_rx_buffer_counter = 0; uint8_t ui8_byte_received; uint8_t ui8_moving_indication = 0; uint8_t ui8_UARTCounter = 0; -uint8_t ui8_msg_received=0; -volatile struc_lcd_configuration_variables lcd_configuration_variables; - - -#endif - - -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) -#include "display_kingmeter.h" -#endif - +volatile struc_lcd_configuration_variables lcd_configuration_variables; -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) // For King-Meter J-LCD, SW-LCD, KM5s-LCD, EBS-LCD2 -KINGMETER_t KM; // Context of the King-Meter object -#endif - - -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) -void kingmeter_update(void) -{ - /* Prepare Tx parameters */ - - if(battery_percent_fromcapacity > 10) - { - KM.Tx.Battery = KM_BATTERY_NORMAL; - } - else - { - KM.Tx.Battery = KM_BATTERY_LOW; - } - - if((ui16_time_ticks_between_speed_interrupt>>4) < KM_MAX_WHEELTIME && ui16_time_ticks_between_speed_interrupt!=0) - { - // Adapt wheeltime to match displayed speedo value according config.h setting - KM.Tx.Wheeltime_ms = ui16_time_ticks_between_speed_interrupt>>4; // is not exactly correct, factor should be 15.625, not 16 - - - } - else - { - KM.Tx.Wheeltime_ms = KM_MAX_WHEELTIME; - } - - KM.Tx.Error = KM_ERROR_NONE; - - if (((ui8_current_cal_a*ui16_BatteryCurrent)/10 -ui16_current_cal_b) != 0x99) - { - KM.Tx.Current_x10= (ui8_current_cal_a*ui16_BatteryCurrent)/10 -ui16_current_cal_b; //calculate Amps out of 10bit ADC value - } - - /* Receive Rx parameters/settings and send Tx parameters */ - KingMeter_Service(&KM); - - - /* Apply Rx parameters */ - - #ifdef SUPPORT_LIGHTS_SWITCH - if(KM.Rx.Headlight == KM_HEADLIGHT_OFF) - { - digitalWrite(lights_pin, 0); - } - else // KM_HEADLIGHT_ON, KM_HEADLIGHT_LOW, KM_HEADLIGHT_HIGH - { - digitalWrite(lights_pin, 1); - } - #endif - - if(KM.Rx.PushAssist == KM_PUSHASSIST_ON) - { - #if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) - //do anything - #else - //do something else - #endif - } - else - { - ui8_assistlevel_global=KM.Rx.AssistLevel+80; // always add max regen - } - - - /* Shutdown in case we received no message in the last 3s - - if((millis() - KM.LastRx) > 3000) - { - poti_stat = 0; - throttle_stat = 0; - - }*/ -} -#endif - - - -void display_init() -{ - -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) - KingMeter_Init(&KM); -#endif - - -} - -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) -void display_update() -{ - kingmeter_update(); +void display_init(){ + // noop just here to have a common interface } -#endif - -#ifdef DISPLAY_TYPE_KT_LCD3 -void display_update() -{ +void send_message() { - // prepare moving indication info - ui8_moving_indication = 0; - if (brake_is_set ()) { ui8_moving_indication |= (1 << 5); } - //if (ebike_app_cruise_control_is_set ()) { ui8_moving_indication |= (1 << 3); } - //if (throttle_is_set ()) { ui8_moving_indication |= (1 << 1); } - //if (pas_is_set ()) { ui8_moving_indication |= (1 << 4); } + // prepare moving indication info + ui8_moving_indication = 0; + if (brake_is_set()) { + ui8_moving_indication |= (1 << 5); + } + //if (ebike_app_cruise_control_is_set ()) { ui8_moving_indication |= (1 << 3); } + //if (throttle_is_set ()) { ui8_moving_indication |= (1 << 1); } + //if (pas_is_set ()) { ui8_moving_indication |= (1 << 4); } #ifdef SPEEDSENSOR_EXTERNAL - if(ui16_time_ticks_between_speed_interrupt>65000){ui16_wheel_period_ms=4500;} - else{ - ui16_wheel_period_ms = (uint16_t) ((float)ui16_time_ticks_between_speed_interrupt/((float)PWM_CYCLES_SECOND/1000.0)); //must be /1000 devided in /125/8 for better resolution - } + if (ui16_time_ticks_between_speed_interrupt > 65000) { + ui16_wheel_period_ms = 4500; + } else { + ui16_wheel_period_ms = (uint16_t) ((float) ui16_time_ticks_between_speed_interrupt / ((float) PWM_CYCLES_SECOND / 1000.0)); //must be /1000 devided in /125/8 for better resolution + } #endif #ifdef SPEEDSENSOR_INTERNAL - if(ui32_erps_filtered==0){ui16_wheel_period_ms=4500;} - else{ - ui16_wheel_period_ms=(uint16_t)(1000.0*(float)GEAR_RATIO/(float)ui32_erps_filtered); - } + if (ui32_erps_filtered == 0) { + ui16_wheel_period_ms = 4500; + } else { + ui16_wheel_period_ms = (uint16_t) (1000.0 * (float) GEAR_RATIO / (float) ui32_erps_filtered); + } #endif - // calc battery pack state of charge (SOC) - ui16_battery_volts = ((uint16_t) ui8_adc_read_battery_voltage()) * ((uint16_t) ADC_BATTERY_VOLTAGE_K); - if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_80)) { ui8_battery_soc = 16; } // 4 bars | full - else if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_60)) { ui8_battery_soc = 12; } // 3 bars - else if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_40)) { ui8_battery_soc = 8; } // 2 bars - else if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_20)) { ui8_battery_soc = 4; } // 1 bar - else { ui8_battery_soc = 3; } // empty - -ui8_tx_buffer [0] = 65; - // B1: battery level - ui8_tx_buffer [1] = ui8_battery_soc; - // B2: 24V controller - ui8_tx_buffer [2] = (uint8_t) COMMUNICATIONS_BATTERY_VOLTAGE; - // B3: speed, wheel rotation period, ms; period(ms)=B3*256+B4; - ui8_tx_buffer [3] = (ui16_wheel_period_ms >> 8) & 0xff; - ui8_tx_buffer [4] = ui16_wheel_period_ms & 0xff; - - //Send confirming signal for activating offroad mode - if (ui8_offroad_state==4){ //quitting signal for offroad mode enabled. Shows about 80 km/h for three seconds - - ui8_tx_buffer [3] = (100 >> 8) & 0xff; //100ms are about 80 km/h @ 28" 2200mm wheel circumference - ui8_tx_buffer [4] = 100 & 0xff; - } - - // B5: error info display - ui8_tx_buffer [5] = ui16_error; - // B6: CRC: xor B1,B2,B3,B4,B5,B7,B8,B9,B10,B11 - // 0 value so no effect on xor operation for now - ui8_tx_buffer [6] = 0; - // B7: moving mode indication, bit - // throttle: 2 - ui8_tx_buffer [7] = ui8_moving_indication; - // B8: 4x controller current - // Vbat = 30V: - // - B8 = 255, LCD shows 1912 watts - // - B8 = 250, LCD shows 1875 watts - // - B8 = 100, LCD shows 750 watts - // each unit of B8 = 0.25A - - - ui8_tx_buffer [8] = (uint8_t)(((ui16_BatteryCurrent-ui16_current_cal_b+1)<<2)/ui8_current_cal_a); - // B9: motor temperature - ui8_tx_buffer [9] = i8_motor_temperature-15; //according to documentation at endless sphere - // B10 and B11: 0 - ui8_tx_buffer [10] = 0; - ui8_tx_buffer [11] = 0; - - // calculate CRC xor - ui8_crc = 0; - for (ui8_j = 1; ui8_j <= 11; ui8_j++) - { - ui8_crc ^= ui8_tx_buffer[ui8_j]; - } - ui8_tx_buffer [6] = ui8_crc; - - // send the package over UART - for (ui8_j = 0; ui8_j <= 11; ui8_j++) - { - putchar (ui8_tx_buffer [ui8_j]); - } -} - -/********************************************************************************************/ - // Process received package from the LCD - // - -void digestLcdValues(void){ - - ui8_assistlevel_global=lcd_configuration_variables.ui8_assist_level+80; // always add max regen - - if (lcd_configuration_variables.ui8_max_speed != ui8_speedlimit_kph){ - ui8_speedlimit_kph = lcd_configuration_variables.ui8_max_speed; - eeprom_write(OFFSET_MAX_SPEED_DEFAULT, lcd_configuration_variables.ui8_max_speed); - } -} - - // see if we have a received package to be processed -void check_message() - { - //printf("Byte recieved \r\n"); - // validation of the package data - ui8_crc = 0; - for (ui8_j = 0; ui8_j <= 12; ui8_j++) - { - //putchar (ui8_j); - //putchar (ui8_rx_buffer[ui8_j]); - if (ui8_j == 7) continue; // don't xor B5 (B7 in our case) - ui8_crc ^= ui8_rx_buffer[ui8_j]; - } - - // see if CRC is ok - if (((ui8_crc ^ 10) == ui8_rx_buffer [7]) || // some versions of CRC LCD5 (??) - ((ui8_crc ^ 5) == ui8_rx_buffer [7]) || // CRC LCD3 (tested with KT36/48SVPR, from PSWpower) - ((ui8_crc ^ 9) == ui8_rx_buffer [7]) || // CRC LCD5 - ((ui8_crc ^ 3) == ui8_rx_buffer [7]) || // CRC LCD5 Added display 5 Romanta - ((ui8_crc ^ 2) == ui8_rx_buffer [7])) // CRC LCD3 - { //printf("message valid \r\n"); - - lcd_configuration_variables.ui8_assist_level = ui8_rx_buffer [3] & 7; - lcd_configuration_variables.ui8_max_speed = 10 + ((ui8_rx_buffer [4] & 248) >> 3) | (ui8_rx_buffer [6] & 32); - lcd_configuration_variables.ui8_wheel_size = ((ui8_rx_buffer [6] & 192) >> 6) | ((ui8_rx_buffer [4] & 7) << 2); - - lcd_configuration_variables.ui8_p1 = ui8_rx_buffer[5]; - lcd_configuration_variables.ui8_p2 = ui8_rx_buffer[6] & 0x07; - lcd_configuration_variables.ui8_p3 = ui8_rx_buffer[6] & 0x08; - lcd_configuration_variables.ui8_p4 = ui8_rx_buffer[6] & 0x10; - lcd_configuration_variables.ui8_p5 = ui8_rx_buffer[2]; - - lcd_configuration_variables.ui8_c1 = (ui8_rx_buffer[8] & 0x38) >>3; - lcd_configuration_variables.ui8_c2 = (ui8_rx_buffer[8] & 0x37); - lcd_configuration_variables.ui8_c4 = (ui8_rx_buffer[10] & 0xE0) >>5; - lcd_configuration_variables.ui8_c5 = (ui8_rx_buffer[9] & 0x0F); - lcd_configuration_variables.ui8_c12 = (ui8_rx_buffer[11] & 0x0F); - lcd_configuration_variables.ui8_c13 = (ui8_rx_buffer[12] & 0x1C) >>2; - lcd_configuration_variables.ui8_c14 = (ui8_rx_buffer[9] & 0x60) >>5; - - digestLcdValues(); - display_update(); - } - } -/**************************************************************************************************** - * UART2 receive interrupt handler - receive data from and to the display - * - ***************************************************************************************************/ -void UART2_IRQHandler(void) __interrupt(UART2_IRQHANDLER) - { - if(UART2_GetFlagStatus(UART2_FLAG_RXNE) == SET){ - ui8_rx_buffer[ui8_UARTCounter] = UART2_ReceiveData8(); - - ui8_UARTCounter++; - - if(ui8_rx_buffer[ui8_UARTCounter-1]==0x0E) // Check for reception of complete message - { - ui8_UARTCounter=2; - ui8_msg_received=1; - - } - if(ui8_UARTCounter>12) // if 0x0E is not received properly avoid buffer overflow - { - ui8_UARTCounter=0; - - } - + // calc battery pack state of charge (SOC) + ui16_battery_volts = ((uint16_t) ui8_adc_read_battery_voltage()) * ((uint16_t) ADC_BATTERY_VOLTAGE_K); + if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_80)) { + ui8_battery_soc = 16; + }// 4 bars | full + else if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_60)) { + ui8_battery_soc = 12; + }// 3 bars + else if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_40)) { + ui8_battery_soc = 8; + }// 2 bars + else if (ui16_battery_volts > ((uint16_t) BATTERY_PACK_VOLTS_20)) { + ui8_battery_soc = 4; + }// 1 bar + else { + ui8_battery_soc = 3; + } // empty + + ui8_tx_buffer [0] = 65; + // B1: battery level + ui8_tx_buffer [1] = ui8_battery_soc; + // B2: 24V controller + ui8_tx_buffer [2] = (uint8_t) COMMUNICATIONS_BATTERY_VOLTAGE; + // B3: speed, wheel rotation period, ms; period(ms)=B3*256+B4; + ui8_tx_buffer [3] = (ui16_wheel_period_ms >> 8) & 0xff; + ui8_tx_buffer [4] = ui16_wheel_period_ms & 0xff; + + //Send confirming signal for activating offroad mode + if (ui8_offroad_state == 4) { //quitting signal for offroad mode enabled. Shows about 80 km/h for three seconds + + ui8_tx_buffer [3] = (100 >> 8) & 0xff; //100ms are about 80 km/h @ 28" 2200mm wheel circumference + ui8_tx_buffer [4] = 100 & 0xff; } - else //catch errors - { - if(UART2_GetITStatus(UART2_IT_IDLE) == SET) - { - - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetITStatus(UART2_IT_LBDF) == SET) - { - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetITStatus(UART2_IT_OR) == SET) - { - - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetITStatus(UART2_IT_PE) == SET) - { + // B5: error info display + ui8_tx_buffer [5] = ui16_error; + // B6: CRC: xor B1,B2,B3,B4,B5,B7,B8,B9,B10,B11 + // 0 value so no effect on xor operation for now + ui8_tx_buffer [6] = 0; + // B7: moving mode indication, bit + // throttle: 2 + ui8_tx_buffer [7] = ui8_moving_indication; + // B8: 4x controller current + // Vbat = 30V: + // - B8 = 255, LCD shows 1912 watts + // - B8 = 250, LCD shows 1875 watts + // - B8 = 100, LCD shows 750 watts + // each unit of B8 = 0.25A + + + ui8_tx_buffer [8] = (uint8_t) (((ui16_BatteryCurrent - ui16_current_cal_b + 1) << 2) / ui8_current_cal_a); + // B9: motor temperature + ui8_tx_buffer [9] = i8_motor_temperature - 15; //according to documentation at endless sphere + // B10 and B11: 0 + ui8_tx_buffer [10] = 0; + ui8_tx_buffer [11] = 0; + + // calculate CRC xor + ui8_crc = 0; + for (ui8_j = 1; ui8_j <= 11; ui8_j++) { + ui8_crc ^= ui8_tx_buffer[ui8_j]; + } + ui8_tx_buffer [6] = ui8_crc; - UART2_ReceiveData8(); // -> clear! - } + // send the package over UART + for (ui8_j = 0; ui8_j <= 11; ui8_j++) { + uart_put_buffered(ui8_tx_buffer [ui8_j]); + } +} +/********************************************************************************************/ +// Process received package from the LCD +// - } //end else - } +void digestLcdValues(void) { -#endif //end of DISPLAY_TYPE_KT_LCD3 + ui8_assistlevel_global = lcd_configuration_variables.ui8_assist_level + 80; // always add max regen -#if !defined DISPLAY_TYPE_KT_LCD3 && !defined BLUOSEC && !(DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) + if (lcd_configuration_variables.ui8_max_speed != ui8_speedlimit_kph) { + ui8_speedlimit_kph = lcd_configuration_variables.ui8_max_speed; + eeprom_write(OFFSET_MAX_SPEED_DEFAULT, lcd_configuration_variables.ui8_max_speed); + } +} +// see if we have a received package to be processed -/**************************************************************************************************** - * UART2 receive interrupt handler - fallback to clear rx buffer - * for debug Mode - ***************************************************************************************************/ +void display_update() { -void UART2_IRQHandler(void) __interrupt(UART2_IRQHANDLER) - { + // fill local buffer from uart ringbuffer + uart_fill_rx_packet_buffer(ui8_rx_buffer, 13, &ui8_UARTCounter); + + // Check for reception of complete message + if ((ui8_UARTCounter > 12) || (ui8_rx_buffer[ui8_UARTCounter - 1] == 0x0E)) { + ui8_UARTCounter = 0; - if(UART2_GetFlagStatus(UART2_FLAG_RXNE) == SET){ - - UART2_ReceiveData8();// -> clear! + // validation of the package data + ui8_crc = 0; + for (ui8_j = 0; ui8_j <= 12; ui8_j++) { + + if (ui8_j == 5) continue; // don't xor B5 + ui8_crc ^= ui8_rx_buffer[ui8_j]; } - else //catch errors - { - if(UART2_GetITStatus(UART2_IT_IDLE) == SET) - { - - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetITStatus(UART2_IT_LBDF) == SET) - { - - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetITStatus(UART2_IT_OR) == SET) - { - - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetITStatus(UART2_IT_PE) == SET) - { - - UART2_ReceiveData8(); // -> clear! - } + // see if CRC is ok + if (((ui8_crc ^ 10) == ui8_rx_buffer [5]) || // some versions of CRC LCD5 (??) + ((ui8_crc ^ 5) == ui8_rx_buffer [5]) || // CRC LCD3 (tested with KT36/48SVPR, from PSWpower) + ((ui8_crc ^ 9) == ui8_rx_buffer [5]) || // CRC LCD5 + ((ui8_crc ^ 3) == ui8_rx_buffer [5]) || // CRC LCD5 Added display 5 Romanta + ((ui8_crc ^ 2) == ui8_rx_buffer [5])) // CRC LCD3 + { + + lcd_configuration_variables.ui8_assist_level = ui8_rx_buffer [1] & 7; + lcd_configuration_variables.ui8_max_speed = 10 + ((ui8_rx_buffer [2] & 248) >> 3) | (ui8_rx_buffer [4] & 32); + lcd_configuration_variables.ui8_wheel_size = ((ui8_rx_buffer [4] & 192) >> 6) | ((ui8_rx_buffer [2] & 7) << 2); + + lcd_configuration_variables.ui8_p1 = ui8_rx_buffer[3]; + lcd_configuration_variables.ui8_p2 = ui8_rx_buffer[4] & 0x07; + lcd_configuration_variables.ui8_p3 = ui8_rx_buffer[4] & 0x08; + lcd_configuration_variables.ui8_p4 = ui8_rx_buffer[4] & 0x10; + lcd_configuration_variables.ui8_p5 = ui8_rx_buffer[0]; + + lcd_configuration_variables.ui8_c1 = (ui8_rx_buffer[6] & 0x38) >> 3; + lcd_configuration_variables.ui8_c2 = (ui8_rx_buffer[6] & 0x37); + lcd_configuration_variables.ui8_c4 = (ui8_rx_buffer[8] & 0xE0) >> 5; + lcd_configuration_variables.ui8_c5 = (ui8_rx_buffer[7] & 0x0F); + lcd_configuration_variables.ui8_c12 = (ui8_rx_buffer[9] & 0x0F); + lcd_configuration_variables.ui8_c13 = (ui8_rx_buffer[10] & 0x1C) >> 2; + lcd_configuration_variables.ui8_c14 = (ui8_rx_buffer[7] & 0x60) >> 5; + + digestLcdValues(); + send_message(); + } + } +} - } //end else - } #endif diff --git a/display.h b/display.h index bca15606..c84ee36b 100644 --- a/display.h +++ b/display.h @@ -23,7 +23,6 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA void display_init(); void display_update(); -void check_message(); //void display_debug(HardwareSerial* localSerial); //void display_show_important_info(const char *str, int duration_secs); diff --git a/display_kingmeter.c b/display_kingmeter.c index b385e15e..7319d749 100644 --- a/display_kingmeter.c +++ b/display_kingmeter.c @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -*/ + */ // Includes @@ -29,9 +29,10 @@ along with this program. If not, see . #include "uart.h" #include "timers.h" #include "interrupts.h" +#include "ACAcontrollerState.h" -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) +#if defined (DISPLAY_TYPE) && defined (DISPLAY_TYPE_KINGMETER) // Definitions #define RXSTATE_STARTCODE 0 @@ -46,32 +47,30 @@ int spd_max1; uint8_t ui8_UARTCounter = 0; uint8_t ui8_rx[6]; -uint8_t ui8_msg_received=0; +uint8_t battery_percent_fromcapacity = 11; //hier nur als Konstante um Batterie normal zu senden.... -uint16_t k; //for debugging, number of calls of service -uint16_t KM_WHEELSIZE [8] = - { +uint16_t k; //for debugging, number of calls of service +uint16_t KM_WHEELSIZE [8] ={ KM_WHEELSIZE_16, KM_WHEELSIZE_18, KM_WHEELSIZE_20, KM_WHEELSIZE_22, - KM_WHEELSIZE_24, + KM_WHEELSIZE_24, KM_WHEELSIZE_26, KM_WHEELSIZE_700, KM_WHEELSIZE_28 - }; +}; uint8_t ui8_UART_flag = 0; // Hashtable used for handshaking in 901U protocol #if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) -const uint8_t KM_901U_HANDSHAKE[64] = -{ - 201, 107, 13, 229, 241, 198, 108, 230, 186, 67, 39, 92, 217, 140, 177, 36, - 22, 71, 174, 39, 161, 151, 7, 140, 107, 155, 189, 195, 209, 106, 63, 191, - 218, 47, 221, 46, 135, 145, 98, 82, 35, 42, 85, 99, 35, 43, 180, 12, - 3, 126, 94, 103, 198, 10, 182, 249, 253, 86, 105, 196, 217, 183, 195, 115 +const uint8_t KM_901U_HANDSHAKE[64] ={ + 201, 107, 13, 229, 241, 198, 108, 230, 186, 67, 39, 92, 217, 140, 177, 36, + 22, 71, 174, 39, 161, 151, 7, 140, 107, 155, 189, 195, 209, 106, 63, 191, + 218, 47, 221, 46, 135, 145, 98, 82, 35, 42, 85, 99, 35, 43, 180, 12, + 3, 126, 94, 103, 198, 10, 182, 249, 253, 86, 105, 196, 217, 183, 195, 115 }; #endif @@ -86,6 +85,7 @@ static void KM_901U_Service(KINGMETER_t* KM_ctx); #endif +KINGMETER_t KM; // Context of the King-Meter object /* Public functions (Prototypes declared by display_kingmeter.h) */ @@ -94,407 +94,401 @@ static void KM_901U_Service(KINGMETER_t* KM_ctx); * ****************************************************************************************************/ -void KingMeter_Init (KINGMETER_t* KM_ctx) - -{ - uint16_t i; - - -// KM_ctx->SerialPort = DisplaySerial; // Store serial port to use - - KM_ctx->RxState = RXSTATE_STARTCODE; -// KM_ctx->LastRx = millis(); +void KingMeter_Init(KINGMETER_t* KM_ctx){ + uint16_t i; - for(i=0; iRxBuff[i] = 0x00; - } - KM_ctx->RxCnt = 0; + // KM_ctx->SerialPort = DisplaySerial; // Store serial port to use - // Settings received from display: - KM_ctx->Settings.PAS_RUN_Direction = KM_PASDIR_FORWARD; - KM_ctx->Settings.PAS_SCN_Tolerance = (uint8_t) pas_tolerance; - KM_ctx->Settings.PAS_N_Ratio = 255; - KM_ctx->Settings.HND_HL_ThrParam = KM_HND_HL_NO; - KM_ctx->Settings.HND_HF_ThrParam = KM_HND_HF_NO; - KM_ctx->Settings.SYS_SSP_SlowStart = 1; - KM_ctx->Settings.SPS_SpdMagnets = (uint8_t) wheel_magnets; - KM_ctx->Settings.VOL_1_UnderVolt_x10 = (uint16_t) (vcutoff * 10); - KM_ctx->Settings.WheelSize_mm = (uint16_t) (wheel_circumference * 1000); - - // Parameters received from display in operation mode: - KM_ctx->Rx.AssistLevel = 1; - KM_ctx->Rx.Headlight = KM_HEADLIGHT_OFF; - KM_ctx->Rx.Battery = KM_BATTERY_NORMAL; - KM_ctx->Rx.PushAssist = KM_PUSHASSIST_OFF; - KM_ctx->Rx.PowerAssist = KM_POWERASSIST_ON; - KM_ctx->Rx.Throttle = KM_THROTTLE_ON; - KM_ctx->Rx.CruiseControl = KM_CRUISE_OFF; - KM_ctx->Rx.OverSpeed = KM_OVERSPEED_NO; - KM_ctx->Rx.SPEEDMAX_Limit_x10 = (uint16_t) (spd_max1 * 10); - KM_ctx->Rx.CUR_Limit_x10 = 150; - - // Parameters to be send to display in operation mode: - KM_ctx->Tx.Battery = KM_BATTERY_NORMAL; - KM_ctx->Tx.Wheeltime_ms = KM_MAX_WHEELTIME; - KM_ctx->Tx.Error = KM_ERROR_NONE; - KM_ctx->Tx.Current_x10 = 0; + KM_ctx->RxState = RXSTATE_STARTCODE; + // KM_ctx->LastRx = millis(); + for (i = 0; i < KM_MAX_RXBUFF; i++) { + KM_ctx->RxBuff[i] = 0x00; + } - //DisplaySerial->begin(9600); wird bereits in der main.c gestartet + KM_ctx->RxCnt = 0; + + // Settings received from display: + KM_ctx->Settings.PAS_RUN_Direction = KM_PASDIR_FORWARD; + KM_ctx->Settings.PAS_SCN_Tolerance = (uint8_t) pas_tolerance; + KM_ctx->Settings.PAS_N_Ratio = 255; + KM_ctx->Settings.HND_HL_ThrParam = KM_HND_HL_NO; + KM_ctx->Settings.HND_HF_ThrParam = KM_HND_HF_NO; + KM_ctx->Settings.SYS_SSP_SlowStart = 1; + KM_ctx->Settings.SPS_SpdMagnets = (uint8_t) wheel_magnets; + KM_ctx->Settings.VOL_1_UnderVolt_x10 = (uint16_t) (vcutoff * 10); + KM_ctx->Settings.WheelSize_mm = (uint16_t) (wheel_circumference * 1000); + + // Parameters received from display in operation mode: + KM_ctx->Rx.AssistLevel = 1; + KM_ctx->Rx.Headlight = KM_HEADLIGHT_OFF; + KM_ctx->Rx.Battery = KM_BATTERY_NORMAL; + KM_ctx->Rx.PushAssist = KM_PUSHASSIST_OFF; + KM_ctx->Rx.PowerAssist = KM_POWERASSIST_ON; + KM_ctx->Rx.Throttle = KM_THROTTLE_ON; + KM_ctx->Rx.CruiseControl = KM_CRUISE_OFF; + KM_ctx->Rx.OverSpeed = KM_OVERSPEED_NO; + KM_ctx->Rx.SPEEDMAX_Limit_x10 = (uint16_t) (spd_max1 * 10); + KM_ctx->Rx.CUR_Limit_x10 = 150; + + // Parameters to be send to display in operation mode: + KM_ctx->Tx.Battery = KM_BATTERY_NORMAL; + KM_ctx->Tx.Wheeltime_ms = KM_MAX_WHEELTIME; + KM_ctx->Tx.Error = KM_ERROR_NONE; + KM_ctx->Tx.Current_x10 = 0; + + + //DisplaySerial->begin(9600); wird bereits in der main.c gestartet } +/* Local functions */ +#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_618U) /**************************************************************************************************** - * UART2 receive interrupt handler - receive data from and to the display + * KM_618U_Service() - Communication protocol of 618U firmware (J-LCD compatible) * ***************************************************************************************************/ -void UART2_IRQHandler(void) __interrupt(UART2_IRQHANDLER) - { - if(UART2_GetFlagStatus(UART2_FLAG_RXNE) == SET){ +static void KM_618U_Service(KINGMETER_t* KM_ctx) { + uint16_t i; + uint16_t j; - ui8_rx[ui8_UARTCounter] = UART2_ReceiveData8(); - ui8_UARTCounter++; + uint8_t TxBuff[KM_MAX_TXBUFF]; - if(ui8_rx[ui8_UARTCounter-1]==0x0D) // Check for reception of complete message - { - ui8_UARTCounter=0; - ui8_msg_received=1; + // Search for Start Code + if (KM_ctx->RxState == RXSTATE_STARTCODE) { - } - if(ui8_UARTCounter>6) // if 0x0D is not received properly avoid buffer overflow - { - ui8_UARTCounter=0; - - } + if (ui8_rx[0] == 0x46 && ui8_rx[5] == 0x0D) //Check, if Message is valid + { + for (j = 0; j < 6; j++) { + KM_ctx->RxBuff[j] = ui8_rx[j]; + + } + KM_ctx->RxState = RXSTATE_SENDTXMSG; + } } - else //catch errors - { - if(UART2_GetFlagStatus(UART2_FLAG_OR_LHE) == SET) - { - UART2_ReceiveData8(); // -> clear! - } - if(UART2_GetFlagStatus(UART2_FLAG_FE) == SET) - { - UART2_ReceiveData8(); // -> clear! - } - } //end else - } -/**************************************************************************************************** - * KingMeter_Service() - Communicates data from and to the display - * - ***************************************************************************************************/ -void KingMeter_Service(KINGMETER_t* KM_ctx) -{ - #if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_618U) - KM_618U_Service(KM_ctx); - #endif - - #if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) - KM_901U_Service(KM_ctx); - #endif -} + if (KM_ctx->RxState == RXSTATE_SENDTXMSG) { + KM_ctx->RxState = RXSTATE_DONE; + // Prepare Tx message + TxBuff[0] = 0X46; // StartCode + if (KM_ctx->Tx.Battery == KM_BATTERY_LOW) { + TxBuff[1] = 0x00; // If none of Bit[0..2] is set, display blinks + } else { + TxBuff[1] = 0x03; //Original firmware of Lishui sends "3" at this Byte + } -/* Local functions */ + TxBuff[2] = (uint8_t) ((KM_ctx->Tx.Current_x10 * 3) / 10); // Current unit: 1/3A, gives still error at first loop run? + //TxBuff[2] = 0x00; + TxBuff[3] = (uint8_t) (KM_ctx->Tx.Wheeltime_ms >> 8); // richtige Funktion der Bitmanipulation noch nicht best�tigt + TxBuff[4] = (uint8_t) (KM_ctx->Tx.Wheeltime_ms & 0xFF); // richtige Funktion der Bitmanipulation noch nicht best�tigt + TxBuff[5] = 0xA7; // Reply with WheelSize 26" / Maxspeed 25km/h (no influence on display) + TxBuff[6] = KM_ctx->Tx.Error; -#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_618U) -/**************************************************************************************************** - * KM_618U_Service() - Communication protocol of 618U firmware (J-LCD compatible) - * - ***************************************************************************************************/ -static void KM_618U_Service(KINGMETER_t* KM_ctx) -{ - uint16_t i; - uint16_t j; - uint8_t TxBuff[KM_MAX_TXBUFF]; + // Send prepared message + TxBuff[7] = 0x00; + uart_put_buffered(TxBuff[0]); // Send StartCode + for (i = 1; i < 7; i++) { + uart_put_buffered(TxBuff[i]); // Send TxBuff[1..6] + TxBuff[7] ^= TxBuff[i]; // Calculate XOR CheckSum + } + uart_put_buffered(TxBuff[7]); // Send XOR CheckSum - // Search for Start Code - if(KM_ctx->RxState == RXSTATE_STARTCODE) - { + } - if (ui8_rx[0]==0x46 && ui8_rx[5]==0x0D) //Check, if Message is valid - { - for(j =0; j<6; j++) - { - KM_ctx->RxBuff[j] = ui8_rx[j]; - //putchar(ui8_rx[j]); - } - KM_ctx->RxState = RXSTATE_SENDTXMSG; - } + // Message received completely + if (KM_ctx->RxState == RXSTATE_DONE) { + KM_ctx->RxState = RXSTATE_STARTCODE; + // Decode PAS level - Display sets PAS-level to 0 when overspeed detected! + KM_ctx->Rx.AssistLevel = KM_ctx->RxBuff[1] & 0x07; //Mapping entfernt, da nur der Faktor genutzt werden soll. - } + // Decode Headlight status + KM_ctx->Rx.Headlight = (KM_ctx->RxBuff[1] & 0x80) >> 7; // KM_HEADLIGHT_OFF / KM_HEADLIGHT_ON + // KM_ctx->Rx.Battery; + // Decode PushAssist status + KM_ctx->Rx.PushAssist = (KM_ctx->RxBuff[1] & 0x10) >> 4; // KM_PUSHASSIST_OFF / KM_PUSHASSIST_ON + // KM_ctx->Rx.PowerAssist; + // KM_ctx->Rx.Throttle; + // KM_ctx->Rx.CruiseControl; + // KM_ctx->Rx.OverSpeed; + // Decode Speedlimit + KM_ctx->Rx.SPEEDMAX_Limit_x10 = (((KM_ctx->RxBuff[2] & 0xF8) >> 3) + 10) * 10; - if(KM_ctx->RxState == RXSTATE_SENDTXMSG) - { - KM_ctx->RxState = RXSTATE_DONE; + // Decode Wheelsize by hashtable + KM_ctx->Settings.WheelSize_mm = KM_WHEELSIZE[KM_ctx->RxBuff[2] & 0x07]; + // KM_ctx->Rx.CUR_Limit_x10; - // Prepare Tx message - TxBuff[0] = 0X46; // StartCode + } - if(KM_ctx->Tx.Battery == KM_BATTERY_LOW) - { - TxBuff[1] = 0x00; // If none of Bit[0..2] is set, display blinks - } - else - { - TxBuff[1] = 0x03; //Original firmware of Lishui sends "3" at this Byte - } +} +#endif - TxBuff[2] = (uint8_t) ((KM_ctx->Tx.Current_x10 * 3) / 10); // Current unit: 1/3A, gives still error at first loop run? - //TxBuff[2] = 0x00; - TxBuff[3] = (uint8_t) (KM_ctx->Tx.Wheeltime_ms>>8); // richtige Funktion der Bitmanipulation noch nicht best�tigt - TxBuff[4] = (uint8_t) (KM_ctx->Tx.Wheeltime_ms & 0xFF); // richtige Funktion der Bitmanipulation noch nicht best�tigt - TxBuff[5] = 0xA7; // Reply with WheelSize 26" / Maxspeed 25km/h (no influence on display) - TxBuff[6] = KM_ctx->Tx.Error; - - // Send prepared message - TxBuff[7] = 0x00; +#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) - putchar(TxBuff[0]); // Send StartCode +/**************************************************************************************************** + * KM_901U_Service() - Communication protocol of 901U firmware + * + ***************************************************************************************************/ +static void KM_901U_Service(KINGMETER_t* KM_ctx) { + uint8_t i; + uint16_t CheckSum; + uint8_t TxBuff[KM_MAX_TXBUFF]; + uint8_t TxCnt; + + + // Search for Start Code + if (KM_ctx->RxState == RXSTATE_STARTCODE) { + if (KM_ctx->SerialPort->available()) { + KM_ctx->LastRx = millis(); + + if (KM_ctx->SerialPort->read() == 0x3A) { + KM_ctx->RxBuff[0] = 0x3A; + KM_ctx->RxCnt = 1; + KM_ctx->RxState = RXSTATE_MSGBODY; + } else { + return; // No need to continue + } + } + } + + // Receive Message body + if (KM_ctx->RxState == RXSTATE_MSGBODY) { + while (KM_ctx->SerialPort->available()) { + KM_ctx->RxBuff[KM_ctx->RxCnt] = KM_ctx->SerialPort->read(); + KM_ctx->RxCnt++; + + if (KM_ctx->RxCnt == 5) // Range check of Data size + { + if (KM_ctx->RxBuff[4] > (KM_MAX_RXBUFF - 5 - 4)) { + KM_ctx->RxState = RXSTATE_STARTCODE; // Invalid Data size, cancel reception + break; + } + } + + + if (KM_ctx->RxCnt == (5 + KM_ctx->RxBuff[4] + 4)) // Check for reception of complete message + { + // Verify CheckSum + CheckSum = 0x0000; + for (i = 1; i < (5 + KM_ctx->RxBuff[4]); i++) { + CheckSum = CheckSum + KM_ctx->RxBuff[i]; // Calculate CheckSum + } + + if ((lowByte(CheckSum) == KM_ctx->RxBuff[i]) && (highByte(CheckSum) == KM_ctx->RxBuff[i + 1])) { + KM_ctx->RxState = RXSTATE_DONE; + } else { + KM_ctx->RxState = RXSTATE_STARTCODE; // Invalid CheckSum, ignore message + } + + break; + } + } + } - for(i=1; i<7; i++) - { - putchar(TxBuff[i]); // Send TxBuff[1..6] - TxBuff[7] ^= TxBuff[i]; // Calculate XOR CheckSum - } - putchar(TxBuff[7]); // Send XOR CheckSum + // Message received completely + if (KM_ctx->RxState == RXSTATE_DONE) { + KM_ctx->RxState = RXSTATE_STARTCODE; + + switch (KM_ctx->RxBuff[3]) { + case 0x52: // Operation mode + + // Decode Rx message + KM_ctx->Rx.AssistLevel = KM_ctx->RxBuff[5]; // 0..255 + KM_ctx->Rx.Headlight = (KM_ctx->RxBuff[6] & 0xC0) >> 6; // KM_HEADLIGHT_OFF / KM_HEADLIGHT_ON / KM_HEADLIGHT_LOW / KM_HEADLIGHT_HIGH + KM_ctx->Rx.Battery = (KM_ctx->RxBuff[6] & 0x20) >> 5; // KM_BATTERY_NORMAL / KM_BATTERY_LOW + KM_ctx->Rx.PushAssist = (KM_ctx->RxBuff[6] & 0x10) >> 4; // KM_PUSHASSIST_OFF / KM_PUSHASSIST_ON + KM_ctx->Rx.PowerAssist = (KM_ctx->RxBuff[6] & 0x08) >> 3; // KM_POWERASSIST_OFF / KM_POWERASSIST_ON + KM_ctx->Rx.Throttle = (KM_ctx->RxBuff[6] & 0x04) >> 2; // KM_THROTTLE_OFF / KM_THROTTLE_ON + KM_ctx->Rx.CruiseControl = (KM_ctx->RxBuff[6] & 0x02) >> 1; // KM_CRUISE_OFF / KM_CRUISE_ON + KM_ctx->Rx.OverSpeed = (KM_ctx->RxBuff[6] & 0x01); // KM_OVERSPEED_NO / KM_OVERSPEED_YES + KM_ctx->Rx.SPEEDMAX_Limit_x10 = (((uint16_t) KM_ctx->RxBuff[8]) << 8) | KM_ctx->RxBuff[7]; + KM_ctx->Rx.CUR_Limit_x10 = (((uint16_t) KM_ctx->RxBuff[10]) << 8) | KM_ctx->RxBuff[9]; + + + // Prepare Tx message + TxBuff[0] = 0X3A; // StartCode + TxBuff[1] = 0x1A; // SrcAdd: Controller + TxBuff[2] = 0X28; // DestAdd: LCD + TxBuff[3] = 0x52; // CmdCode + TxBuff[4] = 0x06; // DataSize + + if (KM_ctx->Tx.Battery == KM_BATTERY_LOW) { + TxBuff[5] = 0x40; // State data (only UnderVoltage bit has influence on display) + } else { + TxBuff[5] = 0x00; // State data (only UnderVoltage bit has influence on display) + } + + TxBuff[6] = lowByte(KM_ctx->Tx.Current_x10); // Current low + TxBuff[7] = highByte(KM_ctx->Tx.Current_x10); // Current high + TxBuff[8] = lowByte(KM_ctx->Tx.Wheeltime_ms); // WheelSpeed low + TxBuff[9] = highByte(KM_ctx->Tx.Wheeltime_ms); // WheelSpeed high + TxBuff[10] = KM_ctx->Tx.Error; // Error + + TxCnt = 11; + break; + + + case 0x53: // Settings mode + + // Decode Rx message + KM_ctx->Settings.PAS_RUN_Direction = (KM_ctx->RxBuff[5] & 0x80) >> 7; // KM_PASDIR_FORWARD / KM_PASDIR_BACKWARD + KM_ctx->Settings.PAS_SCN_Tolerance = KM_ctx->RxBuff[6]; // 2..9 + KM_ctx->Settings.PAS_N_Ratio = KM_ctx->RxBuff[7]; // 0..255 + KM_ctx->Settings.HND_HL_ThrParam = (KM_ctx->RxBuff[8] & 0x80) >> 7; // KM_HND_HL_NO / KM_HND_HL_YES + KM_ctx->Settings.HND_HF_ThrParam = (KM_ctx->RxBuff[8] & 0x40) >> 6; // KM_HND_HF_NO / KM_HND_HF_YES + KM_ctx->Settings.SYS_SSP_SlowStart = KM_ctx->RxBuff[9]; // 1..9 + KM_ctx->Settings.SPS_SpdMagnets = KM_ctx->RxBuff[10]; // 1..4 + KM_ctx->Settings.VOL_1_UnderVolt_x10 = (((uint16_t) KM_ctx->RxBuff[12]) << 8) | KM_ctx->RxBuff[11]; + KM_ctx->Settings.WheelSize_mm = (((uint16_t) KM_ctx->RxBuff[14]) << 8) | KM_ctx->RxBuff[13]; + + + // Prepare Tx message with handshake code + TxBuff[0] = 0X3A; // StartCode + TxBuff[1] = 0x1A; // SrcAdd: Controller + TxBuff[2] = 0X28; // DestAdd: LCD + TxBuff[3] = 0x53; // CmdCode + TxBuff[4] = 0x01; // DataSize + TxBuff[5] = KM_901U_HANDSHAKE[KM_ctx->RxBuff[15]]; // Handshake answer + TxCnt = 6; + break; + + default: + TxCnt = 0; + } + + + // Send prepared message + if (TxCnt != 0) { + CheckSum = 0x0000; + + KM_ctx->SerialPort->write(TxBuff[0]); // Send StartCode + + for (i = 1; i < TxCnt; i++) { + KM_ctx->SerialPort->write(TxBuff[i]); // Send TxBuff[1..x] + CheckSum = CheckSum + TxBuff[i]; // Calculate CheckSum + } + + KM_ctx->SerialPort->write(lowByte(CheckSum)); // Send CheckSum low + KM_ctx->SerialPort->write(highByte(CheckSum)); // Send CheckSum high + + KM_ctx->SerialPort->write(0x0D); // Send CR + KM_ctx->SerialPort->write(0x0A); // Send LF + } + } +} +#endif - } +/**************************************************************************************************** + * KingMeter_Service() - Communicates data from and to the display + * + ***************************************************************************************************/ +void KingMeter_Service(KINGMETER_t* KM_ctx) { +#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_618U) + KM_618U_Service(KM_ctx); +#endif +#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) + KM_901U_Service(KM_ctx); +#endif +} +void kingmeter_update(void) { + /* Prepare Tx parameters */ - // Message received completely - if(KM_ctx->RxState == RXSTATE_DONE) - { - KM_ctx->RxState = RXSTATE_STARTCODE; + if (battery_percent_fromcapacity > 10) { + KM.Tx.Battery = KM_BATTERY_NORMAL; + } else { + KM.Tx.Battery = KM_BATTERY_LOW; + } - // Decode PAS level - Display sets PAS-level to 0 when overspeed detected! - KM_ctx->Rx.AssistLevel = KM_ctx->RxBuff[1] & 0x07; //Mapping entfernt, da nur der Faktor genutzt werden soll. + if ((ui16_time_ticks_between_speed_interrupt >> 4) < KM_MAX_WHEELTIME && ui16_time_ticks_between_speed_interrupt != 0) { + // Adapt wheeltime to match displayed speedo value according config.h setting + KM.Tx.Wheeltime_ms = ui16_time_ticks_between_speed_interrupt >> 4; // is not exactly correct, factor should be 15.625, not 16 - // Decode Headlight status - KM_ctx->Rx.Headlight = (KM_ctx->RxBuff[1] & 0x80) >> 7; // KM_HEADLIGHT_OFF / KM_HEADLIGHT_ON -// KM_ctx->Rx.Battery; + } else { + KM.Tx.Wheeltime_ms = KM_MAX_WHEELTIME; + } - // Decode PushAssist status - KM_ctx->Rx.PushAssist = (KM_ctx->RxBuff[1] & 0x10) >> 4; // KM_PUSHASSIST_OFF / KM_PUSHASSIST_ON + KM.Tx.Error = KM_ERROR_NONE; -// KM_ctx->Rx.PowerAssist; -// KM_ctx->Rx.Throttle; -// KM_ctx->Rx.CruiseControl; -// KM_ctx->Rx.OverSpeed; + if (((ui8_current_cal_a * ui16_BatteryCurrent) / 10 - ui16_current_cal_b) != 0x99) { + KM.Tx.Current_x10 = (ui8_current_cal_a * ui16_BatteryCurrent) / 10 - ui16_current_cal_b; //calculate Amps out of 10bit ADC value + } - // Decode Speedlimit - KM_ctx->Rx.SPEEDMAX_Limit_x10 = (((KM_ctx->RxBuff[2] & 0xF8) >> 3) + 10) * 10; + /* Receive Rx parameters/settings and send Tx parameters */ + KingMeter_Service(&KM); - // Decode Wheelsize by hashtable - KM_ctx->Settings.WheelSize_mm = KM_WHEELSIZE[KM_ctx->RxBuff[2] & 0x07]; -// KM_ctx->Rx.CUR_Limit_x10; + /* Apply Rx parameters */ - } +#ifdef SUPPORT_LIGHTS_SWITCH + if (KM.Rx.Headlight == KM_HEADLIGHT_OFF) { + digitalWrite(lights_pin, 0); + } else // KM_HEADLIGHT_ON, KM_HEADLIGHT_LOW, KM_HEADLIGHT_HIGH + { + digitalWrite(lights_pin, 1); + } +#endif -} + if (KM.Rx.PushAssist == KM_PUSHASSIST_ON) { +#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) + //do anything +#else + //do something else #endif + } else { + ui8_assistlevel_global = KM.Rx.AssistLevel + 80; // always add max regen + } + /* Shutdown in case we received no message in the last 3s + if((millis() - KM.LastRx) > 3000) + { + poti_stat = 0; + throttle_stat = 0; -#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_901U) -/**************************************************************************************************** - * KM_901U_Service() - Communication protocol of 901U firmware - * - ***************************************************************************************************/ -static void KM_901U_Service(KINGMETER_t* KM_ctx) -{ - uint8_t i; - uint16_t CheckSum; - uint8_t TxBuff[KM_MAX_TXBUFF]; - uint8_t TxCnt; - - - // Search for Start Code - if(KM_ctx->RxState == RXSTATE_STARTCODE) - { - if(KM_ctx->SerialPort->available()) - { - KM_ctx->LastRx = millis(); - - if(KM_ctx->SerialPort->read() == 0x3A) - { - KM_ctx->RxBuff[0] = 0x3A; - KM_ctx->RxCnt = 1; - KM_ctx->RxState = RXSTATE_MSGBODY; - } - else - { - return; // No need to continue - } - } - } - - // Receive Message body - if(KM_ctx->RxState == RXSTATE_MSGBODY) - { - while(KM_ctx->SerialPort->available()) - { - KM_ctx->RxBuff[KM_ctx->RxCnt] = KM_ctx->SerialPort->read(); - KM_ctx->RxCnt++; - - if(KM_ctx->RxCnt == 5) // Range check of Data size - { - if(KM_ctx->RxBuff[4] > (KM_MAX_RXBUFF-5-4)) - { - KM_ctx->RxState = RXSTATE_STARTCODE; // Invalid Data size, cancel reception - break; - } - } - - - if(KM_ctx->RxCnt == (5 + KM_ctx->RxBuff[4] + 4)) // Check for reception of complete message - { - // Verify CheckSum - CheckSum = 0x0000; - for(i=1; i<(5+KM_ctx->RxBuff[4]); i++) - { - CheckSum = CheckSum + KM_ctx->RxBuff[i]; // Calculate CheckSum - } - - if((lowByte(CheckSum) == KM_ctx->RxBuff[i]) && (highByte(CheckSum) == KM_ctx->RxBuff[i+1])) - { - KM_ctx->RxState = RXSTATE_DONE; - } - else - { - KM_ctx->RxState = RXSTATE_STARTCODE; // Invalid CheckSum, ignore message - } - - break; - } - } - } - - - // Message received completely - if(KM_ctx->RxState == RXSTATE_DONE) - { - KM_ctx->RxState = RXSTATE_STARTCODE; - - switch(KM_ctx->RxBuff[3]) - { - case 0x52: // Operation mode - - // Decode Rx message - KM_ctx->Rx.AssistLevel = KM_ctx->RxBuff[5]; // 0..255 - KM_ctx->Rx.Headlight = (KM_ctx->RxBuff[6] & 0xC0) >> 6; // KM_HEADLIGHT_OFF / KM_HEADLIGHT_ON / KM_HEADLIGHT_LOW / KM_HEADLIGHT_HIGH - KM_ctx->Rx.Battery = (KM_ctx->RxBuff[6] & 0x20) >> 5; // KM_BATTERY_NORMAL / KM_BATTERY_LOW - KM_ctx->Rx.PushAssist = (KM_ctx->RxBuff[6] & 0x10) >> 4; // KM_PUSHASSIST_OFF / KM_PUSHASSIST_ON - KM_ctx->Rx.PowerAssist = (KM_ctx->RxBuff[6] & 0x08) >> 3; // KM_POWERASSIST_OFF / KM_POWERASSIST_ON - KM_ctx->Rx.Throttle = (KM_ctx->RxBuff[6] & 0x04) >> 2; // KM_THROTTLE_OFF / KM_THROTTLE_ON - KM_ctx->Rx.CruiseControl = (KM_ctx->RxBuff[6] & 0x02) >> 1; // KM_CRUISE_OFF / KM_CRUISE_ON - KM_ctx->Rx.OverSpeed = (KM_ctx->RxBuff[6] & 0x01); // KM_OVERSPEED_NO / KM_OVERSPEED_YES - KM_ctx->Rx.SPEEDMAX_Limit_x10 = (((uint16_t) KM_ctx->RxBuff[8])<<8) | KM_ctx->RxBuff[7]; - KM_ctx->Rx.CUR_Limit_x10 = (((uint16_t) KM_ctx->RxBuff[10])<<8) | KM_ctx->RxBuff[9]; - - - // Prepare Tx message - TxBuff[0] = 0X3A; // StartCode - TxBuff[1] = 0x1A; // SrcAdd: Controller - TxBuff[2] = 0X28; // DestAdd: LCD - TxBuff[3] = 0x52; // CmdCode - TxBuff[4] = 0x06; // DataSize - - if(KM_ctx->Tx.Battery == KM_BATTERY_LOW) - { - TxBuff[5] = 0x40; // State data (only UnderVoltage bit has influence on display) - } - else - { - TxBuff[5] = 0x00; // State data (only UnderVoltage bit has influence on display) - } - - TxBuff[6] = lowByte (KM_ctx->Tx.Current_x10); // Current low - TxBuff[7] = highByte(KM_ctx->Tx.Current_x10); // Current high - TxBuff[8] = lowByte (KM_ctx->Tx.Wheeltime_ms); // WheelSpeed low - TxBuff[9] = highByte(KM_ctx->Tx.Wheeltime_ms); // WheelSpeed high - TxBuff[10] = KM_ctx->Tx.Error; // Error - - TxCnt = 11; - break; - - - case 0x53: // Settings mode - - // Decode Rx message - KM_ctx->Settings.PAS_RUN_Direction = (KM_ctx->RxBuff[5] & 0x80) >> 7; // KM_PASDIR_FORWARD / KM_PASDIR_BACKWARD - KM_ctx->Settings.PAS_SCN_Tolerance = KM_ctx->RxBuff[6]; // 2..9 - KM_ctx->Settings.PAS_N_Ratio = KM_ctx->RxBuff[7]; // 0..255 - KM_ctx->Settings.HND_HL_ThrParam = (KM_ctx->RxBuff[8] & 0x80) >> 7; // KM_HND_HL_NO / KM_HND_HL_YES - KM_ctx->Settings.HND_HF_ThrParam = (KM_ctx->RxBuff[8] & 0x40) >> 6; // KM_HND_HF_NO / KM_HND_HF_YES - KM_ctx->Settings.SYS_SSP_SlowStart = KM_ctx->RxBuff[9]; // 1..9 - KM_ctx->Settings.SPS_SpdMagnets = KM_ctx->RxBuff[10]; // 1..4 - KM_ctx->Settings.VOL_1_UnderVolt_x10 = (((uint16_t) KM_ctx->RxBuff[12])<<8) | KM_ctx->RxBuff[11]; - KM_ctx->Settings.WheelSize_mm = (((uint16_t) KM_ctx->RxBuff[14])<<8) | KM_ctx->RxBuff[13]; - - - // Prepare Tx message with handshake code - TxBuff[0] = 0X3A; // StartCode - TxBuff[1] = 0x1A; // SrcAdd: Controller - TxBuff[2] = 0X28; // DestAdd: LCD - TxBuff[3] = 0x53; // CmdCode - TxBuff[4] = 0x01; // DataSize - TxBuff[5] = KM_901U_HANDSHAKE[KM_ctx->RxBuff[15]]; // Handshake answer - TxCnt = 6; - break; - - default: - TxCnt = 0; - } - - - // Send prepared message - if(TxCnt != 0) - { - CheckSum = 0x0000; - - KM_ctx->SerialPort->write(TxBuff[0]); // Send StartCode - - for(i=1; iSerialPort->write(TxBuff[i]); // Send TxBuff[1..x] - CheckSum = CheckSum + TxBuff[i]; // Calculate CheckSum - } - - KM_ctx->SerialPort->write(lowByte(CheckSum)); // Send CheckSum low - KM_ctx->SerialPort->write(highByte(CheckSum)); // Send CheckSum high - - KM_ctx->SerialPort->write(0x0D); // Send CR - KM_ctx->SerialPort->write(0x0A); // Send LF - } - } + }*/ +} + +void display_init() { + KingMeter_Init(&KM); } + +void display_update() { + +#if (DISPLAY_TYPE == DISPLAY_TYPE_KINGMETER_618U) + + // fill local buffer from uart ringbuffer + uart_fill_rx_packet_buffer(ui8_rx, 6, &ui8_UARTCounter); + + // Check for reception of complete message + if ((ui8_UARTCounter > 5) || (ui8_rx[ui8_UARTCounter - 1] == 0x0D)) + ui8_UARTCounter = 0; #endif + + kingmeter_update(); +} #endif // (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) diff --git a/display_kingmeter.h b/display_kingmeter.h index 5c526efa..259cc179 100644 --- a/display_kingmeter.h +++ b/display_kingmeter.h @@ -26,7 +26,7 @@ along with this program. If not, see . // Includes #include "config.h" -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) +#if defined (DISPLAY_TYPE) && defined (DISPLAY_TYPE_KINGMETER) // Definitions @@ -186,18 +186,10 @@ typedef struct }KINGMETER_t; -void KingMeter_Init (KINGMETER_t* KM_ctx); +void display_init(); +void display_update(); -void KingMeter_Service(KINGMETER_t* KM_ctx); - - - -// Public function prototypes - - - - -#endif // KINGMETER_H #endif // (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) +#endif // KINGMETER_H \ No newline at end of file diff --git a/main.c b/main.c index 5166c4ca..8621fa62 100644 --- a/main.c +++ b/main.c @@ -143,26 +143,8 @@ int main(void) { updateSpeeds(); updatePasStatus(); -#if (DISPLAY_TYPE & DISPLAY_TYPE_KINGMETER) - // Update display after message received occurrence - if (ui8_msg_received) { - ui8_msg_received = 0; - //printf("%d\n", ui16_time_ticks_between_speed_interrupt); - display_update(); //Display aktualisieren aus Code vom Forumscontroller - } -#endif - -#ifdef DISPLAY_TYPE_KT_LCD3 - // Update display after message received occurrence - if (ui8_msg_received) { - ui8_msg_received = 0; - //printf("%d\n", ui16_time_ticks_between_speed_interrupt); - check_message(); //Display aktualisieren aus Code vom Forumscontroller - } -#endif - -#ifdef BLUOSEC - processBoMessage(); +#if (defined (DISPLAY_TYPE) && defined (DISPLAY_TYPE_KINGMETER)) || defined DISPLAY_TYPE_KT_LCD3 || defined BLUOSEC + display_update(); #endif // scheduled update of setpoint and duty cycle (slow loop, 50 Hz) diff --git a/main.h b/main.h index 05695b2c..59287ee7 100644 --- a/main.h +++ b/main.h @@ -79,7 +79,6 @@ extern uint16_t ui16_log1; extern uint16_t ui16_log2; extern uint8_t ui8_log; extern uint8_t ui8_slowloop_flag; //Flag for slow loop timing -extern uint8_t ui8_msg_received; uint8_t update_advance_angle(); diff --git a/motor.c b/motor.c index bc38f433..23d0c8fb 100755 --- a/motor.c +++ b/motor.c @@ -15,7 +15,6 @@ #include "gpio.h" #include "pwm.h" #include "config.h" -#include "display_kingmeter.h" #include "adc.h" //#include "update_setpoint.h" FIXME, not needed anymore? #include "ACAcontrollerState.h" diff --git a/uart.c b/uart.c index 3402e4a1..edbdbcef 100755 --- a/uart.c +++ b/uart.c @@ -50,7 +50,7 @@ uint8_t uart_get_buffered(void) { } // FIXME only needed as long as the other displays do not use new functions // and instead have their own irq handler -#ifdef BLUOSEC + void UART2_IRQHandler(void) __interrupt(UART2_IRQHANDLER) { // if there is something to read, read it into cyclic buffer @@ -83,7 +83,7 @@ void UART2_IRQHandler(void) __interrupt(UART2_IRQHANDLER) { } } } -#endif + void uart_send_if_avail() { // if there is something to send and we are not already sending if ((ui8_tx_fillpointer != ui8_tx_digestpointer)&&(UART2_GetFlagStatus(UART2_FLAG_TXE) != RESET)) {