2121* SOFTWARE.
2222*/
2323
24- import { CmsisDAP , Proxy } from "../proxy" ;
24+ import { CmsisDAP , DAPProtocol , DEFAULT_CLOCK_FREQUENCY } from "../proxy" ;
25+ import { Transport } from "../transport" ;
2526import { DAPLinkFlash , DAPLinkSerial } from "./enums" ;
2627
2728/**
@@ -31,16 +32,20 @@ const DEFAULT_BAUDRATE = 9600;
3132/**
3233 * @hidden
3334 */
34- const DEFAULT_SERIAL_DELAY = 200 ;
35+ const DEFAULT_SERIAL_DELAY = 100 ;
3536/**
3637 * @hidden
3738 */
3839const DEFAULT_PAGE_SIZE = 62 ;
40+ /**
41+ * @hidden
42+ */
43+ const SERIAL_VENDOR_CODE = 131 ;
3944
4045/**
4146 * DAPLink Class
4247 */
43- export class DAPLink extends CmsisDAP implements Proxy {
48+ export class DAPLink extends CmsisDAP {
4449
4550 /**
4651 * Progress event
@@ -54,7 +59,45 @@ export class DAPLink extends CmsisDAP implements Proxy {
5459 */
5560 public static EVENT_SERIAL_DATA : string = "serial" ;
5661
57- private timer ?: any ;
62+ /**
63+ * @hidden
64+ */
65+ protected serialPolling = false ;
66+
67+ /**
68+ * @hidden
69+ */
70+ protected serialListeners = false ;
71+
72+ /**
73+ * DAPLink constructor
74+ * @param transport Debug transport to use
75+ * @param mode Debug mode to use
76+ * @param clockFrequency Communication clock frequency to use (default 10000000)
77+ */
78+ constructor ( transport : Transport , mode : DAPProtocol = DAPProtocol . DEFAULT , clockFrequency : number = DEFAULT_CLOCK_FREQUENCY ) {
79+ super ( transport , mode , clockFrequency ) ;
80+
81+ this . on ( "newListener" , async event => {
82+ if ( event === DAPLink . EVENT_SERIAL_DATA ) {
83+ const listenerCount = this . listenerCount ( event ) ;
84+
85+ if ( listenerCount === 0 ) {
86+ this . serialListeners = true ;
87+ }
88+ }
89+ } ) ;
90+
91+ this . on ( "removeListener" , event => {
92+ if ( event === DAPLink . EVENT_SERIAL_DATA ) {
93+ const listenerCount = this . listenerCount ( event ) ;
94+
95+ if ( listenerCount === 0 ) {
96+ this . serialListeners = false ;
97+ }
98+ }
99+ } ) ;
100+ }
58101
59102 /**
60103 * Detect if buffer contains text or binary data
@@ -146,51 +189,88 @@ export class DAPLink extends CmsisDAP implements Proxy {
146189 }
147190
148191 /**
149- * Start listening for serial data
150- * @param serialDelay The serial delay to use (defaults to 200)
192+ * Write serial data
193+ * @param data The data to write
194+ * @returns Promise
151195 */
152- public startSerialRead ( serialDelay : number = DEFAULT_SERIAL_DELAY ) {
153- this . stopSerialRead ( ) ;
154- this . timer = setInterval ( ( ) => {
155- return this . send ( DAPLinkSerial . READ )
156- . then ( serialData => {
157- if ( serialData . byteLength > 0 ) {
158- // check if there is any data returned from the device
159- // first byte contains the vendor code
160- // second byte contains the actual length of data read from the device
161- const dataLength = serialData . getUint8 ( 1 ) ;
162- if ( dataLength !== 0 ) {
163- const offset = 2 ;
164- const dataArray = serialData . buffer . slice ( offset , offset + dataLength ) ;
165- const numberArray = Array . prototype . slice . call ( new Uint8Array ( dataArray ) ) ;
166- const data = String . fromCharCode . apply ( null , numberArray ) ;
167- this . emit ( DAPLink . EVENT_SERIAL_DATA , data ) ;
168- }
169- }
170- } ) ;
171- } , serialDelay ) ;
196+ public serialWrite ( data : string ) : Promise < void > {
197+ const arrayData = data . split ( "" ) . map ( ( e : string ) => e . charCodeAt ( 0 ) ) ;
198+ arrayData . unshift ( arrayData . length ) ;
199+ return this . send ( DAPLinkSerial . WRITE , new Uint8Array ( arrayData ) . buffer )
200+ . then ( ( ) => undefined ) ;
172201 }
173202
174203 /**
175- * Stop listening for serial data
204+ * Read serial data
205+ * @returns Promise of any arrayBuffer read
176206 */
177- public stopSerialRead ( ) {
178- if ( this . timer ) {
179- clearInterval ( this . timer ) ;
180- this . timer = undefined ;
207+ public serialRead ( ) : Promise < ArrayBuffer | undefined > {
208+ return this . send ( DAPLinkSerial . READ )
209+ . then ( serialData => {
210+ // Check if there is any data returned from the device
211+ if ( serialData . byteLength === 0 ) {
212+ return undefined ;
213+ }
214+
215+ // First byte contains the vendor code
216+ if ( serialData . getUint8 ( 0 ) !== SERIAL_VENDOR_CODE ) {
217+ return undefined ;
218+ }
219+
220+ // Second byte contains the actual length of data read from the device
221+ const dataLength = serialData . getUint8 ( 1 ) ;
222+ if ( dataLength === 0 ) {
223+ return undefined ;
224+ }
225+
226+ const offset = 2 ;
227+ return serialData . buffer . slice ( offset , offset + dataLength ) ;
228+ } ) ;
229+ }
230+
231+ /**
232+ * Start listening for serial data
233+ * @param serialDelay The serial delay to use (default 100)
234+ * @param autoConnect whether to automatically connect to the target (default true)
235+ */
236+ public async startSerialRead ( serialDelay : number = DEFAULT_SERIAL_DELAY , autoConnect = true ) {
237+ this . serialPolling = true ;
238+
239+ while ( this . serialPolling ) {
240+
241+ // Don't read serial output unless we have event listeners
242+ if ( this . serialListeners ) {
243+
244+ // Remember connection state
245+ const connectedState = this . connected ;
246+
247+ if ( this . connected === false && autoConnect === true ) {
248+ await this . connect ( ) ;
249+ }
250+
251+ const serialData = await this . serialRead ( ) ;
252+
253+ // Put state back
254+ if ( connectedState === false && autoConnect === true ) {
255+ await this . disconnect ( ) ;
256+ }
257+
258+ if ( serialData !== undefined ) {
259+ const numberArray = Array . prototype . slice . call ( new Uint8Array ( serialData ) ) ;
260+ const data = String . fromCharCode . apply ( null , numberArray ) ;
261+ this . emit ( DAPLink . EVENT_SERIAL_DATA , data ) ;
262+ }
263+ }
264+
265+ await new Promise ( resolve => setTimeout ( ( ) => resolve ( ) , serialDelay ) ) ;
181266 }
182267 }
183268
184269 /**
185- * Write serial data
186- * @param data The data to write
187- * @returns Promise
270+ * Stop listening for serial data
188271 */
189- public serialWrite ( data : string ) : Promise < void > {
190- const arrayData = data . split ( "" ) . map ( ( e : string ) => e . charCodeAt ( 0 ) ) ;
191- arrayData . unshift ( arrayData . length ) ;
192- return this . send ( DAPLinkSerial . WRITE , new Uint8Array ( arrayData ) . buffer )
193- . then ( ( ) => undefined ) ;
272+ public stopSerialRead ( ) {
273+ this . serialPolling = false ;
194274 }
195275}
196276
0 commit comments