// ************************************************************************************************* // @fn set_value // @brief Generic value setting routine // @param int32_t * value Pointer to value to set // uint8_tdigits Number of digits // uint8_t blanks Number of whitespaces before first valid digit // int32_t limitLow Lower limit of value // int32_t limitHigh Upper limit of value // uint16_t mode // uint8_t segments Segments where value should be drawn // fptr_setValue_display_function1 Value-specific display routine // @return none // ************************************************************************************************* void set_value(int32_t * value, uint8_t digits, uint8_t blanks, int32_t limitLow, int32_t limitHigh, uint16_t mode, uint8_t segments, void (*fptr_setValue_display_function1)(uint8_t segments, uint32_t value, uint8_t digits, uint8_t blanks, uint8_t disp_mode)) { uint8_t update; int16_t stepValue; if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE) { stepValue=5; } else { stepValue=1; } uint8_t doRound = 0; #ifdef CONFIG_STOP_WATCH uint8_t stopwatch_state; #endif uint32_t val; int32_t orig_val=*value; // Clear button flags button.all_flags = 0; // Clear blink memory clear_blink_mem(); // For safety only - buzzer on/off and button_repeat share same IRQ stop_buzzer(); #ifdef CONFIG_STOP_WATCH // Disable stopwatch display update while function is active stopwatch_state = sStopwatch.state; sStopwatch.state = STOPWATCH_HIDE; #endif // Init step size and repeat counter sButton.repeats = 0; // Initial display update update = 1; // Turn on 200ms button repeat function button_repeat_on(200); // Start blinking with with 2Hz set_blink_rate(BIT6 + BIT5); // Value set loop while(1) { // Idle timeout: exit function if (sys.flag.idle_timeout) break; // Button STAR (short) button: exit function if (button.flag.star) break; // NUM button: exit function and goto to next value (if available) if (button.flag.num) { if ((mode & SETVALUE_NEXT_VALUE) == SETVALUE_NEXT_VALUE) break; } // UP button: increase value if(button.flag.up) { // Increase value * value = * value + stepValue; // Check value limits if (* value > limitHigh) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitLow; else * value = limitHigh; // Reset step size to default if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE) { stepValue=5; } else { stepValue=1; } } // Trigger display update update = 1; // Clear button flag button.flag.up = 0; } // DOWN button: decrease value if(button.flag.down) { // Decrease value * value = * value - stepValue; // Check value limits if (* value < limitLow) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitHigh; else * value = limitLow; // Reset step size to default if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE) { stepValue=5; } else { stepValue=1; } } // Trigger display update update = 1; // Clear button flag button.flag.down = 0; } // When fast mode is enabled, increase step size if Sx button is continuously if ((mode & SETVALUE_FAST_MODE) == SETVALUE_FAST_MODE) { switch (sButton.repeats) { case 0: if((mode & SETVALUE_STEP_FIFE ) == SETVALUE_STEP_FIFE){ stepValue=5; doRound = 1; } else { stepValue=1; doRound = 0; } break; case 10: case -10: stepValue = 10; doRound = 1; break; case 20: case -20: stepValue = 100; doRound = 1; break; case 30: case -30: stepValue = 1000; doRound = 1; break; } // Round value to avoid odd numbers on display if (stepValue != 1 && doRound == 1) { * value -= * value % stepValue; doRound = 0; } } // Update display when there is new data if (update) { // Display up or down arrow according to sign of value if ((mode & SETVALUE_DISPLAY_ARROWS) == SETVALUE_DISPLAY_ARROWS) { if (* value >= 0) { display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); val = *value; } else { display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); val = *value * (-1); } } else { val = *value; } if((mode & SETVALUE_DISPLAY_SYMBOL) == SETVALUE_DISPLAY_SYMBOL) { display_symbol(segments,SEG_ON_BLINK_ON); // return when value is changed if( orig_val != *value ) break; } else if( (mode & SETVALUE_SWITCH_ARROWS) == SETVALUE_SWITCH_ARROWS ) { //show up arrow if value is odd if( val & 0x1 ) { display_symbol(LCD_SYMB_ARROW_UP,SEG_ON_BLINK_ON); display_symbol(LCD_SYMB_ARROW_DOWN,SEG_OFF_BLINK_OFF); } //show down arrow if value is even else { display_symbol(LCD_SYMB_ARROW_DOWN,SEG_ON_BLINK_ON); display_symbol(LCD_SYMB_ARROW_UP,SEG_OFF_BLINK_OFF); } } else { // Display function can either display value directly, modify value before displaying // or display a string referenced by the value fptr_setValue_display_function1(segments, val, digits, blanks, SEG_ON_BLINK_ON); } // Clear update flag update = 0; } // Call idle loop to serve background tasks idle_loop(); } //switch symbol if((mode & SETVALUE_DISPLAY_SYMBOL) == SETVALUE_DISPLAY_SYMBOL) { display_symbol(segments,SEG_OFF); } // Set blinking rate to 1Hz and stop set_blink_rate(BIT7 + BIT6 + BIT5); clear_blink_mem(); // Turn off button repeat function button_repeat_off(); #ifdef CONFIG_STOP_WATCH // Enable stopwatch display updates again sStopwatch.state = stopwatch_state; #endif }
// ************************************************************************************************* // @fn set_value // @brief Generic value setting routine // @param s32 * value Pointer to value to set // u8digits Number of digits // u8 blanks Number of whitespaces before first valid digit // s32 limitLow Lower limit of value // s32 limitHigh Upper limit of value // u16 mode // u8 segments Segments where value should be drawn // fptr_setValue_display_function1 Value-specific display routine // @return none // ************************************************************************************************* void set_value(s32 * value, u8 digits, u8 blanks, s32 limitLow, s32 limitHigh, u16 mode, u8 segments, void (*fptr_setValue_display_function1)(u8 segments, u32 value, u8 digits, u8 blanks)) { u8 update; s16 stepValue = 1; u8 doRound = 0; u32 val; // Clear button flags button.all_flags = 0; // Clear blink memory clear_blink_mem(); // For safety only - buzzer on/off and button_repeat share same IRQ stop_buzzer(); // Init step size and repeat counter sButton.repeats = 0; // Initial display update update = 1; // Turn on 200ms button repeat function button_repeat_on(200); // Start blinking with with 2Hz set_blink_rate(BIT6 + BIT5); // Value set loop while(1) { // Idle timeout: exit function if (sys.flag.idle_timeout) break; // STAR (short) button: exit function if (button.flag.star) break; // NUM button: exit function and goto to next value (if available) if (button.flag.num) { if ((mode & SETVALUE_NEXT_VALUE) == SETVALUE_NEXT_VALUE) break; } // UP button: increase value if(button.flag.up) { // Increase value * value = * value + stepValue; // Check value limits if (* value > limitHigh) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitLow; else * value = limitHigh; // Reset step size to default stepValue = 1; } // Trigger display update update = 1; // Clear button flag button.flag.up = 0; } // DOWN button: decrease value if(button.flag.down) { // Decrease value * value = * value - stepValue; // Check value limits if (* value < limitLow) { // Check if value can roll over, else stick to limit if ((mode & SETVALUE_ROLLOVER_VALUE) == SETVALUE_ROLLOVER_VALUE) * value = limitHigh; else * value = limitLow; // Reset step size to default stepValue = 1; } // Trigger display update update = 1; // Clear button flag button.flag.down = 0; } // When fast mode is enabled, increase step size if Sx button is continuously if ((mode & SETVALUE_FAST_MODE) == SETVALUE_FAST_MODE) { switch (sButton.repeats) { case 0: stepValue = 1; doRound = 0; break; case 10: case -10: stepValue = 10; doRound = 1; break; case 20: case -20: stepValue = 100; doRound = 1; break; case 30: case -30: stepValue = 1000; doRound = 1; break; } // Round value to avoid odd numbers on display if (stepValue != 1 && doRound == 1) { * value -= * value % stepValue; doRound = 0; } } // Update display when there is new data if (update) { // Display up or down arrow according to sign of value if ((mode & SETVALUE_DISPLAY_ARROWS) == SETVALUE_DISPLAY_ARROWS) { if (* value >= 0) { display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); val = *value; } else { display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); val = *value * (-1); } } else { val = *value; } // Display function can either display value directly, modify value before displaying // or display a string referenced by the value fptr_setValue_display_function1(segments, val, digits, blanks); // Clear update flag update = 0; } // Call idle loop to serve background tasks idle_loop(); } // Clear up and down arrows display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); // Set blinking rate to 1Hz and stop set_blink_rate(BIT7 + BIT6 + BIT5); clear_blink_mem(); // Turn off button repeat function button_repeat_off(); }
int main (void) { int tmp,i,res; CLKPR = 0x80; CLKPR = 0x00; // Clock prescaler Reset /*-----------------------------------------------------------------* *------------------------- Gear buttoms setup---------------------* *-----------------------------------------------------------------*/ DDRC&=~(1<<PC7); // Neutral PORTC |= (1<<PC7); // Neutral pull-up DDRE&=~(1<<PE6); // Knap1 DDRE&=~(1<<PE7); // Knap2 /* Buttoms interrupt */ EICRB |= (1<<ISC71|1<<ISC70|1<<ISC61|1<<ISC60); /* Rising edge */ EIMSK |= (1<<INT7 | 1<<INT6); uint8_t test_rx[8]; int8_t data; char streng[10]; // Recieve buffer st_cmd_t msg; // Init CAN, UART, I/O init(); uartinit(); sendtekst("UART initialized\n\r"); TWI_init(); sendtekst("TWI initialized\n\r"); sei(); /* Interrupt enable */ sendtekst("Interrupt enabled\n\r"); /*-----------------------------------------------------------------* *----------------------------Display setup -----------------------* *-----------------------------------------------------------------*/ /* Set blink rates */ set_blink_rate(LED0_7_ADDR, LED_BLINK1, 20, 100); set_blink_rate(LED0_7_ADDR, LED_BLINK2, 0, RPM_LED_DUTYCYCLE*2.56); set_blink_rate(LED8_15_ADDR, LED_BLINK1, (1.0/RPM16_RATE)*252, RPM16_DUTYCYCLE*2.56); set_blink_rate(LED8_15_ADDR, LED_BLINK2, 0, RPM_LED_DUTYCYCLE*2.56); set_blink_rate(SEG_ADDR, LED_BLINK1, 20, 100); set_blink_rate(SEG_ADDR, LED_BLINK2, 0, SEG_DUTYCYCLE*2.56); set_blink_rate(LED_BUTTONS_ADDR, LED_BLINK1, 20, 100); set_blink_rate(LED_BUTTONS_ADDR, LED_BLINK2, 0, SEG_DUTYCYCLE*2.56); /*-----------------------------------------------------------------* *----------------------------CAN interrupt setup -----------------* *-----------------------------------------------------------------*/ Can_sei(); /* Enable general can interrupt */ Can_set_tx_int(); /* Enable can tx interrupt */ Can_set_rx_int(); /* Enable can rx interrupt */ /* * Kode til hurtig test af can */ sendtekst("Config 3 mailboxes for rpm_msgid...\n\r"); msg.id.std = rpm_msgid; msg.dlc = 8; res = can_config_rx_mailbox(&msg, 3); if (res == CAN_CMD_ACCEPTED) { sendtekst("SUCCESS\n\r"); } else { sendtekst("FAIL\n\r"); } // --- Init variables /* Init user led 0 & 1 */ DDRB |= (1<<PB6 | 1<<PB5); PORTB |= (1<<PB6 | 1<<PB5); sendtekst("Beep\n\r"); display_test(); params.GearEst = 0; char dataout[] = {gear,0}; while (1) { _delay_ms(20); /* Display selected parameter */ if (mode == RPM_MODE) { set_rpm(params.rpm, LED_ON); } else if (mode == VOLTAGE_MODE) { set_voltage(params.batteryV, LED_ON); } else if (mode == WATER_TEMP_MODE) { set_water_temp(params.waterTemp, LED_ON); } // Geat buttons to CAN dataout[1] = 0; /* Format buttom states for sending */ dataout[1] |= (params.GearButDown*GEARDOWNBUT | GEARUPBUT*params.GearButUp | params.GearButNeutral*GEARNEUBUT); /* Send buttom states */ if(dataout[1] != 0) { // Hack, sender gearskiftesignal et par gange, sådan at det går igennem // Symptombehandling, sygdommen skal kureres... if (dataout[1] & (GEARDOWNBUT) == GEARDOWNBUT) indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1); if (dataout[1] & (GEARUPBUT) == GEARUPBUT) indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1); set_leds(LED_BUTTONS_ADDR, indi_leds_state); for(j=0;j<1;j++){ can_send_non_blocking(gear_msgid, dataout, 2); _delay_ms(5); } indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_2); indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_1); set_leds(LED_BUTTONS_ADDR, indi_leds_state); } /* Clear buttom states */ params.GearButDown = 0; params.GearButUp = 0; params.GearButNeutral = 0; /* Display bottons code */ buttons_state = get_buttons(LED_BUTTONS_ADDR) & (BUTTON1 | BUTTON2); if (buttons_state == 2) { indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1); indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_2); mode = VOLTAGE_MODE; } else if (buttons_state == 1) { indi_leds_state |= (LED_BLINK2<<LED_BUTTON_2); indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_1); mode = WATER_TEMP_MODE; } else if (buttons_state == 0) { indi_leds_state |= (LED_BLINK2<<LED_BUTTON_1 | LED_BLINK2<<LED_BUTTON_2); } else { indi_leds_state &= ~(LED_BLINK2<<LED_BUTTON_1 | LED_BLINK2<<LED_BUTTON_2); mode = RPM_MODE; } /* Indicator for water temp */ if (params.waterTemp <= WATER_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI1); indi_leds_state &= ~(LED_BLINK2<<LED_INDI4); } else if (params.waterTemp > WATER_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI4); indi_leds_state &= ~(LED_BLINK2<<LED_INDI1); } /* Indicator for batt ok */ if (params.batteryV <= VOLTAGE_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI2); indi_leds_state &= ~(LED_BLINK2<<LED_INDI5); } else if (params.batteryV > VOLTAGE_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI5); indi_leds_state &= ~(LED_BLINK2<<LED_INDI2); } /* Indicator for oil pressure ok */ if (params.oilPressure <= OILPRESS_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI3); indi_leds_state &= ~(LED_BLINK2<<LED_INDI6); } else if (params.oilPressure > OILPRESS_OK) { indi_leds_state |= (LED_BLINK2<<LED_INDI6); indi_leds_state &= ~(LED_BLINK2<<LED_INDI3); } /* Indicator for Gear */ if (params.GearNeutral < 0) { SEG_N(LED_ON); } else { if (params.GearEst > 6) { SEG_OFF(); } else { switch (params.GearEst) { case 0: SEG_N(LED_ON); break; case 1: SEG_1(LED_ON); break; case 2: SEG_2(LED_ON); break; case 3: SEG_3(LED_ON); break; case 4: SEG_4(LED_ON); break; case 5: SEG_5(LED_ON); break; case 6: SEG_6(LED_ON); break; default: break; } } } /* if (params.GearNeutral == 0) { SEG_OFF(); } else if (params.GearNeutral > 0) { SEG_N(LED_BLINK2); } */ /* Set indicator leds */ set_leds(LED_BUTTONS_ADDR, indi_leds_state); /* itoa(params.batteryV, streng, 10);*/ /* sendtekst(streng);*/ /* sendtekst("\n\r"); */ PORTB ^= (1<<PB6); } return 0; }