@@ -7,25 +7,39 @@
# include "monomaniacone72pt.h"
# include "usart.h"
# include "crc.h"
# include "float16.h"
# include <stdio.h>
uint8_t initialized = 0 ;
void run_dashboard_loop ( ) {
init ( ) ;
LCD_Init ( ) ;
LCD_Fill_Screen ( COLOR_OFF , 1 ) ;
LCD_Fill_Screen ( COLOR_BG , 0 ) ;
HAL_Delay ( 1000 ) ;
while ( 1 ) {
update_values_setup ( ) ;
update_adc ( ) ;
HAL_Delay ( 100 ) ;
}
}
void run_dashboard_loop_test ( ) {
LCD_Init ( ) ;
LCD_Fill_Screen ( COLOR_OFF , 1 ) ;
LCD_Fill_Screen ( COLOR_BG , 0 ) ;
draw_init ( ) ;
uint32_t i = 0 ;
while ( 1 ) {
if ( i % 10 = = 0 ) {
update_values ( ) ;
}
draw_battery ( 654 , i * 100 / 4 , 1321 , 343 ) ;
draw_speed ( i * 1000 / 4 ) ;
int16_t duty = 1000 - ( int16_t ) i * 1000 / 200 ;
draw_power_bars ( duty ) ;
draw_power ( 100 * i / 20 * ( duty < 0 ? - 1 : 1 ) , duty , 60 * 10 ) ;
draw_adc ( ( i % 34 ) * 100000 , ( ( 400 - i + 16 ) % 34 ) * 100000 ) ;
draw_adc ( i % 34 , ( 400 - i + 16 ) % 34 , i % 34 > = 2.5 , ( 400 - i + 16 ) % 34 > = 2.5 ) ;
draw_temps ( ( 4 * i ) % 900 , ( ( 10 * i ) + 450 ) % 900 ) ;
@@ -39,66 +53,155 @@ void run_dashboard_loop() {
}
void init ( ) {
LCD_Init ( ) ;
draw_init ( ) ;
}
void update_values ( ) {
// UART send 0201 04 4084 03
void update_values_setup ( ) {
// UART send 0201 2F D58D 03
uint8_t packet [ 1 ] ;
packet [ 0 ] = 0x04 ; // PAYLOAD ( COMM_GET_VALUES)
packet [ 0 ] = 0x2F ; // COMM_GET_VALUES_SETUP
USART1_SendPacket ( packet , 1 ) ;
// Wait for start byte (0x02)
while ( USART1_ReceiveByte ( ) ! = 0x02 ) {
}
;
// Read length (big-endian)
uint16_t len = USART1_ReceiveUInt16 ( ) & 0xFF ;
// Read packet
uint8_t data [ len ] ;
for ( uint16_t i = 0 ; i < len - 2 ; i + + ) {
data [ i ] = USART1_ReceiveByte ( ) ;
uint8_t len = USART1_ReceiveUInt16 ( ) & 0xFF ;
if ( len ! = 0x46 ) {
HAL_Delay ( 500 ) ;
USART1_Flush ( ) ;
return ; // Timed out
}
uint16_t crc = USART1_ReceiveUInt16 ( ) ;
// Read packet
USART1_ReceiveByte ( ) ; // Packet id
int16_t temp_fet = USART1_ReceiveInt16 ( ) ;
int16_t temp_motor = USART1_ReceiveInt16 ( ) ;
USART1_ReceiveInt32 ( ) ; // Current tot
int32_t current_in_tot = USART1_ReceiveInt32 ( ) ;
int16_t duty_cycle = USART1_ReceiveInt16 ( ) ;
USART1_ReceiveInt32 ( ) ; // rpm
int32_t speed = USART1_ReceiveInt32 ( ) ;
int16_t input_voltage_filtered = USART1_ReceiveInt16 ( ) ;
int16_t battery_level = USART1_ReceiveInt16 ( ) ;
USART1_ReceiveInt32 ( ) ; // ah tot
USART1_ReceiveInt32 ( ) ; // ah charge tot
USART1_ReceiveInt32 ( ) ; // wh tot
USART1_ReceiveInt32 ( ) ; // wh charge tot
USART1_ReceiveInt32 ( ) ; // distance
int32_t distance_abs = USART1_ReceiveInt32 ( ) ;
USART1_ReceiveInt32 ( ) ; // pid pos now
uint8_t fault_code = USART1_ReceiveByte ( ) ;
USART1_ReceiveByte ( ) ; // Controller Id
USART1_ReceiveByte ( ) ; // Num VESCs
USART1_ReceiveInt32 ( ) ; // wh battery left
uint32_t distance_life = USART1_ReceiveUInt32 ( ) ;
USART1_ReceiveUInt32 ( ) ; // System time
USART1_ReceiveUInt16 ( ) ; // CRC
// End byte
if ( USART1_ReceiveByte ( ) ! = 0x03 ) {
return ; // Invalid packet
}
// CRC check
if ( crc ! = crc16 ( data , len ) ) {
return ;
// if (crc != crc16(data, len)) {
// return;
// }
if ( ! initialized ) {
draw_init ( ) ;
initialized = 1 ;
}
__NOP ( ) ;
}
void update_values_setup ( ) {
// UART send 0201 2F D58D 03
draw_battery ( input_voltage_filtered , battery_level , distance_abs ,
distance_life ) ;
draw_power_bars ( duty_cycle ) ;
draw_speed ( speed * 10 ) ;
draw_power ( current_in_tot , duty_cycle , input_voltage_filtered ) ;
draw_temps ( temp_fet , temp_motor ) ;
}
void update_adc ( ) {
// UART send 0201 20 2462 03
// Replies to 0x24 0x65 for command id: 0, 1, 18, 19, 1B, 1D, C9, CA
// 0 1 24 25 27 29 201 202
uint8_t packet [ 3 ] ;
packet [ 0 ] = 0x24 ; // COMM_CUSTOM_APP_DATA
packet [ 1 ] = 0x65 ; // reFloat package interface
packet [ 2 ] = 0x01 ; // command id
USART1_SendPacket ( packet , 3 ) ;
uint8_t len = USART1_ReceiveUInt16 ( ) & 0xFF ;
if ( len = = 0xFF ) { // len is usually 0x3A = 58, but may be shorter.
HAL_Delay ( 500 ) ;
USART1_Flush ( ) ;
return ; // Timed out
}
void LCD_DrawHollowRoundRect (
uint16_t x ,
uint16_t y ,
uint16_t w ,
uint16_t h ,
uint8_t radius_top ,
uint8_t radius_bottom ,
uint8_t border_width ,
uint16_t color ,
uint16_t fill_color ,
uint8_t do_fill ) ;
// Read packet
USART1_ReceiveByte ( ) ; // packet id
USART1_ReceiveByte ( ) ; // reFloat package interface
USART1_ReceiveByte ( ) ; // command id
USART1_ReceiveInt32 ( ) ; // Balance current
USART1_ReceiveInt32 ( ) ; // IMU Pitch
USART1_ReceiveInt32 ( ) ; // IMU Roll
USART1_ReceiveByte ( ) ; // State
uint8_t beep_fs_state = USART1_ReceiveByte ( ) ; // Beep reason + footpad sensors state
uint32_t adc1_f32 = USART1_ReceiveUInt32 ( ) ;
uint32_t adc2_f32 = USART1_ReceiveUInt32 ( ) ;
// Results if command id 31 (0x1F) was working:
// uint8_t mask = USART1_ReceiveByte();// mask // 0x00
// uint8_t extra_flags = USART1_ReceiveByte();// extra flags // 0x02
// uint32_t time = USART1_ReceiveInt32();// time // 0x00 10 00 41
// uint8_t state_and_time = USART1_ReceiveByte();// state_and_mode // 0x9B
// uint8_t flags_and_footpad = USART1_ReceiveByte();// flags_and_footpad // 0x8A
// uint8_t stop_cond_and_sat = USART1_ReceiveByte();// stop_cond_and_sat // 0x29
// uint8_t alert_reason = USART1_ReceiveByte();// alert_reason // 0x41
//
// USART1_ReceiveInt16();//motor.speed
// USART1_ReceiveInt16();//motor.erpm
// USART1_ReceiveInt16();//motor.current
// USART1_ReceiveInt16();//motor.dir_current
// USART1_ReceiveInt16();//motor.filt_current
// USART1_ReceiveInt16();//motor.duty_cycle
// USART1_ReceiveInt16();//motor.batt_voltage
// USART1_ReceiveInt16();//motor.batt_current
// USART1_ReceiveInt16();//motor.mosfet_temp
// USART1_ReceiveInt16();//motor.motor_temp
// USART1_ReceiveInt16();//imu.pitch
// USART1_ReceiveInt16();//imu.balance_pitch
// USART1_ReceiveInt16();//imu.roll
// uint16_t adc1_f16 = USART1_ReceiveUInt16();//footpad.adc1
// uint16_t adc2_f16 = USART1_ReceiveUInt16();//footpad.adc2
// USART1_ReceiveInt16();//remote.input
//// May have other ignored values.
// int16_t adc1 = refloat_float16_to_int16_scaled(adc1_f16);
// int16_t adc2 = refloat_float16_to_int16_scaled(adc2_f16);
if ( ! initialized ) {
draw_init ( ) ;
initialized = 1 ;
}
float adc1 = * ( ( float * ) & adc1_f32 ) ;
float adc2 = * ( ( float * ) & adc2_f32 ) ;
uint8_t fs_state = beep_fs_state & 0 b11 ;
uint8_t adc1_en = 0 ;
uint8_t adc2_en = 0 ;
if ( fs_state = = 1 ) {
if ( adc1 > adc2 ) {
adc1_en = 1 ;
} else {
adc2_en = 2 ;
}
} else if ( fs_state = = 2 ) {
adc1_en = 1 ;
adc2_en = 1 ;
}
draw_adc ( ( int32_t ) 10 * adc1 , ( int32_t ) 10 * adc2 , adc1_en , adc2_en ) ;
// Make sure other values are discarded
HAL_Delay ( 100 ) ;
USART1_Flush ( ) ;
}
# define LEFT_CENTER_COL1 38
# define LEFT_CENTER_COL2 116
# define RIGHT_CENTER 400
void draw_init ( ) {
LCD_Fill_Screen ( COLOR_OFF , 1 ) ;
LCD_Fill_Screen ( COLOR_BG , 0 ) ;
// Draw footpad sensors rect
uint16_t sensor_width = 126 ;
@@ -142,10 +245,10 @@ void draw_init() {
}
// Displays the battery voltage and percent, with the trip and life distances
// Input voltage from COMM_GET_VALUES, scale 10
// battery percent (level) from COMM_GET_VALUES_SETUP, scale 100
// trip distance from COMM_GET_VALUES_SETUP, scale 100
// life distance (odometer) from COMM_GET_VALUES_SETUP
// Input voltage from COMM_GET_VALUES_SETUP , scale 10
// battery percent (level) from COMM_GET_VALUES_SETUP, scale 10
// trip distance from COMM_GET_VALUES_SETUP, scale 1000, in m
// life distance (odometer) from COMM_GET_VALUES_SETUP, in m
int16_t last_voltage = 0 ;
int32_t last_percent = 0 ;
int32_t last_trip_dist = 0 ;
@@ -155,17 +258,17 @@ void draw_battery(
int32_t trip_dist ,
uint32_t life_dist ) {
if ( voltage = = last_voltage & & percent / 100 = = last_percent / 100
& & trip_dist / 10 = = last_trip_dist / 10 ) {
if ( voltage = = last_voltage & & percent / 10 = = last_percent
& & trip_dist / 100000 = = last_trip_dist ) {
return ;
}
last_voltage = voltage ;
last_percent = percent ;
last_trip_dist = trip_dist ;
last_percent = percent / 10 ;
last_trip_dist = trip_dist / 100000 ;
uint16_t bar_width = LCD_WIDTH - 12 ;
uint16_t bar_height = 22 ;
uint16_t filled_bar_width = ( ( ( float ) ( percent / 100 ) ) / 100.0 ) * bar_width ;
uint16_t filled_bar_width = ( ( ( float ) ( percent / 10 ) ) / 100.0 ) * bar_width ;
if ( filled_bar_width < 6 ) {
filled_bar_width = 6 ; // Must be at least the size of the border radius.
}
@@ -176,10 +279,10 @@ void draw_battery(
char voltage_text [ 8 ] ;
sprintf ( voltage_text , " %.1fV " , ( ( float ) voltage ) / 10.0 ) ;
char percent_text [ 6 ] ;
sprintf ( percent_text , " %lu%% " , percent / 100 ) ;
sprintf ( percent_text , " %lu%% " , percent / 10 ) ;
char distances_text [ 20 ] ;
sprintf ( distances_text , " %.1fKm / %luKm " , ( ( float ) trip_dist ) / 100.0 ,
life_dist ) ;
sprintf ( distances_text , " %.1fKm / %luKm " ,
( ( float ) ( trip_dist / 100000 ) ) / 10.0 , life_dist / 1000 ) ;
// Drawing the bars
LCD_DrawHollowRoundRect ( 4 , LCD_HEIGHT - ( bar_height + 4 ) - 4 , bar_width + 4 ,
@@ -193,7 +296,7 @@ void draw_battery(
uint16_t left_x = 10 ;
uint16_t right_x = LCD_WIDTH - 10 ;
if ( percent > 20 * 100 ) {
if ( percent > 20 * 10 ) {
// Drawing the voltage to the left
left_x = 10
+ GFX_DrawText ( left_x , text_y_14 , voltage_text , & monomaniacone14pt ,
@@ -205,7 +308,7 @@ void draw_battery(
COLOR_FG , COLOR_BG , 2 , - 2 ) ;
}
if ( percent > 50 * 100 ) {
if ( percent > 50 * 10 ) {
// Drawing the distances on the left
GFX_DrawText ( left_x , text_y_14 , distances_text , & monomaniacone14pt ,
COLOR_BG , COLOR_SUCCESS , 0 , - 3 ) ;
@@ -215,7 +318,7 @@ void draw_battery(
COLOR_FG , COLOR_BG , 2 , - 3 ) ;
}
if ( percent > 80 * 100 ) {
if ( percent > 80 * 10 ) {
// Drawing the distances on the left
GFX_DrawText ( filled_bar_end_x - 4 , text_y_14 , percent_text ,
& monomaniacone14pt ,
@@ -386,14 +489,13 @@ void draw_power(int32_t current_i, int16_t duty_i, int16_t voltage_i) {
uint16_t last_adc1 = 1000 ;
uint16_t last_adc2 = 1000 ;
uint16_t adc_threshold = 29 ;
// Displays the two ADS voltages
// 2 voltages from COMM_GET_DECODED_ADC, scale 1 000 000
void draw_adc ( int32_t adc1_scaled , int32_t adc2_scaled ) {
uint16_t adc1 =
adc1_scaled < 0 ? - adc1_scaled / 100000 : adc1_scaled / 100000 ;
uint16_t adc2 =
adc2_scaled < 0 ? - adc2_scaled / 100000 : adc2_scaled / 100000 ;
uint8_t last_adc1_en = 0 ;
uint8_t last_adc2_en = 0 ;
// Displays the two ADC voltages
// 2 voltages from reFloat - COMM_CUSTOM_APP_DATA, scale 10, adcx_en are booleans.
void draw_adc ( int32_t adc1_scaled , int32_t adc2_scaled , uint8_t adc1_en , uint8_t adc2_en ) {
uint16_t adc1 = adc1_scaled < 0 ? - adc1_scaled : adc1_scaled ;
uint16_t adc2 = adc2_scaled < 0 ? - adc2_scaled : adc2_scaled ;
if ( adc1 > 33 ) {
adc1 = 33 ;
}
@@ -401,7 +503,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) {
adc2 = 33 ;
}
// Max filled height = 39
if ( adc1 ! = last_adc1 ) {
if ( adc1 ! = last_adc1 | | adc1_en ! = last_adc1_en ) {
uint16_t filled_height = adc1 * 39 / 33 ;
uint16_t free_height = 61 - filled_height ;
@@ -411,7 +513,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) {
COLOR_BG ) ;
// Draw the colored zone
uint16_t color = adc1 > = adc_threshold ? COLOR_SUCCESS : COLOR_ERROR ;
uint16_t color = adc1_en ? COLOR_SUCCESS : COLOR_ERROR ;
LCD_Draw_Rectangle ( RIGHT_CENTER - 3 - 54 , 76 + free_height , 54 ,
filled_height , color ) ;
@@ -422,9 +524,10 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) {
& monomaniacone14pt , color , COLOR_BG , 1 , - 2 ) ;
last_adc1 = adc1 ;
last_adc1_en = adc1_en ;
}
// Max filled height = 39
if ( adc2 ! = last_adc2 ) {
if ( adc2 ! = last_adc2 | | adc2_en ! = last_adc2_en ) {
uint16_t filled_height = adc2 * 39 / 33 ;
uint16_t free_height = 61 - filled_height ;
@@ -434,7 +537,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) {
COLOR_BG ) ;
// Draw the colored zone
uint16_t color = adc2 > = adc_threshold ? COLOR_SUCCESS : COLOR_ERROR ;
uint16_t color = adc2_en ? COLOR_SUCCESS : COLOR_ERROR ;
LCD_Draw_Rectangle ( RIGHT_CENTER + 3 , 76 + free_height , 54 , filled_height ,
color ) ;
@@ -445,6 +548,7 @@ void draw_adc(int32_t adc1_scaled, int32_t adc2_scaled) {
& monomaniacone14pt , color , COLOR_BG , 1 , - 2 ) ;
last_adc2 = adc2 ;
last_adc2_en = adc2_en ;
}
}