@@ -496,6 +496,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine
496496//| once: Optional[ReadableBuffer] = None,
497497//| *,
498498//| loop: Optional[ReadableBuffer] = None,
499+ //| loop2: Optional[ReadableBuffer] = None,
499500//| swap: bool = False,
500501//| ) -> None:
501502//| """Write data to the TX fifo in the background, with optional looping.
@@ -504,7 +505,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine
504505//| This means that any ``once`` or ``loop`` buffer will be written at least once.
505506//| Then the ``once`` and/or ``loop`` buffers are queued. and the function returns.
506507//| The ``once`` buffer (if specified) will be written just once.
507- //| Finally, the ``loop`` buffer (if specified) will continue being looped indefinitely.
508+ //| Finally, the ``loop`` and/or ``loop2`` buffer (if specified) will continue being looped indefinitely. If both ``loop`` and ``loop2`` are specified, they will alternate .
508509//|
509510//| Writes to the FIFO will match the input buffer's element size. For example, bytearray elements
510511//| will perform 8 bit writes to the PIO FIFO. The RP2040's memory bus will duplicate the value into
@@ -531,14 +532,15 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine
531532//|
532533//| :param ~Optional[circuitpython_typing.ReadableBuffer] once: Data to be written once
533534//| :param ~Optional[circuitpython_typing.ReadableBuffer] loop: Data to be written repeatedly
535+ //| :param ~Optional[circuitpython_typing.ReadableBuffer] loop2: Data to be written repeatedly
534536//| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order
535537//| """
536538//| ...
537539
538- static void fill_buf_info (sm_buf_info * info , mp_obj_t obj , size_t * stride_in_bytes ) {
540+ static void fill_buf_info (sm_buf_info * info , mp_obj_t obj , size_t * stride_in_bytes , mp_uint_t direction ) {
539541 if (obj != mp_const_none ) {
540542 info -> obj = obj ;
541- mp_get_buffer_raise (obj , & info -> info , MP_BUFFER_READ );
543+ mp_get_buffer_raise (obj , & info -> info , direction );
542544 size_t stride = mp_binary_get_size ('@' , info -> info .typecode , NULL );
543545 if (stride > 4 ) {
544546 mp_raise_ValueError (MP_ERROR_TEXT ("Buffer elements must be 4 bytes long or less" ));
@@ -553,27 +555,29 @@ static void fill_buf_info(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_byt
553555}
554556
555557static mp_obj_t rp2pio_statemachine_background_write (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
556- enum { ARG_once , ARG_loop , ARG_swap };
558+ enum { ARG_once , ARG_loop , ARG_loop2 , ARG_swap };
557559 static const mp_arg_t allowed_args [] = {
558560 { MP_QSTR_once , MP_ARG_OBJ , {.u_obj = mp_const_none } },
559561 { MP_QSTR_loop , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
560- { MP_QSTR_swap , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
562+ { MP_QSTR_loop2 , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
563+ { MP_QSTR_swap , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
561564 };
562565 rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
563566 check_for_deinit (self );
564567 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
565568 mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
566569
567- sm_buf_info once_info ;
568- sm_buf_info loop_info ;
569570 size_t stride_in_bytes = 0 ;
570- fill_buf_info (& once_info , args [ARG_once ].u_obj , & stride_in_bytes );
571- fill_buf_info (& loop_info , args [ARG_loop ].u_obj , & stride_in_bytes );
571+
572+ fill_buf_info (& self -> once_write_buf_info , args [ARG_once ].u_obj , & stride_in_bytes , MP_BUFFER_READ );
573+ fill_buf_info (& self -> loop_write_buf_info , args [ARG_loop ].u_obj , & stride_in_bytes , MP_BUFFER_READ );
574+ fill_buf_info (& self -> loop2_write_buf_info , args [ARG_loop2 ].u_obj , & stride_in_bytes , MP_BUFFER_READ );
575+
572576 if (!stride_in_bytes ) {
573577 return mp_const_none ;
574578 }
575579
576- bool ok = common_hal_rp2pio_statemachine_background_write (self , & once_info , & loop_info , stride_in_bytes , args [ARG_swap ].u_bool );
580+ bool ok = common_hal_rp2pio_statemachine_background_write (self , stride_in_bytes , args [ARG_swap ].u_bool );
577581
578582 if (mp_hal_is_interrupted ()) {
579583 return mp_const_none ;
@@ -602,6 +606,7 @@ static mp_obj_t rp2pio_statemachine_obj_stop_background_write(mp_obj_t self_in)
602606}
603607MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_stop_background_write_obj , rp2pio_statemachine_obj_stop_background_write );
604608
609+
605610//| writing: bool
606611//| """Returns True if a background write is in progress"""
607612static mp_obj_t rp2pio_statemachine_obj_get_writing (mp_obj_t self_in ) {
@@ -613,18 +618,147 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_writing_obj, rp2pio_statemachi
613618MP_PROPERTY_GETTER (rp2pio_statemachine_writing_obj ,
614619 (mp_obj_t )& rp2pio_statemachine_get_writing_obj );
615620
621+ //| pending_write: int
616622//| pending: int
617623//| """Returns the number of pending buffers for background writing.
618624//|
619- //| If the number is 0, then a `StateMachine.background_write` call will not block."""
620- static mp_obj_t rp2pio_statemachine_obj_get_pending (mp_obj_t self_in ) {
625+ //| If the number is 0, then a `StateMachine.background_write` call will not block.
626+ //| Note that `pending` is a deprecated alias for `pending_write` and will be removed
627+ //| in a future version of CircuitPython."""
628+
629+
630+ static mp_obj_t rp2pio_statemachine_obj_get_pending_write (mp_obj_t self_in ) {
621631 rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
622- return mp_obj_new_int (common_hal_rp2pio_statemachine_get_pending (self ));
632+ return mp_obj_new_int (common_hal_rp2pio_statemachine_get_pending_write (self ));
623633}
624- MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_pending_obj , rp2pio_statemachine_obj_get_pending );
634+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_pending_write_obj , rp2pio_statemachine_obj_get_pending_write );
625635
626636MP_PROPERTY_GETTER (rp2pio_statemachine_pending_obj ,
627- (mp_obj_t )& rp2pio_statemachine_get_pending_obj );
637+ (mp_obj_t )& rp2pio_statemachine_get_pending_write_obj );
638+
639+ MP_PROPERTY_GETTER (rp2pio_statemachine_pending_write_obj ,
640+ (mp_obj_t )& rp2pio_statemachine_get_pending_write_obj );
641+
642+
643+ // =================================================================================================================================
644+
645+ //| def background_read(
646+ //| self,
647+ //| once: Optional[WriteableBuffer] = None,
648+ //| *,
649+ //| loop: Optional[WriteableBuffer] = None,
650+ //| loop2: Optional[WriteableBuffer] = None,
651+ //| swap: bool = False,
652+ //| ) -> None:
653+ //| """Read data from the RX fifo in the background, with optional looping.
654+ //|
655+ //| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have been started.
656+ //| This means that any ``once`` or ``loop`` buffer will be read at least once.
657+ //| Then the ``once`` and/or ``loop`` buffers are queued. and the function returns.
658+ //| The ``once`` buffer (if specified) will be read just once.
659+ //| Finally, the ``loop`` and/or ``loop2`` buffer (if specified) will continue being read indefinitely. If both ``loop`` and ``loop2`` are specified, they will alternate.
660+ //|
661+ //| Reads from the FIFO will match the input buffer's element size. For example, bytearray elements
662+ //| will perform 8 bit reads from the PIO FIFO. The RP2040's memory bus will duplicate the value into
663+ //| the other byte positions. So, pulling more data in the PIO assembly will read the duplicated values.
664+ //|
665+ //| To perform 16 or 32 bits reads from the FIFO use an `array.array` with a type code of the desired
666+ //| size, or use `memoryview.cast` to change the interpretation of an
667+ //| existing buffer. To receive just part of a larger buffer, slice a `memoryview`
668+ //| of it.
669+ //|
670+ //| Most use cases will probably only use one of ``once`` or ``loop``.
671+ //|
672+ //| Having neither ``once`` nor ``loop`` terminates an existing
673+ //| background looping read after exactly a whole loop. This is in contrast to
674+ //| `stop_background_read`, which interrupts an ongoing DMA operation.
675+ //|
676+ //| :param ~Optional[circuitpython_typing.WriteableBuffer] once: Data to be read once
677+ //| :param ~Optional[circuitpython_typing.WriteableBuffer] loop: Data to be read repeatedly
678+ //| :param ~Optional[circuitpython_typing.WriteableBuffer] loop2: Data to be read repeatedly
679+ //| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order
680+ //| """
681+ //| ...
682+
683+
684+ static mp_obj_t rp2pio_statemachine_background_read (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
685+ enum { ARG_once , ARG_loop , ARG_loop2 , ARG_swap };
686+ static const mp_arg_t allowed_args [] = {
687+ { MP_QSTR_once , MP_ARG_OBJ , {.u_obj = mp_const_none } },
688+ { MP_QSTR_loop , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
689+ { MP_QSTR_loop2 , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
690+ { MP_QSTR_swap , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
691+ };
692+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
693+ check_for_deinit (self );
694+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
695+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
696+
697+ size_t stride_in_bytes = 0 ;
698+
699+ fill_buf_info (& self -> once_read_buf_info , args [ARG_once ].u_obj , & stride_in_bytes , MP_BUFFER_WRITE );
700+ fill_buf_info (& self -> loop_read_buf_info , args [ARG_loop ].u_obj , & stride_in_bytes , MP_BUFFER_WRITE );
701+ fill_buf_info (& self -> loop2_read_buf_info , args [ARG_loop2 ].u_obj , & stride_in_bytes , MP_BUFFER_WRITE );
702+
703+ if (!stride_in_bytes ) {
704+ return mp_const_none ;
705+ }
706+
707+ bool ok = common_hal_rp2pio_statemachine_background_read (self , stride_in_bytes , args [ARG_swap ].u_bool );
708+
709+ if (mp_hal_is_interrupted ()) {
710+ return mp_const_none ;
711+ }
712+ if (!ok ) {
713+ mp_raise_OSError (MP_EIO );
714+ }
715+ return mp_const_none ;
716+ }
717+ MP_DEFINE_CONST_FUN_OBJ_KW (rp2pio_statemachine_background_read_obj , 1 , rp2pio_statemachine_background_read );
718+
719+ //| def stop_background_read(self) -> None:
720+ //| """Immediately stop a background read, if one is in progress. Any
721+ //| DMA in progress is halted, but items already in the RX FIFO are not
722+ //| affected."""
723+ static mp_obj_t rp2pio_statemachine_obj_stop_background_read (mp_obj_t self_in ) {
724+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
725+ bool ok = common_hal_rp2pio_statemachine_stop_background_read (self );
726+ if (mp_hal_is_interrupted ()) {
727+ return mp_const_none ;
728+ }
729+ if (!ok ) {
730+ mp_raise_OSError (MP_EIO );
731+ }
732+ return mp_const_none ;
733+ }
734+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_stop_background_read_obj , rp2pio_statemachine_obj_stop_background_read );
735+
736+ //| reading: bool
737+ //| """Returns True if a background read is in progress"""
738+ static mp_obj_t rp2pio_statemachine_obj_get_reading (mp_obj_t self_in ) {
739+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
740+ return mp_obj_new_bool (common_hal_rp2pio_statemachine_get_reading (self ));
741+ }
742+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_reading_obj , rp2pio_statemachine_obj_get_reading );
743+
744+ MP_PROPERTY_GETTER (rp2pio_statemachine_reading_obj ,
745+ (mp_obj_t )& rp2pio_statemachine_get_reading_obj );
746+
747+ //| pending_read: int
748+ //| """Returns the number of pending buffers for background reading.
749+ //|
750+ //| If the number is 0, then a `StateMachine.background_read` call will not block."""
751+ static mp_obj_t rp2pio_statemachine_obj_get_pending_read (mp_obj_t self_in ) {
752+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
753+ return mp_obj_new_int (common_hal_rp2pio_statemachine_get_pending_read (self ));
754+ }
755+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_pending_read_obj , rp2pio_statemachine_obj_get_pending_read );
756+
757+ MP_PROPERTY_GETTER (rp2pio_statemachine_pending_read_obj ,
758+ (mp_obj_t )& rp2pio_statemachine_get_pending_read_obj );
759+
760+
761+ // =================================================================================================================================
628762
629763//| def readinto(
630764//| self,
@@ -924,6 +1058,42 @@ MP_PROPERTY_GETTER(rp2pio_statemachine_rxfifo_obj,
9241058 (mp_obj_t )& rp2pio_statemachine_get_rxfifo_obj );
9251059
9261060
1061+ //| last_read: array.array
1062+ //| """Returns the buffer most recently filled by background reads.
1063+ //|
1064+ //| This property is self-clearing -- once read, subsequent reads
1065+ //| will return a zero-length buffer until the background read buffer
1066+ //| changes or restarts.
1067+ //| """
1068+ static mp_obj_t rp2pio_statemachine_obj_get_last_read (mp_obj_t self_in ) {
1069+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
1070+ check_for_deinit (self );
1071+ return common_hal_rp2pio_statemachine_get_last_read (self );
1072+ }
1073+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_last_read_obj , rp2pio_statemachine_obj_get_last_read );
1074+
1075+ MP_PROPERTY_GETTER (rp2pio_statemachine_last_read_obj ,
1076+ (mp_obj_t )& rp2pio_statemachine_get_last_read_obj );
1077+
1078+
1079+ //| last_write: array.array
1080+ //| """Returns the buffer most recently emptied by background writes.
1081+ //|
1082+ //| This property is self-clearing -- once read, subsequent reads
1083+ //| will return a zero-length buffer until the background write buffer
1084+ //| changes or restarts.
1085+ //| """
1086+ //|
1087+ static mp_obj_t rp2pio_statemachine_obj_get_last_write (mp_obj_t self_in ) {
1088+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
1089+ check_for_deinit (self );
1090+ return common_hal_rp2pio_statemachine_get_last_write (self );
1091+ }
1092+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_last_write_obj , rp2pio_statemachine_obj_get_last_write );
1093+
1094+ MP_PROPERTY_GETTER (rp2pio_statemachine_last_write_obj ,
1095+ (mp_obj_t )& rp2pio_statemachine_get_last_write_obj );
1096+
9271097static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table [] = {
9281098 { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& rp2pio_statemachine_deinit_obj ) },
9291099 { MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& default___enter___obj ) },
@@ -938,10 +1108,17 @@ static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
9381108 { MP_ROM_QSTR (MP_QSTR_readinto ), MP_ROM_PTR (& rp2pio_statemachine_readinto_obj ) },
9391109 { MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& rp2pio_statemachine_write_obj ) },
9401110 { MP_ROM_QSTR (MP_QSTR_write_readinto ), MP_ROM_PTR (& rp2pio_statemachine_write_readinto_obj ) },
1111+
9411112 { MP_ROM_QSTR (MP_QSTR_background_write ), MP_ROM_PTR (& rp2pio_statemachine_background_write_obj ) },
9421113 { MP_ROM_QSTR (MP_QSTR_stop_background_write ), MP_ROM_PTR (& rp2pio_statemachine_stop_background_write_obj ) },
9431114 { MP_ROM_QSTR (MP_QSTR_writing ), MP_ROM_PTR (& rp2pio_statemachine_writing_obj ) },
944- { MP_ROM_QSTR (MP_QSTR_pending ), MP_ROM_PTR (& rp2pio_statemachine_pending_obj ) },
1115+ { MP_ROM_QSTR (MP_QSTR_pending ), MP_ROM_PTR (& rp2pio_statemachine_pending_write_obj ) },
1116+ { MP_ROM_QSTR (MP_QSTR_pending_write ), MP_ROM_PTR (& rp2pio_statemachine_pending_write_obj ) },
1117+
1118+ { MP_ROM_QSTR (MP_QSTR_background_read ), MP_ROM_PTR (& rp2pio_statemachine_background_read_obj ) },
1119+ { MP_ROM_QSTR (MP_QSTR_stop_background_read ), MP_ROM_PTR (& rp2pio_statemachine_stop_background_read_obj ) },
1120+ { MP_ROM_QSTR (MP_QSTR_reading ), MP_ROM_PTR (& rp2pio_statemachine_reading_obj ) },
1121+ { MP_ROM_QSTR (MP_QSTR_pending_read ), MP_ROM_PTR (& rp2pio_statemachine_pending_read_obj ) },
9451122
9461123 { MP_ROM_QSTR (MP_QSTR_frequency ), MP_ROM_PTR (& rp2pio_statemachine_frequency_obj ) },
9471124 { MP_ROM_QSTR (MP_QSTR_rxstall ), MP_ROM_PTR (& rp2pio_statemachine_rxstall_obj ) },
@@ -952,6 +1129,10 @@ static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
9521129 { MP_ROM_QSTR (MP_QSTR_pc ), MP_ROM_PTR (& rp2pio_statemachine_pc_obj ) },
9531130
9541131 { MP_ROM_QSTR (MP_QSTR_rxfifo ), MP_ROM_PTR (& rp2pio_statemachine_rxfifo_obj ) },
1132+
1133+ { MP_ROM_QSTR (MP_QSTR_last_read ), MP_ROM_PTR (& rp2pio_statemachine_last_read_obj ) },
1134+ { MP_ROM_QSTR (MP_QSTR_last_write ), MP_ROM_PTR (& rp2pio_statemachine_last_write_obj ) },
1135+
9551136};
9561137static MP_DEFINE_CONST_DICT (rp2pio_statemachine_locals_dict , rp2pio_statemachine_locals_dict_table ) ;
9571138
0 commit comments