3
3
* Part of AVR8js
4
4
* Reference: http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
5
5
*
6
- * Copyright (C) 2019, 2020, Uri Shaked
6
+ * Copyright (C) 2019, 2020, 2021 Uri Shaked
7
7
*/
8
8
9
9
import { AVRInterruptConfig , CPU } from '../cpu/cpu' ;
@@ -36,6 +36,7 @@ export const usart0Config: USARTConfig = {
36
36
37
37
export type USARTTransmitCallback = ( value : u8 ) => void ;
38
38
export type USARTLineTransmitCallback = ( value : string ) => void ;
39
+ export type USARTConfigurationChangeCallback = ( ) => void ;
39
40
40
41
/* eslint-disable @typescript-eslint/no-unused-vars */
41
42
// Register bits:
@@ -47,6 +48,7 @@ const UCSRA_DOR = 0x8; // Data OverRun
47
48
const UCSRA_UPE = 0x4 ; // USART Parity Error
48
49
const UCSRA_U2X = 0x2 ; // Double the USART Transmission Speed
49
50
const UCSRA_MPCM = 0x1 ; // Multi-processor Communication Mode
51
+ const UCSRA_CFG_MASK = UCSRA_U2X ;
50
52
const UCSRB_RXCIE = 0x80 ; // RX Complete Interrupt Enable
51
53
const UCSRB_TXCIE = 0x40 ; // TX Complete Interrupt Enable
52
54
const UCSRB_UDRIE = 0x20 ; // USART Data Register Empty Interrupt Enable
@@ -55,6 +57,7 @@ const UCSRB_TXEN = 0x8; // Transmitter Enable
55
57
const UCSRB_UCSZ2 = 0x4 ; // Character Size 2
56
58
const UCSRB_RXB8 = 0x2 ; // Receive Data Bit 8
57
59
const UCSRB_TXB8 = 0x1 ; // Transmit Data Bit 8
60
+ const UCSRB_CFG_MASK = UCSRB_UCSZ2 | UCSRB_RXEN | UCSRB_TXEN ;
58
61
const UCSRC_UMSEL1 = 0x80 ; // USART Mode Select 1
59
62
const UCSRC_UMSEL0 = 0x40 ; // USART Mode Select 0
60
63
const UCSRC_UPM1 = 0x20 ; // Parity Mode 1
@@ -76,6 +79,7 @@ export class AVRUSART {
76
79
public onByteTransmit : USARTTransmitCallback | null = null ;
77
80
public onLineTransmit : USARTLineTransmitCallback | null = null ;
78
81
public onRxComplete : ( ( ) => void ) | null = null ;
82
+ public onConfigurationChange : USARTConfigurationChangeCallback | null = null ;
79
83
80
84
private rxBusyValue = false ;
81
85
private rxByte = 0 ;
@@ -107,9 +111,12 @@ export class AVRUSART {
107
111
108
112
constructor ( private cpu : CPU , private config : USARTConfig , private freqHz : number ) {
109
113
this . reset ( ) ;
110
- this . cpu . writeHooks [ config . UCSRA ] = ( value ) => {
114
+ this . cpu . writeHooks [ config . UCSRA ] = ( value , oldValue ) => {
111
115
cpu . data [ config . UCSRA ] = value & ( UCSRA_MPCM | UCSRA_U2X ) ;
112
116
cpu . clearInterruptByFlag ( this . TXC , value ) ;
117
+ if ( ( value & UCSRA_CFG_MASK ) !== ( oldValue & UCSRA_CFG_MASK ) ) {
118
+ this . onConfigurationChange ?.( ) ;
119
+ }
113
120
return true ;
114
121
} ;
115
122
this . cpu . writeHooks [ config . UCSRB ] = ( value , oldValue ) => {
@@ -123,6 +130,16 @@ export class AVRUSART {
123
130
// Enabling the transmission - mark UDR as empty
124
131
cpu . setInterruptFlag ( this . UDRE ) ;
125
132
}
133
+ cpu . data [ config . UCSRB ] = value ;
134
+ if ( ( value & UCSRB_CFG_MASK ) !== ( oldValue & UCSRB_CFG_MASK ) ) {
135
+ this . onConfigurationChange ?.( ) ;
136
+ }
137
+ return true ;
138
+ } ;
139
+ this . cpu . writeHooks [ config . UCSRC ] = ( value ) => {
140
+ cpu . data [ config . UCSRC ] = value ;
141
+ this . onConfigurationChange ?.( ) ;
142
+ return true ;
126
143
} ;
127
144
this . cpu . readHooks [ config . UDR ] = ( ) => {
128
145
const mask = rxMasks [ this . bitsPerChar ] ?? 0xff ;
@@ -151,6 +168,16 @@ export class AVRUSART {
151
168
this . cpu . clearInterrupt ( this . TXC ) ;
152
169
this . cpu . clearInterrupt ( this . UDRE ) ;
153
170
} ;
171
+ this . cpu . writeHooks [ config . UBRRH ] = ( value ) => {
172
+ this . cpu . data [ config . UBRRH ] = value ;
173
+ this . onConfigurationChange ?.( ) ;
174
+ return true ;
175
+ } ;
176
+ this . cpu . writeHooks [ config . UBRRL ] = ( value ) => {
177
+ this . cpu . data [ config . UBRRL ] = value ;
178
+ this . onConfigurationChange ?.( ) ;
179
+ return true ;
180
+ } ;
154
181
}
155
182
156
183
reset ( ) {
@@ -187,13 +214,22 @@ export class AVRUSART {
187
214
}
188
215
189
216
private get UBRR ( ) {
190
- return ( this . cpu . data [ this . config . UBRRH ] << 8 ) | this . cpu . data [ this . config . UBRRL ] ;
217
+ const { UBRRH , UBRRL } = this . config ;
218
+ return ( this . cpu . data [ UBRRH ] << 8 ) | this . cpu . data [ UBRRL ] ;
191
219
}
192
220
193
221
private get multiplier ( ) {
194
222
return this . cpu . data [ this . config . UCSRA ] & UCSRA_U2X ? 8 : 16 ;
195
223
}
196
224
225
+ get rxEnable ( ) {
226
+ return ! ! ( this . cpu . data [ this . config . UCSRB ] & UCSRB_RXEN ) ;
227
+ }
228
+
229
+ get txEnable ( ) {
230
+ return ! ! ( this . cpu . data [ this . config . UCSRB ] & UCSRB_TXEN ) ;
231
+ }
232
+
197
233
get baudRate ( ) {
198
234
return Math . floor ( this . freqHz / ( this . multiplier * ( 1 + this . UBRR ) ) ) ;
199
235
}
0 commit comments