Skip to content

Python frontend

ADS1299

A class representing the ADS1299 driver.

Parameters:

Name Type Description Default
port str

The serial port to communicate with the ADS1299.

required
baudrate int

The baud rate for serial communication. Defaults to 115200.

115200

Attributes:

Name Type Description
channels list

A list of available channels.

gains list

A list of available gains.

input_modes list

A list of available input modes.

test_signal_conf dict

A dictionary containing the configuration for the test signal.

Source code in eeg_acquisition\ADS1299driver.py
 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
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
class ADS1299:
    """
    A class representing the ADS1299 driver.

    Args:
        port (str): The serial port to communicate with the ADS1299.
        baudrate (int, optional): The baud rate for serial communication.
            Defaults to 115200.

    Attributes:
        channels (list): A list of available channels.
        gains (list): A list of available gains.
        input_modes (list): A list of available input modes.
        test_signal_conf (dict): A dictionary containing the configuration for
            the test signal.
    """

    delay = 0.1  # Delay between commands in seconds
    verbose_header = "ADS1299: "

    valid_channels = [1, 2, 3, 4, 5, 6, 7, 8]
    valid_gains = [0, 1, 2, 4, 6, 8, 12, 24]  # 0 means PGA is bypassed
    valid_data_rates = {
        16000: "0",
        8000: "1",
        4000: "2",
        2000: "3",
        1000: "4",
        500: "5",
        250: "6",
    }
    valid_input_modes = ["normal", "shorted", "test"]
    references = ["SRB1", "SRB2"]
    valid_test_signal_conf = {
        "amplitude": ["1", "2"],
        "frequency": ["slow", "fast", "dc"],
    }

    enabled_channels = [True for _ in range(8)]
    gains = np.ones(8) * 24
    data_rate = 250
    modes = ["shorted" for _ in range(8)]

    NBITS = 24
    VREF = 4.5

    def __init__(self, port, baudrate=115200):
        """
        Initializes the ADS1299driver object.

        Args:
            port (str): The serial port to connect to.
            baudrate (int, optional): The baud rate for the serial communication.
                Defaults to 115200.
        """
        self.ser = serial.Serial(port, baudrate, timeout=1)
        self.ser.flushInput()
        self.ser.flushOutput()

        self.verbosity(True)

    def verbosity(self, value):
        """
        Sets the verbose mode for the ADS1299.

        Args:
            value (bool): True to enable verbose mode, False to disable it.
        """
        if value is True:
            self.ser.write("v1\n".encode())
            self.verbose = True
        else:
            self.ser.write("v0\n".encode())
            self.verbose = False

        if self.verbose:
            print(self.verbose_header + self.read_line())

    def read_line(self) -> str:
        """
        Reads a line from the serial port.

        Returns:
            str: The line read from the serial port.
        """
        return self.ser.readline().decode().strip()

    def set_gain(self, channel, gain):
        """
        Sets the gain for a specific channel.

        Args:
            channel (int): The channel number.
            gain (int): The gain value.

        Raises:
            AssertionError: If the channel or gain is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_gain(1, 24)
            ```
        """
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
        assert gain in self.valid_gains, "Invalid gain. Available gains: {}".format(
            self.valid_gains
        )
        self.ser.write("g{}{:02d}\n".format(channel, gain).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

        if gain == 0:
            self.gains[channel - 1] = 1
        else:
            self.gains[channel - 1] = gain

    def set_gain_for_all(self, gain):
        """
        Sets the gain for all channels.

        Args:
            gain (int): The gain value.

        Raises:
            AssertionError: If the gain is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_gain_for_all(24)
            ```
        """
        assert gain in self.valid_gains, "Invalid gain. Available gains: {}".format(
            self.valid_gains
        )
        for channel in self.valid_channels:
            self.set_gain(channel, gain)

    def set_data_rate(self, data_rate):
        """
        Sets the data rate for the ADS1299.

        Args:
            data_rate (int): The data rate in Hz.

        Raises:
            AssertionError: If the data rate is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_data_rate(1000)
            ```
        """
        assert data_rate in self.valid_data_rates.keys(), (
            "Invalid data rate. Available rates: {}".format(
                self.valid_data_rates.keys()
            )
        )
        self.ser.write("f{}\n".format(self.valid_data_rates[data_rate]).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

        self.data_rate = data_rate

    def set_input_mode(self, channel, mode):
        """
        Sets the input mode for a specific channel.

        Args:
            channel (int): The channel number.
            mode (str): The input mode.

        Raises:
            AssertionError: If the channel or mode is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_input_mode(1, 'normal')
            >>> ads.set_input_mode(2, 'shorted')
            >>> ads.set_input_mode(3, 'test')
            ```
        """
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
        assert mode in self.valid_input_modes, (
            "Invalid input mode. Available modes: {}".format(self.valid_input_modes)
        )
        self.ser.write("i{}{}\n".format(channel, mode[0]).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

        self.modes[channel - 1] = mode

    def set_input_mode_for_all(self, mode):
        """
        Sets the input mode for all channels.

        Args:
            mode (str): The input mode.

        Raises:
            AssertionError: If the mode is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_input_mode_for_all('normal')
            ```
        """
        assert mode in self.valid_input_modes, (
            "Invalid input mode. Available modes: {}".format(self.valid_input_modes)
        )
        for channel in self.valid_channels:
            self.set_input_mode(channel, mode)

    def set_bias(self, mode):
        """
        Enables or disables the bias for the ADS1299.

        Args:
            mode (bool): True to enable the bias, False to disable it.

        Raises:
            AssertionError: If the mode is not a boolean.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_bias(True)
            ```
        """
        assert isinstance(mode, bool), "Invalid mode. Mode must be a boolean."

        self.ser.write("be{}\n".format(int(mode)).encode())

        if self.verbose:
            print(self.verbose_header + self.read_line())

    def set_biasrefint(self, mode):
        """
        Enables or disables the internal bias reference for the ADS1299.

        Args:
            mode (bool): True to enable the internal bias reference, False to
                disable it.

        Raises:
            AssertionError: If the mode is not a boolean.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_biasrefint(True)
            ```
        """
        assert isinstance(mode, bool), "Invalid mode. Mode must be a boolean."

        if mode:
            self.ser.write("bri\n".encode())  # Enable internal bias reference
        else:
            self.ser.write(
                "bre\n".encode()
            )  # Disable internal bias reference, use external

        if self.verbose:
            print(self.verbose_header + self.read_line())

    def set_channel_bias_connections(self, channel, positive, negative):
        """
        Sets the connections of the desired channel to the input of bias drive.

        Args:
            channel (int): The channel number.
            positive (bool): True to connect the positive input to the bias drive.
            negative (bool): True to connect the negative input to the bias drive.

        Raises:
            AssertionError: If the channel is invalid or if positive/negative is
                not a boolean.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_channel_bias_connections(1, True, False)
            >>> ads.set_channel_bias_connections(2, False, True)
            ```
        """
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
        assert isinstance(positive, bool), (
            "Invalid positive mode. Mode must be a boolean."
        )
        assert isinstance(negative, bool), (
            "Invalid negative mode. Mode must be a boolean."
        )

        if positive:
            self.ser.write("bpe{}\n".format(channel).encode())
        else:
            self.ser.write("bpd{}\n".format(channel).encode())
        if self.verbose:
            print(self.verbose_header + self.read_line())

        if negative:
            self.ser.write("bne{}\n".format(channel).encode())
        else:
            self.ser.write("bnd{}\n".format(channel).encode())
        if self.verbose:
            print(self.verbose_header + self.read_line())

    def set_channel_bias_connections_for_all(self, positive, negative):
        """
        Sets the connections of all channels to the input of bias drive.

        Args:
            positive (bool): True to connect the positive inputs to the bias drive.
            negative (bool): True to connect the negative inputs to the bias drive.

        Raises:
            AssertionError: If positive/negative is not a boolean.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_channel_bias_connections_for_all(True, False)
            ```
        """
        for channel in self.valid_channels:
            self.set_channel_bias_connections(channel, positive, negative)

    def bias_measure(self, connect, channel=None):
        """
        Connects the bias to a channel to be measured or disconnects the bias
        measurement.

        Args:
            connect (bool): True to enable bias measurement, False to disable it.
            channel (int, optional): The channel number. Required if connect is True.

        Raises:
            AssertionError: If connect is not a boolean or if the channel is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.bias_measure(True, 1)
            ```
        """
        assert isinstance(connect, bool), (
            "Invalid connect mode. Mode must be a boolean."
        )

        if connect:
            assert channel in self.valid_channels, (
                "Invalid channel. Available channels: {}".format(self.valid_channels)
            )
            self.ser.write("bme{}\n".format(channel).encode())
        else:
            self.ser.write("bmd0\n".encode())

        if self.verbose:
            print(self.verbose_header + self.read_line())

    def set_reference(self, reference, mode, channel=None):
        """
        Sets the references for the ADS1299.

        Args:
            reference (str): The reference to set. Must be 'SRB1' or 'SRB2'.
            mode (bool): True to enable the reference, False to disable it.
            channel (int, optional): The channel number. Required for 'SRB2'.

        Raises:
            AssertionError: If the reference or channel is invalid, or if mode
                is not a boolean.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.set_reference('SRB1', True)
            ```
        """
        assert reference in self.references, (
            "Invalid reference. Available references: {}".format(self.references)
        )
        assert isinstance(mode, bool), "Invalid mode. Mode must be a boolean."

        if reference == "SRB2":
            assert channel in self.valid_channels, (
                "Invalid channel. Available channels: {}".format(self.valid_channels)
            )
        else:
            channel = 0

        self.ser.write("r{}{}{}\n".format(reference[-1], int(mode), channel).encode())

        if self.verbose:
            print(self.verbose_header + self.read_line())

    def enable_channel(self, channel):
        """
        Enables a specific channel.

        Args:
            channel (int): The channel number.

        Raises:
            AssertionError: If the channel is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.enable_channel(1)
            ```
        """
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
        self.ser.write("e{}\n".format(channel).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

        self.enabled_channels[channel - 1] = True

    def enable_all_channels(self):
        """
        Enables all channels.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.enable_all_channels()
            ```
        """
        for channel in self.valid_channels:
            self.enable_channel(channel)

    def disable_channel(self, channel):
        """
        Disables a specific channel.

        Args:
            channel (int): The channel number.

        Raises:
            AssertionError: If the channel is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.disable_channel(1)
            ```
        """
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
        self.ser.write("d{}\n".format(channel).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

        self.enabled_channels[channel - 1] = False

    def disable_all_channels(self):
        """
        Disables all channels.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.disable_all_channels()
            ```
        """
        for channel in self.valid_channels:
            self.disable_channel(channel)

    def rdatac(self):
        """
        Enables Read Data Continuous mode in the ADS1299.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.rdatac()
            ```
        """
        self.ser.write("z\n".encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

    def sdatac(self):
        """
        Disables Read Data Continuous mode in the ADS1299.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.sdatac()
            ```
        """
        self.ser.write("x\n".encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

    def start_streaming(self):
        """
        Starts streaming data from the ADS1299.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.start_streaming()
            ```
        """
        self.ser.write("a\n".encode())

    def stop_streaming(self):
        """
        Stops the stream of data from the ADS1299.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.stop_streaming()
            ```
        """
        self.ser.write("s\n".encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

    def single_shot_mode(self, enable: bool):
        """
        Enables or disables single-shot mode.

        Args:
            enable (bool): True to enable single-shot mode, False to disable it.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.single_shot_mode(True)
            ```
        """
        assert isinstance(enable, bool), "Invalid argument. Mode must be a boolean."
        self.ser.write("k{}\n".format(int(enable)).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

    def single_read(self) -> np.ndarray:
        """
        Starts a single conversion and reads the data from the ADS1299.

        Returns:
            np.ndarray: A list of data read from the ADS1299.

        Raises:
            TaskAbortedError: If the read operation takes more than its timeout.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> data = ads.single_read()
                [123, 456, 789, ...]
            ```
        """
        self.ser.write("u\n".encode())
        return self.read_ASCII_data()

    def set_batch_read(self, n_samples: int) -> None:
        """
        Sets a read of N samples from the ADS1299.

        Args:
            n_samples (int): The number of samples to read.

        Raises:
            TaskAbortedError: If the read operation takes more than its timeout.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> data = ads.set_batch_read(10)
            ```
        """
        self.batch_size = n_samples
        self.ser.write("n{}\n".format(n_samples).encode())

    def get_batch_read(self) -> np.ndarray:
        """
        Gets the batch data from the ADS1299.

        Returns:
            np.ndarray: A numpy array of data read from the ADS1299.

        Raises:
            TaskAbortedError: If the operation takes more than its timeout.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> data = ads.get_batch_read()
                [[123, 456, 789, ...], [123, 456, 789, ...], ...]
            ```
        """
        if self.batch_size is None:
            raise ValueError("Batch size not set. Call read_batch() first.")

        data = []

        self.ser.flush()

        self.ser.write("m\n".encode())

        for i in range(self.batch_size):
            data.append(self.read_ASCII_data())

        data = np.array(data).T

        self.batch_size = None  # Reset batch size after reading

        return data

    def close(self):
        """
        Closes the serial connection.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.close()
            ```
        """
        self.ser.close()

    @timecapped_to(1)
    def read_ASCII_data(self, normalized=True) -> np.array:
        """
        Reads data from the ADS1299.

        Args:
            normalized (bool): True to normalize the data, False to return raw data.

        Returns:
            np.array: A numpy array of data read from the ADS1299.

        Raises:
            TaskAbortedError: If the operation takes more than its timeout.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> data = ads.read_ASCII_data(True)
                [0.123, 0.456, 0.789, ...]
            ```
        """
        data = self.ser.readline().decode().strip()
        data = data.split(",")[:-1]
        # data = [int(d) for d in data]
        data = np.array(data, dtype=int)

        if normalized:
            data = self._norm(data)

        return data

    def test_signal(self, amplitude, frequency):
        """
        Configures the test signal to the ADS1299.

        Args:
            amplitude (str): The amplitude of the test signal.
            frequency (str): The frequency of the test signal.

        Raises:
            AssertionError: If the amplitude or frequency is invalid.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.test_signal('1', 'fast')
            ```
        """
        assert amplitude in self.valid_test_signal_conf["amplitude"], (
            "Invalid amplitude. Available amplitudes: {}".format(
                self.valid_test_signal_conf["amplitude"]
            )
        )
        assert frequency in self.valid_test_signal_conf["frequency"], (
            "Invalid frequency. Available frequencies: {}".format(
                self.valid_test_signal_conf["frequency"]
            )
        )
        self.ser.write("t{}{}\n".format(amplitude, frequency[0]).encode())
        sleep(self.delay)
        if self.verbose:
            print(self.verbose_header + self.read_line())

    def log_data(self, filename, duration=10):
        """
        Logs data from the ADS1299 to a file.

        Args:
            filename (str): The name of the file to log the data to.
            duration (int, optional): The duration of the logging in seconds.
                Defaults to 10. If set to -1, the logging will continue
                indefinitely.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.log_data('data_log.txt', 10)
            ```
        """
        from time import strftime, time

        f = open(filename, "w")
        f.write("ADS1299 data log @ {}\n".format(strftime("%Y-%m-%d %H:%M:%S")))

        start_time = time()
        while time() - start_time < duration or duration == -1:
            try:
                data = self.read_ASCII_data(True)
            except TaskAbortedError:
                print("Read operation timed out.")
                break
            f.write(", ".join([str(d) for d in data]) + "\n")
            f.flush()  # Flush the buffer to write to the file

        f.close()

    def print_all_registers(self):
        """
        Prints all registers from the ADS1299.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.print_all_registers()
            ID, 0x00, 0x3E, 0, 0, 1, 1, 1, 1, 1, 0
            CONFIG1, 0x01, 0x96, 1, 0, 0, 1, 0, 1, 1, 0
            CONFIG2, 0x02, 0xC0, 1, 1, 0, 0, 0, 0, 0, 0
            CONFIG3, 0x03, 0xE0, 1, 1, 1, 0, 0, 0, 0, 0
            LOFF, 0x04, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            CH1SET, 0x05, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH2SET, 0x06, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH3SET, 0x07, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH4SET, 0x08, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH5SET, 0x09, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH6SET, 0x0A, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH7SET, 0x0B, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            CH8SET, 0x0C, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
            BIAS_SENSP, 0x0D, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            BIAS_SENSN, 0x0E, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            LOFF_SENSP, 0x0F, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            LOFF_SENSN, 0x10, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            LOFF_FLIP, 0x11, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            LOFF_STATP, 0x12, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            LOFF_STATN, 0x13, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            GPIO, 0x14, 0x0F, 0, 0, 0, 0, 1, 1, 1, 1
            MISC1, 0x15, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            MISC2, 0x16, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            CONFIG4, 0x17, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
            ```
        """
        N_REGISTERS = 0x18
        self.ser.write("?\n".encode())
        for i in range(N_REGISTERS):
            print(self.read_line())

    def _norm(self, data):
        """
        Normalizes the data read from the ADS1299, converting it to volts.

        Args:
            data (np.array): The integer values read from the ADS1299.

        Returns:
            np.array: The normalized data in volts.
        """
        norm_data = data / (2 ** (self.NBITS - 1) - 1) * self.VREF / self.gains

        return norm_data

    def live_plot(self, buffer_width=1000):
        """
        Creates a live plot of the 8 channels' data over the last `width` seconds.

        Args:
            buffer_width (int): The time window to display in the plot.

        Example:
            ```python
            >>> ads = ADS1299('COM8')
            >>> ads.live_plot()
            ```
        """

        import pyqtgraph as pg


        app = pg.mkQApp("Plotting Example")

        win = pg.GraphicsLayoutWidget(show=True, title="EEG acquisition - ADS1299")
        win.resize(1000,600)
        win.setWindowTitle("ADS1299 - EEG acquisition")

        pg.setConfigOptions(antialias=True)

        p = []
        curve = []
        for i in range(len(self.valid_channels)):
            p.append(win.addPlot())
            p[i].setLabel('left', 'Chan{}'.format(i), units='V')
            # Remove labels and ticks in x axis
            p[i].setLabel('bottom', '')
            p[i].getAxis('bottom').setTicks([])
            curve.append(p[i].plot())
            win.nextRow()

        ADC_values = np.zeros((len(self.valid_channels), buffer_width))

        def update():
            ADC_values[:,:-1] = ADC_values[:, 1:]
            data = ads.single_read()[:len(self.valid_channels)]
            ADC_values[:,-1] =  data
            for i in range(len(self.valid_channels)):
                curve[i].setData(ADC_values[i,:])

            app.processEvents()

        try:
            while True:
                update()
        except KeyboardInterrupt:
            pass

__init__(port, baudrate=115200)

Initializes the ADS1299driver object.

Parameters:

Name Type Description Default
port str

The serial port to connect to.

required
baudrate int

The baud rate for the serial communication. Defaults to 115200.

115200
Source code in eeg_acquisition\ADS1299driver.py
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def __init__(self, port, baudrate=115200):
    """
    Initializes the ADS1299driver object.

    Args:
        port (str): The serial port to connect to.
        baudrate (int, optional): The baud rate for the serial communication.
            Defaults to 115200.
    """
    self.ser = serial.Serial(port, baudrate, timeout=1)
    self.ser.flushInput()
    self.ser.flushOutput()

    self.verbosity(True)

bias_measure(connect, channel=None)

Connects the bias to a channel to be measured or disconnects the bias measurement.

Parameters:

Name Type Description Default
connect bool

True to enable bias measurement, False to disable it.

required
channel int

The channel number. Required if connect is True.

None

Raises:

Type Description
AssertionError

If connect is not a boolean or if the channel is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.bias_measure(True, 1)
Source code in eeg_acquisition\ADS1299driver.py
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
def bias_measure(self, connect, channel=None):
    """
    Connects the bias to a channel to be measured or disconnects the bias
    measurement.

    Args:
        connect (bool): True to enable bias measurement, False to disable it.
        channel (int, optional): The channel number. Required if connect is True.

    Raises:
        AssertionError: If connect is not a boolean or if the channel is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.bias_measure(True, 1)
        ```
    """
    assert isinstance(connect, bool), (
        "Invalid connect mode. Mode must be a boolean."
    )

    if connect:
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
        self.ser.write("bme{}\n".format(channel).encode())
    else:
        self.ser.write("bmd0\n".encode())

    if self.verbose:
        print(self.verbose_header + self.read_line())

close()

Closes the serial connection.

Example
>>> ads = ADS1299('COM8')
>>> ads.close()
Source code in eeg_acquisition\ADS1299driver.py
662
663
664
665
666
667
668
669
670
671
672
def close(self):
    """
    Closes the serial connection.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.close()
        ```
    """
    self.ser.close()

disable_all_channels()

Disables all channels.

Example
>>> ads = ADS1299('COM8')
>>> ads.disable_all_channels()
Source code in eeg_acquisition\ADS1299driver.py
499
500
501
502
503
504
505
506
507
508
509
510
def disable_all_channels(self):
    """
    Disables all channels.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.disable_all_channels()
        ```
    """
    for channel in self.valid_channels:
        self.disable_channel(channel)

disable_channel(channel)

Disables a specific channel.

Parameters:

Name Type Description Default
channel int

The channel number.

required

Raises:

Type Description
AssertionError

If the channel is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.disable_channel(1)
Source code in eeg_acquisition\ADS1299driver.py
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
def disable_channel(self, channel):
    """
    Disables a specific channel.

    Args:
        channel (int): The channel number.

    Raises:
        AssertionError: If the channel is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.disable_channel(1)
        ```
    """
    assert channel in self.valid_channels, (
        "Invalid channel. Available channels: {}".format(self.valid_channels)
    )
    self.ser.write("d{}\n".format(channel).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

    self.enabled_channels[channel - 1] = False

enable_all_channels()

Enables all channels.

Example
>>> ads = ADS1299('COM8')
>>> ads.enable_all_channels()
Source code in eeg_acquisition\ADS1299driver.py
460
461
462
463
464
465
466
467
468
469
470
471
def enable_all_channels(self):
    """
    Enables all channels.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.enable_all_channels()
        ```
    """
    for channel in self.valid_channels:
        self.enable_channel(channel)

enable_channel(channel)

Enables a specific channel.

Parameters:

Name Type Description Default
channel int

The channel number.

required

Raises:

Type Description
AssertionError

If the channel is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.enable_channel(1)
Source code in eeg_acquisition\ADS1299driver.py
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
def enable_channel(self, channel):
    """
    Enables a specific channel.

    Args:
        channel (int): The channel number.

    Raises:
        AssertionError: If the channel is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.enable_channel(1)
        ```
    """
    assert channel in self.valid_channels, (
        "Invalid channel. Available channels: {}".format(self.valid_channels)
    )
    self.ser.write("e{}\n".format(channel).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

    self.enabled_channels[channel - 1] = True

get_batch_read()

Gets the batch data from the ADS1299.

Returns:

Type Description
ndarray

np.ndarray: A numpy array of data read from the ADS1299.

Raises:

Type Description
TaskAbortedError

If the operation takes more than its timeout.

Example
>>> ads = ADS1299('COM8')
>>> data = ads.get_batch_read()
    [[123, 456, 789, ...], [123, 456, 789, ...], ...]
Source code in eeg_acquisition\ADS1299driver.py
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
def get_batch_read(self) -> np.ndarray:
    """
    Gets the batch data from the ADS1299.

    Returns:
        np.ndarray: A numpy array of data read from the ADS1299.

    Raises:
        TaskAbortedError: If the operation takes more than its timeout.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> data = ads.get_batch_read()
            [[123, 456, 789, ...], [123, 456, 789, ...], ...]
        ```
    """
    if self.batch_size is None:
        raise ValueError("Batch size not set. Call read_batch() first.")

    data = []

    self.ser.flush()

    self.ser.write("m\n".encode())

    for i in range(self.batch_size):
        data.append(self.read_ASCII_data())

    data = np.array(data).T

    self.batch_size = None  # Reset batch size after reading

    return data

live_plot(buffer_width=1000)

Creates a live plot of the 8 channels' data over the last width seconds.

Parameters:

Name Type Description Default
buffer_width int

The time window to display in the plot.

1000
Example
>>> ads = ADS1299('COM8')
>>> ads.live_plot()
Source code in eeg_acquisition\ADS1299driver.py
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
def live_plot(self, buffer_width=1000):
    """
    Creates a live plot of the 8 channels' data over the last `width` seconds.

    Args:
        buffer_width (int): The time window to display in the plot.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.live_plot()
        ```
    """

    import pyqtgraph as pg


    app = pg.mkQApp("Plotting Example")

    win = pg.GraphicsLayoutWidget(show=True, title="EEG acquisition - ADS1299")
    win.resize(1000,600)
    win.setWindowTitle("ADS1299 - EEG acquisition")

    pg.setConfigOptions(antialias=True)

    p = []
    curve = []
    for i in range(len(self.valid_channels)):
        p.append(win.addPlot())
        p[i].setLabel('left', 'Chan{}'.format(i), units='V')
        # Remove labels and ticks in x axis
        p[i].setLabel('bottom', '')
        p[i].getAxis('bottom').setTicks([])
        curve.append(p[i].plot())
        win.nextRow()

    ADC_values = np.zeros((len(self.valid_channels), buffer_width))

    def update():
        ADC_values[:,:-1] = ADC_values[:, 1:]
        data = ads.single_read()[:len(self.valid_channels)]
        ADC_values[:,-1] =  data
        for i in range(len(self.valid_channels)):
            curve[i].setData(ADC_values[i,:])

        app.processEvents()

    try:
        while True:
            update()
    except KeyboardInterrupt:
        pass

log_data(filename, duration=10)

Logs data from the ADS1299 to a file.

Parameters:

Name Type Description Default
filename str

The name of the file to log the data to.

required
duration int

The duration of the logging in seconds. Defaults to 10. If set to -1, the logging will continue indefinitely.

10
Example
>>> ads = ADS1299('COM8')
>>> ads.log_data('data_log.txt', 10)
Source code in eeg_acquisition\ADS1299driver.py
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
def log_data(self, filename, duration=10):
    """
    Logs data from the ADS1299 to a file.

    Args:
        filename (str): The name of the file to log the data to.
        duration (int, optional): The duration of the logging in seconds.
            Defaults to 10. If set to -1, the logging will continue
            indefinitely.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.log_data('data_log.txt', 10)
        ```
    """
    from time import strftime, time

    f = open(filename, "w")
    f.write("ADS1299 data log @ {}\n".format(strftime("%Y-%m-%d %H:%M:%S")))

    start_time = time()
    while time() - start_time < duration or duration == -1:
        try:
            data = self.read_ASCII_data(True)
        except TaskAbortedError:
            print("Read operation timed out.")
            break
        f.write(", ".join([str(d) for d in data]) + "\n")
        f.flush()  # Flush the buffer to write to the file

    f.close()

print_all_registers()

Prints all registers from the ADS1299.

Example
>>> ads = ADS1299('COM8')
>>> ads.print_all_registers()
ID, 0x00, 0x3E, 0, 0, 1, 1, 1, 1, 1, 0
CONFIG1, 0x01, 0x96, 1, 0, 0, 1, 0, 1, 1, 0
CONFIG2, 0x02, 0xC0, 1, 1, 0, 0, 0, 0, 0, 0
CONFIG3, 0x03, 0xE0, 1, 1, 1, 0, 0, 0, 0, 0
LOFF, 0x04, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
CH1SET, 0x05, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH2SET, 0x06, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH3SET, 0x07, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH4SET, 0x08, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH5SET, 0x09, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH6SET, 0x0A, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH7SET, 0x0B, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
CH8SET, 0x0C, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
BIAS_SENSP, 0x0D, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
BIAS_SENSN, 0x0E, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
LOFF_SENSP, 0x0F, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
LOFF_SENSN, 0x10, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
LOFF_FLIP, 0x11, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
LOFF_STATP, 0x12, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
LOFF_STATN, 0x13, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
GPIO, 0x14, 0x0F, 0, 0, 0, 0, 1, 1, 1, 1
MISC1, 0x15, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
MISC2, 0x16, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
CONFIG4, 0x17, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
Source code in eeg_acquisition\ADS1299driver.py
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
def print_all_registers(self):
    """
    Prints all registers from the ADS1299.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.print_all_registers()
        ID, 0x00, 0x3E, 0, 0, 1, 1, 1, 1, 1, 0
        CONFIG1, 0x01, 0x96, 1, 0, 0, 1, 0, 1, 1, 0
        CONFIG2, 0x02, 0xC0, 1, 1, 0, 0, 0, 0, 0, 0
        CONFIG3, 0x03, 0xE0, 1, 1, 1, 0, 0, 0, 0, 0
        LOFF, 0x04, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        CH1SET, 0x05, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH2SET, 0x06, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH3SET, 0x07, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH4SET, 0x08, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH5SET, 0x09, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH6SET, 0x0A, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH7SET, 0x0B, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        CH8SET, 0x0C, 0x61, 0, 1, 1, 0, 0, 0, 0, 1
        BIAS_SENSP, 0x0D, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        BIAS_SENSN, 0x0E, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        LOFF_SENSP, 0x0F, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        LOFF_SENSN, 0x10, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        LOFF_FLIP, 0x11, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        LOFF_STATP, 0x12, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        LOFF_STATN, 0x13, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        GPIO, 0x14, 0x0F, 0, 0, 0, 0, 1, 1, 1, 1
        MISC1, 0x15, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        MISC2, 0x16, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        CONFIG4, 0x17, 0x00, 0, 0, 0, 0, 0, 0, 0, 0
        ```
    """
    N_REGISTERS = 0x18
    self.ser.write("?\n".encode())
    for i in range(N_REGISTERS):
        print(self.read_line())

rdatac()

Enables Read Data Continuous mode in the ADS1299.

Example
>>> ads = ADS1299('COM8')
>>> ads.rdatac()
Source code in eeg_acquisition\ADS1299driver.py
512
513
514
515
516
517
518
519
520
521
522
523
524
525
def rdatac(self):
    """
    Enables Read Data Continuous mode in the ADS1299.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.rdatac()
        ```
    """
    self.ser.write("z\n".encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

read_ASCII_data(normalized=True)

Reads data from the ADS1299.

Parameters:

Name Type Description Default
normalized bool

True to normalize the data, False to return raw data.

True

Returns:

Type Description
array

np.array: A numpy array of data read from the ADS1299.

Raises:

Type Description
TaskAbortedError

If the operation takes more than its timeout.

Example
>>> ads = ADS1299('COM8')
>>> data = ads.read_ASCII_data(True)
    [0.123, 0.456, 0.789, ...]
Source code in eeg_acquisition\ADS1299driver.py
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
@timecapped_to(1)
def read_ASCII_data(self, normalized=True) -> np.array:
    """
    Reads data from the ADS1299.

    Args:
        normalized (bool): True to normalize the data, False to return raw data.

    Returns:
        np.array: A numpy array of data read from the ADS1299.

    Raises:
        TaskAbortedError: If the operation takes more than its timeout.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> data = ads.read_ASCII_data(True)
            [0.123, 0.456, 0.789, ...]
        ```
    """
    data = self.ser.readline().decode().strip()
    data = data.split(",")[:-1]
    # data = [int(d) for d in data]
    data = np.array(data, dtype=int)

    if normalized:
        data = self._norm(data)

    return data

read_line()

Reads a line from the serial port.

Returns:

Name Type Description
str str

The line read from the serial port.

Source code in eeg_acquisition\ADS1299driver.py
103
104
105
106
107
108
109
110
def read_line(self) -> str:
    """
    Reads a line from the serial port.

    Returns:
        str: The line read from the serial port.
    """
    return self.ser.readline().decode().strip()

sdatac()

Disables Read Data Continuous mode in the ADS1299.

Example
>>> ads = ADS1299('COM8')
>>> ads.sdatac()
Source code in eeg_acquisition\ADS1299driver.py
527
528
529
530
531
532
533
534
535
536
537
538
539
540
def sdatac(self):
    """
    Disables Read Data Continuous mode in the ADS1299.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.sdatac()
        ```
    """
    self.ser.write("x\n".encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

set_batch_read(n_samples)

Sets a read of N samples from the ADS1299.

Parameters:

Name Type Description Default
n_samples int

The number of samples to read.

required

Raises:

Type Description
TaskAbortedError

If the read operation takes more than its timeout.

Example
>>> ads = ADS1299('COM8')
>>> data = ads.set_batch_read(10)
Source code in eeg_acquisition\ADS1299driver.py
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
def set_batch_read(self, n_samples: int) -> None:
    """
    Sets a read of N samples from the ADS1299.

    Args:
        n_samples (int): The number of samples to read.

    Raises:
        TaskAbortedError: If the read operation takes more than its timeout.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> data = ads.set_batch_read(10)
        ```
    """
    self.batch_size = n_samples
    self.ser.write("n{}\n".format(n_samples).encode())

set_bias(mode)

Enables or disables the bias for the ADS1299.

Parameters:

Name Type Description Default
mode bool

True to enable the bias, False to disable it.

required

Raises:

Type Description
AssertionError

If the mode is not a boolean.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_bias(True)
Source code in eeg_acquisition\ADS1299driver.py
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
def set_bias(self, mode):
    """
    Enables or disables the bias for the ADS1299.

    Args:
        mode (bool): True to enable the bias, False to disable it.

    Raises:
        AssertionError: If the mode is not a boolean.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_bias(True)
        ```
    """
    assert isinstance(mode, bool), "Invalid mode. Mode must be a boolean."

    self.ser.write("be{}\n".format(int(mode)).encode())

    if self.verbose:
        print(self.verbose_header + self.read_line())

set_biasrefint(mode)

Enables or disables the internal bias reference for the ADS1299.

Parameters:

Name Type Description Default
mode bool

True to enable the internal bias reference, False to disable it.

required

Raises:

Type Description
AssertionError

If the mode is not a boolean.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_biasrefint(True)
Source code in eeg_acquisition\ADS1299driver.py
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
def set_biasrefint(self, mode):
    """
    Enables or disables the internal bias reference for the ADS1299.

    Args:
        mode (bool): True to enable the internal bias reference, False to
            disable it.

    Raises:
        AssertionError: If the mode is not a boolean.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_biasrefint(True)
        ```
    """
    assert isinstance(mode, bool), "Invalid mode. Mode must be a boolean."

    if mode:
        self.ser.write("bri\n".encode())  # Enable internal bias reference
    else:
        self.ser.write(
            "bre\n".encode()
        )  # Disable internal bias reference, use external

    if self.verbose:
        print(self.verbose_header + self.read_line())

set_channel_bias_connections(channel, positive, negative)

Sets the connections of the desired channel to the input of bias drive.

Parameters:

Name Type Description Default
channel int

The channel number.

required
positive bool

True to connect the positive input to the bias drive.

required
negative bool

True to connect the negative input to the bias drive.

required

Raises:

Type Description
AssertionError

If the channel is invalid or if positive/negative is not a boolean.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_channel_bias_connections(1, True, False)
>>> ads.set_channel_bias_connections(2, False, True)
Source code in eeg_acquisition\ADS1299driver.py
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
def set_channel_bias_connections(self, channel, positive, negative):
    """
    Sets the connections of the desired channel to the input of bias drive.

    Args:
        channel (int): The channel number.
        positive (bool): True to connect the positive input to the bias drive.
        negative (bool): True to connect the negative input to the bias drive.

    Raises:
        AssertionError: If the channel is invalid or if positive/negative is
            not a boolean.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_channel_bias_connections(1, True, False)
        >>> ads.set_channel_bias_connections(2, False, True)
        ```
    """
    assert channel in self.valid_channels, (
        "Invalid channel. Available channels: {}".format(self.valid_channels)
    )
    assert isinstance(positive, bool), (
        "Invalid positive mode. Mode must be a boolean."
    )
    assert isinstance(negative, bool), (
        "Invalid negative mode. Mode must be a boolean."
    )

    if positive:
        self.ser.write("bpe{}\n".format(channel).encode())
    else:
        self.ser.write("bpd{}\n".format(channel).encode())
    if self.verbose:
        print(self.verbose_header + self.read_line())

    if negative:
        self.ser.write("bne{}\n".format(channel).encode())
    else:
        self.ser.write("bnd{}\n".format(channel).encode())
    if self.verbose:
        print(self.verbose_header + self.read_line())

set_channel_bias_connections_for_all(positive, negative)

Sets the connections of all channels to the input of bias drive.

Parameters:

Name Type Description Default
positive bool

True to connect the positive inputs to the bias drive.

required
negative bool

True to connect the negative inputs to the bias drive.

required

Raises:

Type Description
AssertionError

If positive/negative is not a boolean.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_channel_bias_connections_for_all(True, False)
Source code in eeg_acquisition\ADS1299driver.py
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
def set_channel_bias_connections_for_all(self, positive, negative):
    """
    Sets the connections of all channels to the input of bias drive.

    Args:
        positive (bool): True to connect the positive inputs to the bias drive.
        negative (bool): True to connect the negative inputs to the bias drive.

    Raises:
        AssertionError: If positive/negative is not a boolean.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_channel_bias_connections_for_all(True, False)
        ```
    """
    for channel in self.valid_channels:
        self.set_channel_bias_connections(channel, positive, negative)

set_data_rate(data_rate)

Sets the data rate for the ADS1299.

Parameters:

Name Type Description Default
data_rate int

The data rate in Hz.

required

Raises:

Type Description
AssertionError

If the data rate is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_data_rate(1000)
Source code in eeg_acquisition\ADS1299driver.py
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
def set_data_rate(self, data_rate):
    """
    Sets the data rate for the ADS1299.

    Args:
        data_rate (int): The data rate in Hz.

    Raises:
        AssertionError: If the data rate is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_data_rate(1000)
        ```
    """
    assert data_rate in self.valid_data_rates.keys(), (
        "Invalid data rate. Available rates: {}".format(
            self.valid_data_rates.keys()
        )
    )
    self.ser.write("f{}\n".format(self.valid_data_rates[data_rate]).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

    self.data_rate = data_rate

set_gain(channel, gain)

Sets the gain for a specific channel.

Parameters:

Name Type Description Default
channel int

The channel number.

required
gain int

The gain value.

required

Raises:

Type Description
AssertionError

If the channel or gain is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_gain(1, 24)
Source code in eeg_acquisition\ADS1299driver.py
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
def set_gain(self, channel, gain):
    """
    Sets the gain for a specific channel.

    Args:
        channel (int): The channel number.
        gain (int): The gain value.

    Raises:
        AssertionError: If the channel or gain is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_gain(1, 24)
        ```
    """
    assert channel in self.valid_channels, (
        "Invalid channel. Available channels: {}".format(self.valid_channels)
    )
    assert gain in self.valid_gains, "Invalid gain. Available gains: {}".format(
        self.valid_gains
    )
    self.ser.write("g{}{:02d}\n".format(channel, gain).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

    if gain == 0:
        self.gains[channel - 1] = 1
    else:
        self.gains[channel - 1] = gain

set_gain_for_all(gain)

Sets the gain for all channels.

Parameters:

Name Type Description Default
gain int

The gain value.

required

Raises:

Type Description
AssertionError

If the gain is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_gain_for_all(24)
Source code in eeg_acquisition\ADS1299driver.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
def set_gain_for_all(self, gain):
    """
    Sets the gain for all channels.

    Args:
        gain (int): The gain value.

    Raises:
        AssertionError: If the gain is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_gain_for_all(24)
        ```
    """
    assert gain in self.valid_gains, "Invalid gain. Available gains: {}".format(
        self.valid_gains
    )
    for channel in self.valid_channels:
        self.set_gain(channel, gain)

set_input_mode(channel, mode)

Sets the input mode for a specific channel.

Parameters:

Name Type Description Default
channel int

The channel number.

required
mode str

The input mode.

required

Raises:

Type Description
AssertionError

If the channel or mode is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_input_mode(1, 'normal')
>>> ads.set_input_mode(2, 'shorted')
>>> ads.set_input_mode(3, 'test')
Source code in eeg_acquisition\ADS1299driver.py
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
def set_input_mode(self, channel, mode):
    """
    Sets the input mode for a specific channel.

    Args:
        channel (int): The channel number.
        mode (str): The input mode.

    Raises:
        AssertionError: If the channel or mode is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_input_mode(1, 'normal')
        >>> ads.set_input_mode(2, 'shorted')
        >>> ads.set_input_mode(3, 'test')
        ```
    """
    assert channel in self.valid_channels, (
        "Invalid channel. Available channels: {}".format(self.valid_channels)
    )
    assert mode in self.valid_input_modes, (
        "Invalid input mode. Available modes: {}".format(self.valid_input_modes)
    )
    self.ser.write("i{}{}\n".format(channel, mode[0]).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

    self.modes[channel - 1] = mode

set_input_mode_for_all(mode)

Sets the input mode for all channels.

Parameters:

Name Type Description Default
mode str

The input mode.

required

Raises:

Type Description
AssertionError

If the mode is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_input_mode_for_all('normal')
Source code in eeg_acquisition\ADS1299driver.py
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
def set_input_mode_for_all(self, mode):
    """
    Sets the input mode for all channels.

    Args:
        mode (str): The input mode.

    Raises:
        AssertionError: If the mode is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_input_mode_for_all('normal')
        ```
    """
    assert mode in self.valid_input_modes, (
        "Invalid input mode. Available modes: {}".format(self.valid_input_modes)
    )
    for channel in self.valid_channels:
        self.set_input_mode(channel, mode)

set_reference(reference, mode, channel=None)

Sets the references for the ADS1299.

Parameters:

Name Type Description Default
reference str

The reference to set. Must be 'SRB1' or 'SRB2'.

required
mode bool

True to enable the reference, False to disable it.

required
channel int

The channel number. Required for 'SRB2'.

None

Raises:

Type Description
AssertionError

If the reference or channel is invalid, or if mode is not a boolean.

Example
>>> ads = ADS1299('COM8')
>>> ads.set_reference('SRB1', True)
Source code in eeg_acquisition\ADS1299driver.py
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
def set_reference(self, reference, mode, channel=None):
    """
    Sets the references for the ADS1299.

    Args:
        reference (str): The reference to set. Must be 'SRB1' or 'SRB2'.
        mode (bool): True to enable the reference, False to disable it.
        channel (int, optional): The channel number. Required for 'SRB2'.

    Raises:
        AssertionError: If the reference or channel is invalid, or if mode
            is not a boolean.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.set_reference('SRB1', True)
        ```
    """
    assert reference in self.references, (
        "Invalid reference. Available references: {}".format(self.references)
    )
    assert isinstance(mode, bool), "Invalid mode. Mode must be a boolean."

    if reference == "SRB2":
        assert channel in self.valid_channels, (
            "Invalid channel. Available channels: {}".format(self.valid_channels)
        )
    else:
        channel = 0

    self.ser.write("r{}{}{}\n".format(reference[-1], int(mode), channel).encode())

    if self.verbose:
        print(self.verbose_header + self.read_line())

single_read()

Starts a single conversion and reads the data from the ADS1299.

Returns:

Type Description
ndarray

np.ndarray: A list of data read from the ADS1299.

Raises:

Type Description
TaskAbortedError

If the read operation takes more than its timeout.

Example
>>> ads = ADS1299('COM8')
>>> data = ads.single_read()
    [123, 456, 789, ...]
Source code in eeg_acquisition\ADS1299driver.py
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
def single_read(self) -> np.ndarray:
    """
    Starts a single conversion and reads the data from the ADS1299.

    Returns:
        np.ndarray: A list of data read from the ADS1299.

    Raises:
        TaskAbortedError: If the read operation takes more than its timeout.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> data = ads.single_read()
            [123, 456, 789, ...]
        ```
    """
    self.ser.write("u\n".encode())
    return self.read_ASCII_data()

single_shot_mode(enable)

Enables or disables single-shot mode.

Parameters:

Name Type Description Default
enable bool

True to enable single-shot mode, False to disable it.

required
Example
>>> ads = ADS1299('COM8')
>>> ads.single_shot_mode(True)
Source code in eeg_acquisition\ADS1299driver.py
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
def single_shot_mode(self, enable: bool):
    """
    Enables or disables single-shot mode.

    Args:
        enable (bool): True to enable single-shot mode, False to disable it.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.single_shot_mode(True)
        ```
    """
    assert isinstance(enable, bool), "Invalid argument. Mode must be a boolean."
    self.ser.write("k{}\n".format(int(enable)).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

start_streaming()

Starts streaming data from the ADS1299.

Example
>>> ads = ADS1299('COM8')
>>> ads.start_streaming()
Source code in eeg_acquisition\ADS1299driver.py
542
543
544
545
546
547
548
549
550
551
552
def start_streaming(self):
    """
    Starts streaming data from the ADS1299.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.start_streaming()
        ```
    """
    self.ser.write("a\n".encode())

stop_streaming()

Stops the stream of data from the ADS1299.

Example
>>> ads = ADS1299('COM8')
>>> ads.stop_streaming()
Source code in eeg_acquisition\ADS1299driver.py
554
555
556
557
558
559
560
561
562
563
564
565
566
567
def stop_streaming(self):
    """
    Stops the stream of data from the ADS1299.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.stop_streaming()
        ```
    """
    self.ser.write("s\n".encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

test_signal(amplitude, frequency)

Configures the test signal to the ADS1299.

Parameters:

Name Type Description Default
amplitude str

The amplitude of the test signal.

required
frequency str

The frequency of the test signal.

required

Raises:

Type Description
AssertionError

If the amplitude or frequency is invalid.

Example
>>> ads = ADS1299('COM8')
>>> ads.test_signal('1', 'fast')
Source code in eeg_acquisition\ADS1299driver.py
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
def test_signal(self, amplitude, frequency):
    """
    Configures the test signal to the ADS1299.

    Args:
        amplitude (str): The amplitude of the test signal.
        frequency (str): The frequency of the test signal.

    Raises:
        AssertionError: If the amplitude or frequency is invalid.

    Example:
        ```python
        >>> ads = ADS1299('COM8')
        >>> ads.test_signal('1', 'fast')
        ```
    """
    assert amplitude in self.valid_test_signal_conf["amplitude"], (
        "Invalid amplitude. Available amplitudes: {}".format(
            self.valid_test_signal_conf["amplitude"]
        )
    )
    assert frequency in self.valid_test_signal_conf["frequency"], (
        "Invalid frequency. Available frequencies: {}".format(
            self.valid_test_signal_conf["frequency"]
        )
    )
    self.ser.write("t{}{}\n".format(amplitude, frequency[0]).encode())
    sleep(self.delay)
    if self.verbose:
        print(self.verbose_header + self.read_line())

verbosity(value)

Sets the verbose mode for the ADS1299.

Parameters:

Name Type Description Default
value bool

True to enable verbose mode, False to disable it.

required
Source code in eeg_acquisition\ADS1299driver.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
def verbosity(self, value):
    """
    Sets the verbose mode for the ADS1299.

    Args:
        value (bool): True to enable verbose mode, False to disable it.
    """
    if value is True:
        self.ser.write("v1\n".encode())
        self.verbose = True
    else:
        self.ser.write("v0\n".encode())
        self.verbose = False

    if self.verbose:
        print(self.verbose_header + self.read_line())