+/*
+ * File: adc_random.c
+ *
+ * Generate a random 8-bit value by reading an unused (floating) IO pin.
+ * Pin 1, RA2 (AN2) is free in the current design.
+ */
+
+#include <htc.h>
+#include "timer.h"
+
+unsigned char adc_random()
+{
+ unsigned char save_ansela;
+ unsigned char save_trisa;
+ unsigned char accumulate = 0;
+
+ /* Turn on the FVR, configured for 1.024V to the ADC */
+ FVRCON = 0b10000001;
+ while (!FVRRDY); /* wait for ready signal */
+
+ /* Configure RA2 (AN2) for ADC input */
+ save_ansela = ANSELA;
+ ANSELA |= 4;
+ save_trisa = TRISA;
+ TRISA |= 4;
+ ADCON1 = 0b11110011; /* Right justified result, Frc clk, FVR/Vss refs */
+ ADCON0 = 0b00001001; /* Enable channel AN2, enable ADC */
+
+ /* Sample the ADC several times, accumulating the LSB of the result */
+ for (unsigned i = 0; i < 128; i++) {
+ timer_uwait(10); /* Sampling time */
+ ADGO = 1; /* Start the conversion */
+ while (ADGO); /* wait for completion */
+ accumulate += ADRESL;
+ }
+
+ /* Turn off ADC, FVR, and revert PORTA changes */
+ ADON = 0;
+ FVREN = 0;
+ TRISA = save_trisa;
+ ANSELA = save_ansela;
+
+ /* Return the result */
+ return accumulate;
+}