#include <main.h>

#include <lcd.c>

void main() {
	setup_adc_ports(sAN0 | sAN1 | sAN2, VSS_VDD);
	setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_0);

   lcd_init();
 
	int btn_1_mode = 0; // Button 1 counter

	while(TRUE)	{
		// TASK 1
		// Show all three potentiometer values on separate lines, from 0-255
		sane_lcd_gotoxy(7,0); // Line 1 centre
		printf(lcd_putc, "A=%3u", read_pot(0));
		sane_lcd_gotoxy(7,1); // Line 2 centre
		printf(lcd_putc, "B=%3u", read_pot(1));
		sane_lcd_gotoxy(7,2); // Line 3 centre
		printf(lcd_putc, "C=%3u", read_pot(2));

		// TASK 2
		if (input(BTN_1)) {
			switch (btn_1_mode++) {
				default:
					// If counter overflows, reset counter and then proceed to mode 0
					btn_1_mode = 0;
				case 0: // TASK 2.i
					// Set motor running counter-clockwise
					output_low (MOTOR_A);
					output_high(MOTOR_B);
					break;

				case 2: // TASK 2.iii
					// Set motor running counter-clockwise
					output_high(MOTOR_A);
					output_low (MOTOR_B);
					break;

				// In either steps 2 or 4...
				case 1: // TASK 2.ii
				case 3: // TASK 2.iv
					// ... stop the motor.
					output_low(MOTOR_A);
					output_low(MOTOR_B);
					break;
			}

			while (input(BTN_1)); // Wait for release
		}

		// TASK 3
		if (input(BTN_2)) {
			btn_1_mode = 0; // Interpretation of "sequentially" in Task 2 suggests that pressing Button 2 should reset the sequence
			
			// For each potentiometer A,B,C (0,1,2)...
			for (int pot=0; pot<=2; pot++) {
				// ... show the binary representation on the LEDs
				output_b(read_pot(pot));
				// Then wait 2 seconds before showing the next value.
				delay_ms(2000);
			}
			output_b(0); // Clear LEDS after the final value

			// Task 3 doesn't specify if this should loop when held. I've interpreted "press" to mean "on rising edge". 
			while (input(BTN_2)); // Wait for release
		}
	}
}

int read_pot(int pot) {
	// Change ADC channel then return a reading.
	// Argument 'pot' corresponds to PORTA analogue pins 0-3
	set_adc_channel(pot);
	delay_us(20); // Allow time for the hardware to adjust
	return read_adc();
}

void sane_lcd_gotoxy(int x, int y) {
   // Because the memory map for multiple lines on a character LCD are ludicrous.
   switch (y) {
	  case 0:
	  default:
		 lcd_gotoxy(1+x,1); // Line 1
		 break;
	  case 1:
		 lcd_gotoxy(1+x,0); // Line 2
		 break;
	  case 2:
		 lcd_gotoxy(21+x,1); // Line 3
		 break;
	  case 3:
		 lcd_gotoxy(21+x,0); // Line 4
		 break;
   }
}
