示例#1
0
文件: user.c 项目: romelemperado/psx
// *************************************************************************************************
// @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();
}
// *************************************************************************************************
// @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
}