@@ -535,10 +535,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine
535535//| """
536536//| ...
537537
538- static void fill_buf_info (sm_buf_info * info , mp_obj_t obj , size_t * stride_in_bytes ) {
538+ static void fill_buf_info (sm_buf_info * info , mp_obj_t obj , size_t * stride_in_bytes , mp_uint_t direction ) {
539539 if (obj != mp_const_none ) {
540540 info -> obj = obj ;
541- mp_get_buffer_raise (obj , & info -> info , MP_BUFFER_READ );
541+ mp_get_buffer_raise (obj , & info -> info , direction );
542542 size_t stride = mp_binary_get_size ('@' , info -> info .typecode , NULL );
543543 if (stride > 4 ) {
544544 mp_raise_ValueError (MP_ERROR_TEXT ("Buffer elements must be 4 bytes long or less" ));
@@ -553,27 +553,29 @@ static void fill_buf_info(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_byt
553553}
554554
555555static 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 };
556+ enum { ARG_once , ARG_loop , ARG_loop2 , ARG_swap };
557557 static const mp_arg_t allowed_args [] = {
558558 { MP_QSTR_once , MP_ARG_OBJ , {.u_obj = mp_const_none } },
559559 { 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} },
560+ { MP_QSTR_loop2 , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
561+ { MP_QSTR_swap , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
561562 };
562563 rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
563564 check_for_deinit (self );
564565 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
565566 mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
566567
567- sm_buf_info once_info ;
568- sm_buf_info loop_info ;
569568 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 );
569+
570+ fill_buf_info (& self -> once_write_buf_info , args [ARG_once ].u_obj , & stride_in_bytes , MP_BUFFER_READ );
571+ fill_buf_info (& self -> loop_write_buf_info , args [ARG_loop ].u_obj , & stride_in_bytes , MP_BUFFER_READ );
572+ fill_buf_info (& self -> loop2_write_buf_info , args [ARG_loop2 ].u_obj , & stride_in_bytes , MP_BUFFER_READ );
573+
572574 if (!stride_in_bytes ) {
573575 return mp_const_none ;
574576 }
575577
576- bool ok = common_hal_rp2pio_statemachine_background_write (self , & once_info , & loop_info , stride_in_bytes , args [ARG_swap ].u_bool );
578+ bool ok = common_hal_rp2pio_statemachine_background_write (self , stride_in_bytes , args [ARG_swap ].u_bool );
577579
578580 if (mp_hal_is_interrupted ()) {
579581 return mp_const_none ;
@@ -602,6 +604,7 @@ static mp_obj_t rp2pio_statemachine_obj_stop_background_write(mp_obj_t self_in)
602604}
603605MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_stop
6901
_background_write_obj , rp2pio_statemachine_obj_stop_background_write );
604606
607+
605608//| writing: bool
606609//| """Returns True if a background write is in progress"""
607610static mp_obj_t rp2pio_statemachine_obj_get_writing (mp_obj_t self_in ) {
@@ -613,18 +616,145 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_writing_obj, rp2pio_statemachi
613616MP_PROPERTY_GETTER (rp2pio_statemachine_writing_obj ,
614617 (mp_obj_t )& rp2pio_statemachine_get_writing_obj );
615618
619+ //| pending_write: int
616620//| pending: int
617621//| """Returns the number of pending buffers for background writing.
618622//|
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 ) {
623+ //| If the number is 0, then a `StateMachine.background_write` call will not block.
624+ //| Note that `pending` is a deprecated alias for `pending_write` and will be removed
625+ //| in a future version of CircuitPython."""
626+
627+
628+ static mp_obj_t rp2pio_statemachine_obj_get_pending_write (mp_obj_t self_in ) {
621629 rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
622- return mp_obj_new_int (common_hal_rp2pio_statemachine_get_pending (self ));
630+ return mp_obj_new_int (common_hal_rp2pio_statemachine_get_pending_write (self ));
623631}
624- MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_pending_obj , rp2pio_statemachine_obj_get_pending );
632+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_pending_write_obj , rp2pio_statemachine_obj_get_pending_write );
625633
626634MP_PROPERTY_GETTER (rp2pio_statemachine_pending_obj ,
627- (mp_obj_t )& rp2pio_statemachine_get_pending_obj );
635+ (mp_obj_t )& rp2pio_statemachine_get_pending_write_obj );
636+
637+ MP_PROPERTY_GETTER (rp2pio_statemachine_pending_write_obj ,
638+ (mp_obj_t )& rp2pio_statemachine_get_pending_write_obj );
639+
640+
641+ // =================================================================================================================================
642+
643+ //| def background_read(
644+ //| self,
645+ //| once: Optional[WriteableBuffer] = None,
646+ //| *,
647+ //| loop: Optional[WriteableBuffer] = None,
648+ //| swap: bool = False,
649+ //| ) -> None:
650+ //| """Read data from the RX fifo in the background, with optional looping.
651+ //|
652+ //| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have been started.
653+ //| This means that any ``once`` or ``loop`` buffer will be read at least once.
654+ //| Then the ``once`` and/or ``loop`` buffers are queued. and the function returns.
655+ //| The ``once`` buffer (if specified) will be read just once.
656+ //| Finally, the ``loop`` buffer (if specified) will continue being read indefinitely.
657+ //|
658+ //| Reads from the FIFO will match the input buffer's element size. For example, bytearray elements
659+ //| will perform 8 bit reads from the PIO FIFO. The RP2040's memory bus will duplicate the value into
660+ //| the other byte positions. So, pulling more data in the PIO assembly will read the duplicated values.
661+ //|
662+ //| To perform 16 or 32 bits reads from the FIFO use an `array.array` with a type code of the desired
663+ //| size, or use `memoryview.cast` to change the interpretation of an
664+ //| existing buffer. To receive just part of a larger buffer, slice a `memoryview`
665+ //| of it.
666+ //|
667+ //| Most use cases will probably only use one of ``once`` or ``loop``.
668+ //|
669+ //| Having neither ``once`` nor ``loop`` terminates an existing
670+ //| background looping read after exactly a whole loop. This is in contrast to
671+ //| `stop_background_read`, which interrupts an ongoing DMA operation.
672+ //|
673+ //| :param ~Optional[circuitpython_typing.WriteableBuffer] once: Data to be read once
674+ //| :param ~Optional[circuitpython_typing.WriteableBuffer] loop: Data to be read repeatedly
675+ //| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order
676+ //| """
677+ //| ...
678+
679+
680+ static mp_obj_t rp2pio_statemachine_background_read (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
681+ enum { ARG_once , ARG_loop , ARG_loop2 , ARG_swap };
682+ static const mp_arg_t allowed_args [] = {
683+ { MP_QSTR_once , MP_ARG_OBJ , {.u_obj = mp_const_none } },
684+ { MP_QSTR_loop , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
685+ { MP_QSTR_loop2 , MP_ARG_OBJ | MP_ARG_KW_ONLY , {.u_obj = mp_const_none } },
686+ { MP_QSTR_swap , MP_ARG_KW_ONLY | MP_ARG_BOOL , {.u_bool = false} },
687+ };
688+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
689+ check_for_deinit (self );
690+ mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
691+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
692+
693+ size_t stride_in_bytes = 0 ;
694+
695+ fill_buf_info (& self -> once_read_buf_info , args [ARG_once ].u_obj , & stride_in_bytes , MP_BUFFER_WRITE );
696+ fill_buf_info (& self -> loop_read_buf_info , args [ARG_loop ].u_obj , & stride_in_bytes , MP_BUFFER_WRITE );
697+ fill_buf_info (& self -> loop2_read_buf_info , args [ARG_loop2 ].u_obj , & stride_in_bytes , MP_BUFFER_WRITE );
698+
699+ if (!stride_in_bytes ) {
700+ return mp_const_none ;
701+ }
702+
703+ bool ok = common_hal_rp2pio_statemachine_background_read (self , stride_in_bytes , args [ARG_swap ].u_bool );
704+
705+ if (mp_hal_is_interrupted ()) {
706+ return mp_const_none ;
707+ }
708+ if (!ok ) {
709+ mp_raise_OSError (MP_EIO );
710+ }
711+ return mp_const_none ;
712+ }
713+ MP_DEFINE_CONST_FUN_OBJ_KW (rp2pio_statemachine_background_read_obj , 1 , rp2pio_statemachine_background_read );
714+
715+ //| def stop_background_read(self) -> None:
716+ //| """Immediately stop a background read, if one is in progress. Any
717+ //| DMA in progress is halted, but items already in the RX FIFO are not
718+ //| affected."""
719+ static mp_obj_t rp2pio_statemachine_obj_stop_background_read (mp_obj_t self_in ) {
720+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
721+ bool ok = common_hal_rp2pio_statemachine_stop_background_read (self );
722+ if (mp_hal_is_interrupted ()) {
723+ return mp_const_none ;
724+ }
725+ if (!ok ) {
726+ mp_raise_OSError (MP_EIO );
727+ }
728+ return mp_const_none ;
729+ }
730+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_stop_background_read_obj , rp2pio_statemachine_obj_stop_background_read );
731+
732+ //| reading: bool
733+ //| """Returns True if a background read is in progress"""
734+ static mp_obj_t rp2pio_statemachine_obj_get_reading (mp_obj_t self_in ) {
735+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
736+ return mp_obj_new_bool (common_hal_rp2pio_statemachine_get_reading (self ));
737+ }
738+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_reading_obj , rp2pio_statemachine_obj_get_reading );
739+
740+ MP_PROPERTY_GETTER (rp2pio_statemachine_reading_obj ,
741+ (mp_obj_t )& rp2pio_statemachine_get_reading_obj );
742+
743+ //| pending_read: int
744+ //| """Returns the number of pending buffers for background reading.
745+ //|
746+ //| If the number is 0, then a `StateMachine.background_read` call will not block."""
747+ static mp_obj_t rp2pio_statemachine_obj_get_pending_read (mp_obj_t self_in ) {
748+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
749+ return mp_obj_new_int (common_hal_rp2pio_statemachine_get_pending_read (self ));
750+ }
751+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_pending_read_obj , rp2pio_statemachine_obj_get_pending_read );
752+
753+ MP_PROPERTY_GETTER (rp2pio_statemachine_pending_read_obj ,
754+ (mp_obj_t )& rp2pio_statemachine_get_pending_read_obj );
755+
756+
757+ // =================================================================================================================================
628758
629759//| def readinto(
630760//| self,
@@ -924,6 +1054,42 @@ MP_PROPERTY_GETTER(rp2pio_statemachine_rxfifo_obj,
9241054 (mp_obj_t )& rp2pio_statemachine_get_rxfifo_obj );
9251055
9261056
1057+ //| last_read: array.array
1058+ //| """Returns the buffer most recently filled by background reads.
1059+ //|
1060+ //| This property is self-clearing -- once read, subsequent reads
1061+ //| will return a zero-length buffer until the background read buffer
1062+ //| changes or restarts.
1063+ //| """
1064+ static mp_obj_t rp2pio_statemachine_obj_get_last_read (mp_obj_t self_in ) {
1065+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
1066+ check_for_deinit (self );
1067+ return common_hal_rp2pio_statemachine_get_last_read (self );
1068+ }
1069+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_last_read_obj , rp2pio_statemachine_obj_get_last_read );
1070+
1071+ MP_PROPERTY_GETTER (rp2pio_statemachine_last_read_obj ,
1072+ (mp_obj_t )& rp2pio_statemachine_get_last_read_obj );
1073+
1074+
1075+ //| last_write: array.array
1076+ //| """Returns the buffer most recently emptied by background writes.
1077+ //|
1078+ //| This property is self-clearing -- once read, subsequent reads
1079+ //| will return a zero-length buffer until the background write buffer
1080+ //| changes or restarts.
1081+ //| """
1082+ //|
1083+ static mp_obj_t rp2pio_statemachine_obj_get_last_write (mp_obj_t self_in ) {
1084+ rp2pio_statemachine_obj_t * self = MP_OBJ_TO_PTR (self_in );
1085+ check_for_deinit (self );
1086+ return common_hal_rp2pio_statemachine_get_last_write (self );
1087+ }
1088+ MP_DEFINE_CONST_FUN_OBJ_1 (rp2pio_statemachine_get_last_write_obj , rp2pio_statemachine_obj_get_last_write );
1089+
1090+ MP_PROPERTY_GETTER (rp2pio_statemachine_last_write_obj ,
1091+ (mp_obj_t )& rp2pio_statemachine_get_last_write_obj );
1092+
9271093static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table [] = {
9281094 { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& rp2pio_statemachine_deinit_obj ) },
9291095 { MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& default___enter___obj ) },
@@ -938,10 +1104,17 @@ static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
9381104 { MP_ROM_QSTR (MP_QSTR_readinto ), MP_ROM_PTR (& rp2pio_statemachine_readinto_obj ) },
9391105 { MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& rp2pio_statemachine_write_obj ) },
9401106 { MP_ROM_QSTR (MP_QSTR_write_readinto ), MP_ROM_PTR (& rp2pio_statemachine_write_readinto_obj ) },
1107+
9411108 { MP_ROM_QSTR (MP_QSTR_background_write ), MP_ROM_PTR (& rp2pio_statemachine_background_write_obj ) },
9421109 { MP_ROM_QSTR (MP_QSTR_stop_background_write ), MP_ROM_PTR (& rp2pio_statemachine_stop_background_write_obj ) },
9431110 { 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 ) },
1111+ { MP_ROM_QSTR (MP_QSTR_pending ), MP_ROM_PTR (& rp2pio_statemachine_pending_write_obj ) },
1112+ { MP_ROM_QSTR (MP_QSTR_pending_write ), MP_ROM_PTR (& rp2pio_statemachine_pending_write_obj ) },
1113+
1114+ { MP_ROM_QSTR (MP_QSTR_background_read ), MP_ROM_PTR (& rp2pio_statemachine_background_read_obj ) },
1115+ { MP_ROM_QSTR (MP_QSTR_stop_background_read ), MP_ROM_PTR (& rp2pio_statemachine_stop_background_read_obj ) },
1116+ { MP_ROM_QSTR (MP_QSTR_reading ), MP_ROM_PTR (& rp2pio_statemachine_reading_obj ) },
1117+ { MP_ROM_QSTR (MP_QSTR_pending_read ), MP_ROM_PTR (& rp2pio_statemachine_pending_read_obj ) },
9451118
9461119 { MP_ROM_QSTR (MP_QSTR_frequency ), MP_ROM_PTR (& rp2pio_statemachine_frequency_obj ) },
9471120 { MP_ROM_QSTR (MP_QSTR_rxstall ), MP_ROM_PTR (& rp2pio_statemachine_rxstall_obj ) },
@@ -952,6 +1125,10 @@ static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = {
9521125 { MP_ROM_QSTR (MP_QSTR_pc ), MP_ROM_PTR (& rp2pio_statemachine_pc_obj ) },
9531126
9541127 { MP_ROM_QSTR (MP_QSTR_rxfifo ), MP_ROM_PTR (& rp2pio_statemachine_rxfifo_obj ) },
1128+
1129+ { MP_ROM_QSTR (MP_QSTR_last_read ), MP_ROM_PTR (& rp2pio_statemachine_last_read_obj ) },
1130+ { MP_ROM_QSTR (MP_QSTR_last_write ), MP_ROM_PTR (& rp2pio_statemachine_last_write_obj ) },
1131+
9551132};
9561133static MP_DEFINE_CONST_DICT (rp2pio_statemachine_locals_dict , rp2pio_statemachine_locals_dict_table ) ;
9571134
0 commit comments