1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
/// Simple buidlers for MPSSE commands
use crate::command::{Command, CommandList, DataShiftOptions};

pub use crate::command::{
    BitDirection, ClockEdge, PinDirection, PinDirectionArray, PinRange, PinValue,
    PinValueArray,
};

/// Internal macro for repetitive builder methods
macro_rules! builder_funcs {
    () => {
        /// Same as commit, but more readable in a chain.
        pub fn then(self) -> Builder {
            self.commit()
        }

        /// Commit this command to the parent Builder, then get the entire command list as a byte sequence.
        pub fn build(self) -> Vec<u8> {
            self.commit().build()
        }
    };
}

/// Builder for MPSSE commands.
#[derive(Debug)]
pub struct Builder {
    commands: Vec<Command>,
}

impl Builder {
    /// Create a new command builder with.
    pub fn new() -> Self {
        Builder {
            commands: Vec::new(),
        }
    }

    /// Write bytes of data, one bit at a time, on a single pin.
    ///
    /// This will generate a Data Shifting Command with the appropriate bits set to
    /// write to TDO with the appropriate parameters
    ///
    /// * `data` - The data to write out.
    ///
    /// ```
    /// use mpsse::{Builder, ClockEdge, BitDirection};
    ///
    /// let commands = Builder::new()
    ///     .write_data(vec![0xD, 0xEC, 0xAF])
    ///     .with_clock_direction(ClockEdge::Rising)
    ///     .with_bit_direction(BitDirection::MsbFirst)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x10, 0x02, 0x00, 0xD, 0xEC, 0xAF])
    /// ```
    pub fn write_data(self, data: Vec<u8>) -> WriteBuilder {
        WriteBuilder {
            parent: self,
            data,
            clock_direction: ClockEdge::Rising,
            bit_direction: BitDirection::MsbFirst,
        }
    }

    /// Read bytes of data, one bit at a time, on a single pin.
    ///
    /// This will generate a Data Shifting Command with the appropriate bits set to
    /// read from TDI with the appropriate parameters
    ///
    /// * `length` - The number of bytes to read out.
    ///
    /// ```
    /// use mpsse::{Builder, ClockEdge, BitDirection};
    ///
    /// let commands = Builder::new()
    ///     .read_data(328)
    ///     .with_clock_direction(ClockEdge::Rising)
    ///     .with_bit_direction(BitDirection::MsbFirst)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x20, 0x47, 0x01])
    /// ```
    pub fn read_data(self, length: u16) -> ReadBuilder {
        ReadBuilder {
            parent: self,
            length,
            clock_direction: ClockEdge::Rising,
            bit_direction: BitDirection::MsbFirst,
        }
    }

    /// Set the pins of the interface directly to the given values, and configure their direction.
    ///
    /// This will generate a Set Data Bits command of the appropriate type
    ///
    /// * `range` - Set either the high or low byte to be set
    /// * `direction` - The direction to set the pins, as either inputs or outputs.
    /// * `value` - The value to set the pins to, high or low (only applies to output pins)
    ///
    /// ```
    /// use mpsse::{Builder, PinRange};
    ///
    /// let commands = Builder::new()
    ///     .set_pins(PinRange::Low, 0b00110100, 0b11001100)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x80, 0xCC, 0x34])
    /// ```
    pub fn set_pins<D, V>(self, range: PinRange, direction: D, value: V) -> SetPinsBuilder
    where
        D: Into<PinDirectionArray>,
        V: Into<PinValueArray>,
    {
        SetPinsBuilder {
            parent: self,
            range,
            direction: direction.into(),
            value: value.into(),
        }
    }

    /// Read the value of input pins of the interface directly.
    ///
    /// This will generate a Read Data Bits command of the appropriate type
    ///
    /// * `range` - Read either the high or low byte to be set
    ///
    /// ```
    /// use mpsse::{Builder, PinRange};
    ///
    /// let commands = Builder::new()
    ///     .read_pins(PinRange::High)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x83])
    /// ```
    pub fn read_pins(self, range: PinRange) -> ReadPinsBuilder {
        ReadPinsBuilder {
            parent: self,
            range,
        }
    }

    /// Set the clock frequency of the interface.
    ///
    /// This will calculate the closest clock divisor to acheive the given frequency and generate a
    /// Set Clock Divisor command
    ///
    /// * `frequency` - The *target* frequency to set the clock to in hz. *Note*: this is a target
    ///     frequency that may not be met due to MPSSE internals. If you need more definite control
    ///     over the clock speed, use `.set_divisor()` instead.
    ///
    /// ```
    /// use mpsse::Builder;
    ///
    /// let commands = Builder::new()
    ///     .set_frequency(1_000_000.0)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x86, 0x05, 0x00])
    /// ```
    pub fn set_frequency<F>(self, frequency: F) -> SetFrequencyBuilder
    where
        F: Into<f64>,
    {
        SetFrequencyBuilder {
            parent: self,
            frequency: frequency.into(),
        }
    }

    pub fn set_divisor(self, _divisor: u16) -> ! {
        todo!()
    }

    /// Wait for IO on pin 1.
    ///
    /// This will send a Set Clock Frequency command
    ///
    /// * `value` - Whether to wait for a High or Low state on the pin.
    ///
    /// ```
    /// use mpsse::{Builder, PinValue};
    ///
    /// let commands = Builder::new()
    ///     .wait_for_io(PinValue::High)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x88])
    /// ```
    pub fn wait_for_io(self, value: PinValue) -> WaitForIoBuilder {
        WaitForIoBuilder {
            parent: self,
            value,
        }
    }

    /// Build the current command list into a sequence of bytes.
    pub fn build(self) -> Vec<u8> {
        CommandList(self.commands).into()
    }
}

/// Build a Data Shifting Command set to read bytes.
#[derive(Debug)]
pub struct ReadBuilder {
    parent: Builder,
    length: u16,
    clock_direction: ClockEdge,
    bit_direction: BitDirection,
}

impl ReadBuilder {
    /// Set this command to read the bits on a specific edge of the clock.
    ///
    /// By default, the ReadBuilder will build the command with the clock direction set Rising (meaning read on the rising clock).
    ///
    /// ```
    /// use mpsse::{Builder, ClockEdge};
    ///
    /// let commands = Builder::new()
    ///     .read_data(1)
    ///     .with_clock_direction(ClockEdge::Rising)
    ///     .then()
    ///     .read_data(1)
    ///     .with_clock_direction(ClockEdge::Falling)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x20, 0x00, 0x00, 0x21, 0x00, 0x00])
    /// ```
    pub fn with_clock_direction(self, direction: ClockEdge) -> Self {
        ReadBuilder {
            clock_direction: direction,
            ..self
        }
    }

    /// Set this command to read the bits in a specific direction
    ///
    /// By default, the ReadBuilder will build the command with the bit direction set MsbFirst.
    ///
    /// ```
    /// use mpsse::{Builder, BitDirection};
    ///
    /// let commands = Builder::new()
    ///     .read_data(1)
    ///     .with_bit_direction(BitDirection::MsbFirst)
    ///     .then()
    ///     .read_data(1)
    ///     .with_bit_direction(BitDirection::LsbFirst)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x20, 0x00, 0x00, 0x28, 0x00, 0x00])
    /// ```
    pub fn with_bit_direction(self, direction: BitDirection) -> Self {
        ReadBuilder {
            bit_direction: direction,
            ..self
        }
    }

    /// Commit this command to the parent Builder.
    fn commit(mut self) -> Builder {
        self.parent.commands.push(Command::ReadDataShiftBytes {
            options: DataShiftOptions {
                clock_direction: self.clock_direction,
                bit_direction: self.bit_direction,
            },
            length: self.length,
        });

        self.parent
    }

    builder_funcs!();
}

/// Build a Data Shifting Command set to write bytes.
#[derive(Debug)]
pub struct WriteBuilder {
    parent: Builder,
    data: Vec<u8>,
    clock_direction: ClockEdge,
    bit_direction: BitDirection,
}

impl WriteBuilder {
    /// Set this command to write the bits on a specific clock edge.
    ///
    /// By default, the WriteBuilder will build the command with the clock direction set Rising (meaning read on the rising clock).
    ///
    /// ```
    /// use mpsse::{Builder, ClockEdge};
    ///
    /// let commands = Builder::new()
    ///     .write_data(vec![0x01])
    ///     .with_clock_direction(ClockEdge::Rising)
    ///     .then()
    ///     .write_data(vec![0x01])
    ///     .with_clock_direction(ClockEdge::Falling)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x10, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01])
    /// ```
    pub fn with_clock_direction(self, direction: ClockEdge) -> Self {
        WriteBuilder {
            clock_direction: direction,
            ..self
        }
    }

    /// Set this command to write the bits in a specific direction
    ///
    /// By default, the WriteBuilder will build the command with the bit direction set MsbFirst.
    ///
    /// ```
    /// use mpsse::{Builder, BitDirection};
    ///
    /// let commands = Builder::new()
    ///     .write_data(vec![0x01])
    ///     .with_bit_direction(BitDirection::MsbFirst)
    ///     .then()
    ///     .write_data(vec![0x01])
    ///     .with_bit_direction(BitDirection::LsbFirst)
    ///     .build();
    ///
    /// assert_eq!(commands, vec![0x10, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01])
    /// ```
    pub fn with_bit_direction(self, direction: BitDirection) -> Self {
        WriteBuilder {
            bit_direction: direction,
            ..self
        }
    }

    /// Commit this command to the parent Builder.
    fn commit(mut self) -> Builder {
        self.parent.commands.push(Command::WriteDataShiftBytes {
            options: DataShiftOptions {
                clock_direction: self.clock_direction,
                bit_direction: self.bit_direction,
            },
            bytes: self.data,
        });

        self.parent
    }

    builder_funcs!();
}


/// Build a Set Pins command
#[derive(Debug)]
pub struct SetPinsBuilder {
    parent: Builder,
    range: PinRange,
    direction: PinDirectionArray,
    value: PinValueArray,
}

impl SetPinsBuilder {
    /// Commit this command to the parent Builder.
    fn commit(mut self) -> Builder {
        self.parent.commands.push(Command::SetBits {
            range: self.range,
            value: self.value,
            direction: self.direction,
        });

        self.parent
    }

    builder_funcs!();
}

/// Build a Set Divisor command using the given frequency.
#[derive(Debug)]
pub struct SetFrequencyBuilder {
    parent: Builder,
    frequency: f64,
}

impl SetFrequencyBuilder {
    /// Commit this command to the parent Builder.
    fn commit(mut self) -> Builder {
        self.parent.commands.push(Command::SetClockDivisor {
            divisor: (6_000_000f64 / self.frequency - 0.5).floor() as u16,
        });

        self.parent
    }

    builder_funcs!();
}

#[derive(Debug)]
pub struct WaitForIoBuilder {
    parent: Builder,
    value: PinValue,
}

impl WaitForIoBuilder {
    /// Commit this command to the parent Builder.
    fn commit(mut self) -> Builder {
        self.parent
            .commands
            .push(Command::WaitForIo { value: self.value });

        self.parent
    }

    builder_funcs!();
}

#[derive(Debug)]
pub struct ReadPinsBuilder {
    parent: Builder,
    range: PinRange,
}

impl ReadPinsBuilder {
    /// Commit this command to the parent Builder.
    fn commit(mut self) -> Builder {
        self.parent
            .commands
            .push(Command::ReadBits { range: self.range });

        self.parent
    }

    builder_funcs!();
}

#[cfg(test)]
mod write_builder_tests {
    use super::*;

    #[test]
    fn syntax_test() {
        let data = vec![0x10, 0x01, 0x20, 0x01];

        let commands = Builder::new()
            .write_data(data)
            .with_clock_direction(ClockEdge::Rising)
            .with_bit_direction(BitDirection::MsbFirst)
            .build();

        let command_bytes: Vec<u8> = commands.into_iter().collect();

        assert_eq!(
            command_bytes,
            vec![0x10, 0x03, 0x00, 0x10, 0x01, 0x20, 0x01]
        );
    }
}

#[cfg(test)]
mod read_builder_tests {
    use super::*;

    #[test]
    fn syntax_test() {
        let commands = Builder::new()
            .read_data(15)
            .with_clock_direction(ClockEdge::Rising)
            .with_bit_direction(BitDirection::MsbFirst)
            .build();

        let command_bytes: Vec<u8> = commands.into_iter().collect();

        assert_eq!(command_bytes, vec![0x20, 0x0e, 0x00]);
    }
}

#[cfg(test)]
mod set_freq_tests {
    use super::*;

    #[test]
    fn syntax_test() {
        let commands = Builder::new().set_frequency(5000.0).build();

        let command_bytes: Vec<u8> = commands.into_iter().collect();

        assert_eq!(command_bytes, vec![0x86, 0xAF, 0x04]);
    }
}