aboutsummaryrefslogtreecommitdiff
path: root/src/peripherals/usart.ts
diff options
context:
space:
mode:
authorUri Shaked2021-07-15 17:53:05 +0300
committerUri Shaked2021-07-15 17:53:05 +0300
commit77afa2308ed969a9583149646d05e26716f672d8 (patch)
tree221a129adee9da672660ac6fe8c05a37f33358e8 /src/peripherals/usart.ts
parent0.16.1 (diff)
downloadavr8js-77afa2308ed969a9583149646d05e26716f672d8.tar.gz
avr8js-77afa2308ed969a9583149646d05e26716f672d8.tar.bz2
avr8js-77afa2308ed969a9583149646d05e26716f672d8.zip
feat(usart): add configuration change event
also add `txEnable` and `rxEnable` properties
Diffstat (limited to 'src/peripherals/usart.ts')
-rw-r--r--src/peripherals/usart.ts42
1 files changed, 39 insertions, 3 deletions
diff --git a/src/peripherals/usart.ts b/src/peripherals/usart.ts
index f55fef3..3ad787d 100644
--- a/src/peripherals/usart.ts
+++ b/src/peripherals/usart.ts
@@ -3,7 +3,7 @@
* Part of AVR8js
* Reference: http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
*
- * Copyright (C) 2019, 2020, Uri Shaked
+ * Copyright (C) 2019, 2020, 2021 Uri Shaked
*/
import { AVRInterruptConfig, CPU } from '../cpu/cpu';
@@ -36,6 +36,7 @@ export const usart0Config: USARTConfig = {
export type USARTTransmitCallback = (value: u8) => void;
export type USARTLineTransmitCallback = (value: string) => void;
+export type USARTConfigurationChangeCallback = () => void;
/* eslint-disable @typescript-eslint/no-unused-vars */
// Register bits:
@@ -47,6 +48,7 @@ const UCSRA_DOR = 0x8; // Data OverRun
const UCSRA_UPE = 0x4; // USART Parity Error
const UCSRA_U2X = 0x2; // Double the USART Transmission Speed
const UCSRA_MPCM = 0x1; // Multi-processor Communication Mode
+const UCSRA_CFG_MASK = UCSRA_U2X;
const UCSRB_RXCIE = 0x80; // RX Complete Interrupt Enable
const UCSRB_TXCIE = 0x40; // TX Complete Interrupt Enable
const UCSRB_UDRIE = 0x20; // USART Data Register Empty Interrupt Enable
@@ -55,6 +57,7 @@ const UCSRB_TXEN = 0x8; // Transmitter Enable
const UCSRB_UCSZ2 = 0x4; // Character Size 2
const UCSRB_RXB8 = 0x2; // Receive Data Bit 8
const UCSRB_TXB8 = 0x1; // Transmit Data Bit 8
+const UCSRB_CFG_MASK = UCSRB_UCSZ2 | UCSRB_RXEN | UCSRB_TXEN;
const UCSRC_UMSEL1 = 0x80; // USART Mode Select 1
const UCSRC_UMSEL0 = 0x40; // USART Mode Select 0
const UCSRC_UPM1 = 0x20; // Parity Mode 1
@@ -76,6 +79,7 @@ export class AVRUSART {
public onByteTransmit: USARTTransmitCallback | null = null;
public onLineTransmit: USARTLineTransmitCallback | null = null;
public onRxComplete: (() => void) | null = null;
+ public onConfigurationChange: USARTConfigurationChangeCallback | null = null;
private rxBusyValue = false;
private rxByte = 0;
@@ -107,9 +111,12 @@ export class AVRUSART {
constructor(private cpu: CPU, private config: USARTConfig, private freqHz: number) {
this.reset();
- this.cpu.writeHooks[config.UCSRA] = (value) => {
+ this.cpu.writeHooks[config.UCSRA] = (value, oldValue) => {
cpu.data[config.UCSRA] = value & (UCSRA_MPCM | UCSRA_U2X);
cpu.clearInterruptByFlag(this.TXC, value);
+ if ((value & UCSRA_CFG_MASK) !== (oldValue & UCSRA_CFG_MASK)) {
+ this.onConfigurationChange?.();
+ }
return true;
};
this.cpu.writeHooks[config.UCSRB] = (value, oldValue) => {
@@ -123,6 +130,16 @@ export class AVRUSART {
// Enabling the transmission - mark UDR as empty
cpu.setInterruptFlag(this.UDRE);
}
+ cpu.data[config.UCSRB] = value;
+ if ((value & UCSRB_CFG_MASK) !== (oldValue & UCSRB_CFG_MASK)) {
+ this.onConfigurationChange?.();
+ }
+ return true;
+ };
+ this.cpu.writeHooks[config.UCSRC] = (value) => {
+ cpu.data[config.UCSRC] = value;
+ this.onConfigurationChange?.();
+ return true;
};
this.cpu.readHooks[config.UDR] = () => {
const mask = rxMasks[this.bitsPerChar] ?? 0xff;
@@ -151,6 +168,16 @@ export class AVRUSART {
this.cpu.clearInterrupt(this.TXC);
this.cpu.clearInterrupt(this.UDRE);
};
+ this.cpu.writeHooks[config.UBRRH] = (value) => {
+ this.cpu.data[config.UBRRH] = value;
+ this.onConfigurationChange?.();
+ return true;
+ };
+ this.cpu.writeHooks[config.UBRRL] = (value) => {
+ this.cpu.data[config.UBRRL] = value;
+ this.onConfigurationChange?.();
+ return true;
+ };
}
reset() {
@@ -187,13 +214,22 @@ export class AVRUSART {
}
private get UBRR() {
- return (this.cpu.data[this.config.UBRRH] << 8) | this.cpu.data[this.config.UBRRL];
+ const { UBRRH, UBRRL } = this.config;
+ return (this.cpu.data[UBRRH] << 8) | this.cpu.data[UBRRL];
}
private get multiplier() {
return this.cpu.data[this.config.UCSRA] & UCSRA_U2X ? 8 : 16;
}
+ get rxEnable() {
+ return !!(this.cpu.data[this.config.UCSRB] & UCSRB_RXEN);
+ }
+
+ get txEnable() {
+ return !!(this.cpu.data[this.config.UCSRB] & UCSRB_TXEN);
+ }
+
get baudRate() {
return Math.floor(this.freqHz / (this.multiplier * (1 + this.UBRR)));
}