commit 5f152b9f37adee99314ace9e46020234ad3b4a51
parent 89ed277617f38496c114e6a05afc6ce1dfe34a60
Author: William Lindholm <william_lindholm@outlook.com>
Date: Tue, 12 Nov 2024 02:16:04 +0000
Changed to circular queue for usart transmitting
Diffstat:
2 files changed, 151 insertions(+), 35 deletions(-)
diff --git a/Project2/.vs/Project2/v14/.atsuo b/Project2/.vs/Project2/v14/.atsuo
Binary files differ.
diff --git a/Project2/Project2/main.c b/Project2/Project2/main.c
@@ -2,18 +2,22 @@
* Project2.c
*
* Created: 2024-11-06 11:04:34
- * Author : Willi
+ * Author : William Lindholm & Thomas Berry
*/
#define F_CPU 20000000
#define USART3_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
+#define BAUD_RATE 115200
+#define QUEUE_SIZE 512
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
+#include <util/delay.h>
#include <stdio.h>
#include <stdbool.h>
+#include <stdbool.h>
/************************************************************************/
@@ -33,8 +37,8 @@ struct LED_BITS LED_Array[10] = {
/* Serial com related globals */
-unsigned char qcntr = 0,sndcntr = 0; /*indexes into the queue*/
-unsigned char queue[50]; /*character queue*/
+uint16_t qcntr = 0, sndcntr = 0; /*indexes into the queue*/
+unsigned char queue[QUEUE_SIZE]; /*character queue*/
/* Led related globals */
bool ADC_READING_READY;
@@ -46,20 +50,28 @@ uint16_t ADC_VALUE;
/* Function declarations */
/************************************************************************/
void CLOCK_init (void);
-static void USART3_init(void);
+static void configure_USART3(void);
void sendmsg (char *s);
void configure_ADC0(void);
+void print_adc_voltage(void);
+void print_adc_value(void);
+void print_available_commands(void);
+bool queue_is_empty(void);
int main(void)
{
- char ch;
- char str_buffer[60];
- uint32_t adc_reading_mv;
-
+ char ch;
+ char str_buffer[32];
+ // Flags
+ bool continuous_adc_reporting = false;
+ bool continuous_timer_reporting = false;
+ bool continuous_lowpulse_reporting = false;
+ bool continuous_highpulse_reporting = false;
+
CLOCK_init();
- USART3_init();
+ configure_USART3();
configure_ADC0();
sei(); /* Enable Global Interrupts */
@@ -71,23 +83,39 @@ int main(void)
ch = USART3.RXDATAL;
switch (ch)
{
+ case 'A':
case 'a':
- adc_reading_mv = ((uint32_t)ADC_VALUE * 5000) / 1023;
- sprintf(str_buffer, "ADC0 = %d, %lumV\n", ADC_VALUE, adc_reading_mv);
- sendmsg(str_buffer);
+ print_adc_value();
+ break;
+ case 'V':
+ case 'v':
+ print_adc_voltage();
break;
- case 'b':
- case 'B':
- sprintf(str_buffer, "That was a B or a b\n");
+ case 'M': // Start continuous reporting of ADC voltage in mV
+ case 'm':
+ continuous_adc_reporting = true;
+ break;
+ case 'N': // Stop continuous reporting of ADC
+ case 'n':
+ continuous_adc_reporting = false;
+ sprintf(str_buffer, "Stopped\n");
sendmsg(str_buffer);
break;
default:
- sprintf(str_buffer, "That was neither 'a' or 'b'\n");
- sendmsg(str_buffer);
+ print_available_commands();
break;
}
}
- /* Even if a character has not been received, code inserted here can still run */
+
+ // Continuous reporting
+ if (continuous_adc_reporting)
+ {
+ if (ADC_READING_READY && queue_is_empty())
+ {
+ print_adc_voltage();
+ ADC_READING_READY = false;
+ }
+ }
}
}
@@ -95,18 +123,21 @@ void CLOCK_init (void)
{
/* Do not use low frequency clock, disable CLK_PER Prescaler */
ccp_write_io( (void *) &CLKCTRL.MCLKCTRLB , (0 << CLKCTRL_PEN_bp));
- /* If set from the fuses during progamming, the CPU will now run at 20MHz (default is /6) */
+ /* If set from the fuses during programming, the CPU will now run at 20MHz (default is /6) */
}
-static void USART3_init(void)
+static void configure_USART3(void)
{
+ // Assign the USART3 transmit complete interrupt high priority (1)
+ CPUINT.LVL1VEC = USART3_TXC_vect_num;
+
PORTB.DIR &= ~PIN5_bm; /* this is the RX input */
PORTB.DIR |= PIN4_bm; /* this is the TX output */
- USART3.BAUD = (uint16_t)USART3_BAUD_RATE(9600);
- USART3.CTRLB |= (USART_TXEN_bm | USART_RXEN_bm);
- PORTMUX.USARTROUTEA |= PORTMUX_USART3_ALT1_gc;
+ USART3.BAUD = (uint16_t)USART3_BAUD_RATE(BAUD_RATE); // set the baud rate
+ USART3.CTRLB |= (USART_TXEN_bm | USART_RXEN_bm); // enable transmitter and receiver
+ PORTMUX.USARTROUTEA |= PORTMUX_USART3_ALT1_gc; // USART3 on PB[5:4]
- USART3.CTRLA = USART_TXCIE_bm;
+ USART3.CTRLA = USART_TXCIE_bm; // Transmit Complete Interrupt Enable
}
/************************************************************************/
@@ -126,24 +157,109 @@ void configure_ADC0()
/*this function loads the queue and */
/*starts the sending process*/
void sendmsg (char *s)
+{
+ uint16_t msg_len = 0;
+ char *temp = s;
+
+ while (*temp)
+ {
+ temp++;
+ msg_len++;
+ }
+
+ uint8_t available_space = (sndcntr > qcntr) ? (sndcntr - qcntr - 1) : (QUEUE_SIZE - qcntr + sndcntr - 1);
+
+ if (msg_len > available_space) // prevent it from adding any more to the buffer if its full.
+ return;
+
+ // Send message with circular buffer
+ while (*s)
+ {
+ // Prevent new message from overwriting data in queue
+ if (((qcntr + 1) % QUEUE_SIZE) != sndcntr)
+ {
+ queue[qcntr] = *s++;
+ qcntr = (qcntr + 1) % QUEUE_SIZE; // wrap around after hitting pos QUEUE_SIZE
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (qcntr != sndcntr && !(USART3.STATUS & USART_TXCIF_bm))
+ {
+ USART3.TXDATAL = queue[sndcntr];
+ sndcntr = (sndcntr + 1) % QUEUE_SIZE;
+ }
+}
+
+bool queue_is_empty()
{
- qcntr = 0; /*preset indices*/
- sndcntr = 1; /*set to one because first character already sent*/
+ return (qcntr == sndcntr);
+}
+
+/************************************************************************/
+/* Allows printing of ADC information */
+/************************************************************************/
+
+// Print the current ADC volatage reading (mV)
+void print_adc_voltage()
+{
+ char str_buffer[16];
+ uint32_t adc_reading_mv;
+ adc_reading_mv = ((uint32_t)ADC_VALUE * 5000) / 1023;
+ sprintf(str_buffer, "ADC0 = %dmV\n", (uint16_t)adc_reading_mv);
+ sendmsg(str_buffer);
+}
+
+// Print the current ADC value (0-1024)
+void print_adc_value()
+{
+ char str_buffer[16];
+ sprintf(str_buffer, "ADC0 = %d\n", ADC_VALUE);
+ sendmsg(str_buffer);
+}
+
+// Print the available commands
+void print_available_commands()
+{
+ char str_buffer[256];
+ sprintf(
+ str_buffer,
+ "Undefined instruction.\n"
+ "A/a = ADC value.\n"
+ "V/v = ADC voltage reading (mV).\n"
+ "M/m = Continuous ADC reporting (mV).\n"
+ "N/n = Stop ADC reporting.\n"
+ );
+ sendmsg(str_buffer);
- while (*s)
- queue[qcntr++] = *s++; /*put characters into queue*/
+ _delay_ms(50);
- USART3.TXDATAL = queue[0]; /*send first character to start process*/
+ sprintf(
+ str_buffer,
+ "T/t = Report timer period (mS)\n"
+ "L/l = Report low pulse\n"
+ "H/h = Report high pulse\n"
+ "C/c Continuously report timer period\n"
+ "E/e Stop continuously reporting timer period\n"
+ );
+ sendmsg(str_buffer);
}
ISR(USART3_TXC_vect)
{
- /*send next character and increment index*/
- USART3.STATUS |= USART_TXCIF_bm;
- if (qcntr != sndcntr)
- USART3.TXDATAL = queue[sndcntr++];
- /* Stop sending when the queue is empty. TXC interrupts only happen when a character
- has been transmitted. Stoppping sending stops the interrupts */
+ // Clear the transmit complete flag
+ USART3.STATUS |= USART_TXCIF_bm;
+
+ // Continue sending if there is data in the queue
+ if (sndcntr != qcntr)
+ {
+ // Load the next character from the queue
+ USART3.TXDATAL = queue[sndcntr];
+ sndcntr = (sndcntr + 1) % QUEUE_SIZE; // Move sndcntr forward with wrap-around
+ }
}
/************************************************************************/