diff pru_rtaudio.p @ 39:638bc1ae2500 staging

Improved readibility of the DIGITAL code in the PRU, using register names instead of aliases and expanding some of the macros, removing unused macros. Binaries were not modified
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 13 May 2015 12:18:10 +0100
parents a9af130097e8
children 419ce4ebfc4c
line wrap: on
line diff
--- a/pru_rtaudio.p	Tue May 12 23:48:37 2015 +0100
+++ b/pru_rtaudio.p	Wed May 13 12:18:10 2015 +0100
@@ -189,7 +189,7 @@
 #define MEM_DIGITAL_BUFFER1_OFFSET 0x400 //Start pointer to DIGITAL_BUFFER1, which is 256 words after.
 // 256 is the maximum number of frames allowed
 
-#define reg_digital_current r6  // Pointer to current storage location of DIGITAL
+#define r27_current r6  // Pointer to current storage location of DIGITAL
 #define reg_num_channels	r9		// Number of SPI ADC/DAC channels to use
 #define reg_frame_current	r10		// Current frame count in SPI ADC/DAC transfer
 #define reg_frame_total		r11		// Total frame count for SPI ADC/DAC
@@ -238,7 +238,6 @@
 #define GPIO_OE 0x134 
 #define GPIO_DATAIN 0x138
 
-//gpioX_oe must be adjacent to gpioX_datain
 //gpioX_cleardataout must be adjacent to gpioX_setdataout
 #define reg_gpio1_oe r2
 #define reg_gpio2_oe r3
@@ -248,25 +247,8 @@
 #define reg_gpio1_setdataout r8
 #define reg_digital r27 //will first contain digitalOut from render() and digitalIn to render() later
 //aliases
-#define reg_gpio1_datain reg_gpio1_oe
-#define reg_gpio2_datain reg_gpio2_oe
-
-.macro SET_GPIO1_BITS
-.mparam gpio_num_bit, digital_bit
-    SET_GPIO_BITS reg_gpio1_oe, reg_gpio1_setdataout, reg_gpio1_cleardataout, gpio_num_bit, digital_bit, reg_digital
-.endm
-.macro SET_GPIO2_BITS
-.mparam gpio_num_bit, digital_bit
-    SET_GPIO_BITS reg_gpio2_oe, reg_gpio2_setdataout, reg_gpio2_cleardataout, gpio_num_bit, digital_bit, reg_digital
-.endm
-.macro READ_GPIO1_BITS
-.mparam gpio_num_bit, digital_bit
-    READ_GPIO_BITS reg_gpio1_datain, gpio_num_bit, digital_bit, reg_digital
-.endm
-.macro READ_GPIO2_BITS
-.mparam gpio_num_bit, digital_bit
-    READ_GPIO_BITS reg_gpio2_datain, gpio_num_bit, digital_bit, reg_digital
-.endm
+#define reg_gpio1_datain r2
+#define reg_gpio2_datain r3
 
 .macro READ_GPIO_BITS
 .mparam gpio_data, gpio_num_bit, digital_bit, digital
@@ -299,125 +281,127 @@
 DONE:
 .endm
 
-.macro PROCESS_GPIO1_BITS
-//- sets appropriate bits for output in reg_gpio1_oe, reg_gpio1_cleardataout, reg_gpio1_data
-//- sets appropriate bits in reg_digital to reflect the input values
-.mparam gpio_num_bit, digital_bit
-// params to SET_GPIO_BITS gpio_oe, gpio_setdataout, gpio_cleardataout, gpio_num_bit, digital_bit, digital //sets the bits in GPIO_OE, GPIO_SETDATAOUT and GPIO_CLEARDATAOUT
-    SET_GPIO_BITS reg_gpio1_oe, reg_gpio1_setdataout, reg_gpio1_cleardataout, gpio_num_bit, digital_bit, reg_digital
-    READ_GPIO_BITS reg_gpio1_oe, reg_gpio1_datain, gpio_num_bit, digital_bit, reg_digital
-.endm
-
-.macro PROCESS_GPIO2_BITS
-//- sets appropriate bits for output in reg_gpio2_oe, reg_gpio2_cleardataout, reg_gpio2_data
-//- sets appropriate bits in reg_digital to reflect the input values
-.mparam gpio_num_bit, digital_bit
-    SET_GPIO_BITS reg_gpio2_oe, reg_gpio2_setdataout, reg_gpio2_cleardataout, gpio_num_bit, digital_bit, reg_digital
-    READ_GPIO_BITS reg_gpio2_oe, reg_gpio2_datain, gpio_num_bit, digital_bit, reg_digital
-.endm
-
 QBA START // when first starting, go to START, skipping this section.
 
 DIGITAL:
-//reg_digital is now the input word passed in render(), one word per frame
+//IMPORTANT: do NOT use r28 in this macro, as it contains the return address for JAL
+//r27 is now the input word passed in render(), one word per frame
 //[31:16]: data(1=high, 0=low), [15:0]: direction (0=output, 1=input) )
+
+
 //Preparing the gpio_oe, gpio_cleardataout and gpio_setdataout for each module
-
-//load current status of GPIO_OE in reg_gpioX_oe
-    MOV reg_gpio1_oe, GPIO1 | GPIO_OE 
+//r2 will hold GPIO1_OE
+//load current status of GPIO_OE in r2
+    MOV r2, GPIO1 | GPIO_OE 
     //it takes 190ns to go through the next instruction
-    LBBO reg_gpio1_oe, reg_gpio1_oe, 0, 4
+    LBBO r2, r2, 0, 4
 //GPIO1-start
 //process oe and datain and prepare dataout for GPIO1
-    LDI reg_gpio1_setdataout, 0 
-    LDI reg_gpio1_cleardataout, 0
-//map GPIO_ANALOG to gpio1 pins, affects reg_gpio1_oe, reg_gpio1_cleardataout, reg_gpio1_data, reg_digital
-    SET_GPIO1_BITS 13, 4
-    SET_GPIO1_BITS 12, 5
-    SET_GPIO1_BITS 28, 6
-    SET_GPIO1_BITS 18, 7
-    SET_GPIO1_BITS 15, 8
-    SET_GPIO1_BITS 14, 9
-    SET_GPIO1_BITS 19, 10
+//r7 will contain GPIO1_CLEARDATAOUT
+//r8 will contain GPIO1_SETDATAOUT
+    MOV r8, 0 
+    MOV r7, 0
+//map GPIO_ANALOG to gpio1 pins,
+//r2 is gpio1_oe, r8 is gpio1_setdataout, r7 is gpio1_cleardataout, r27 is the input word
+//the following operations will read from r27 and update r2,r7,r8
+    SET_GPIO_BITS r2, r8, r7, 13, 4, r27
+    SET_GPIO_BITS r2, r8, r7, 12, 5, r27
+    SET_GPIO_BITS r2, r8, r7, 28, 6, r27
+    SET_GPIO_BITS r2, r8, r7, 18, 7, r27
+    SET_GPIO_BITS r2, r8, r7, 15, 8, r27
+    SET_GPIO_BITS r2, r8, r7, 14, 9, r27
+    SET_GPIO_BITS r2, r8, r7, 19, 10, r27
 //set the output enable register for gpio1.
-    MOV reg_gpio2_oe, GPIO1 | GPIO_OE  //reg_gpio2_oe is now unused. It is here used as a temp
-    SBBO reg_gpio1_oe, reg_gpio2_oe, 0, 4 //takes two cycles (10ns)
+    MOV r3, GPIO1 | GPIO_OE  //use r3 as a temp register
+    SBBO r2, r3, 0, 4 //takes two cycles (10ns)
 //GPIO1-end
+// r2 is now unused
 
-// reg_gpio1_oe is now unused, its register is taken by gpio2_cleardataout
-// reg_gpio1_datain now unused, its register is taken by gpio2_setdataout
 //GPIO2-start
-//load current status of GPIO_OE in reg_gpioX_oe
-    MOV reg_gpio2_oe, GPIO2 | GPIO_OE  
+//r3 will hold GPIO1_OE
+//load current status of GPIO_OE in r3
+    MOV r3, GPIO2 | GPIO_OE  
 //it takes 200ns to go through the next instructions
-    LBBO reg_gpio2_oe, reg_gpio2_oe, 0, 4
+    LBBO r3, r3, 0, 4
 //process oe and datain and prepare dataout for GPIO2
-    LDI reg_gpio2_setdataout, 0 
-    LDI reg_gpio2_cleardataout, 0
-//map GPIO_ANALOG to gpio2 pins, affects reg_gpio2_oe, reg_gpio2_cleardataout, reg_gpio2_data, reg_digital
-    SET_GPIO2_BITS 2, 0
-    SET_GPIO2_BITS 3, 1
-    SET_GPIO2_BITS 5, 2
-    SET_GPIO2_BITS 4, 3
-    SET_GPIO2_BITS 1, 11
-    SET_GPIO2_BITS 22, 12
-    SET_GPIO2_BITS 24, 13
-    SET_GPIO2_BITS 23, 14
-    SET_GPIO2_BITS 25, 15
+//r4 will contain GPIO2_CLEARDATAOUT
+//r5 will contain GPIO2_SETDATAOUT
+    MOV r5, 0
+    MOV r4, 0 
+//map GPIO_ANALOG to gpio2 pins
+//r3 is gpio2_oe, r5 is gpio2_setdataout, r4 is gpio2_cleardataout, r27 is the input word
+//the following operations will read from r27 and update r3,r4,r5
+    SET_GPIO_BITS r3, r5, r4, 2, 0, r27
+    SET_GPIO_BITS r3, r5, r4, 3, 1, r27
+    SET_GPIO_BITS r3, r5, r4, 5, 2, r27
+    SET_GPIO_BITS r3, r5, r4, 4, 3, r27
+    SET_GPIO_BITS r3, r5, r4, 1, 11, r27
+    SET_GPIO_BITS r3, r5, r4, 22, 12, r27
+    SET_GPIO_BITS r3, r5, r4, 24, 13, r27
+    SET_GPIO_BITS r3, r5, r4, 23, 14, r27
+    SET_GPIO_BITS r3, r5, r4, 25, 15, r27
 //set the output enable register for gpio2.
-    MOV reg_gpio1_oe, GPIO2 | GPIO_OE  //reg_gpio1_oe is now unused. It is here used as a temp
-    SBBO reg_gpio2_oe, reg_gpio1_oe, 0, 4 //takes two cycles (10ns)
+    MOV r2, GPIO2 | GPIO_OE  //use r2 as a temp registerp
+    SBBO r3, r2, 0, 4 //takes two cycles (10ns)
 //GPIO2-end
+//r3 is now unused
 
-//load current inputs in reg_gpioX_datain
-    MOV reg_gpio1_datain, GPIO1 | GPIO_DATAIN 
-    MOV reg_gpio2_datain, GPIO2 | GPIO_DATAIN 
+//load current inputs in r2, r3
+//r2 will contain GPIO1_DATAIN
+//r3 will contain GPIO2_DATAIN
+//load the memory locations
+    MOV r2, GPIO1 | GPIO_DATAIN  
+    MOV r3, GPIO2 | GPIO_DATAIN  
     //takes 375 nns to go through the next two instructions
-    LBBO reg_gpio1_datain, reg_gpio1_datain, 0, 4
-    LBBO reg_gpio2_datain, reg_gpio2_datain, 0, 4
-    READ_GPIO1_BITS 13, 4
-    READ_GPIO1_BITS 12, 5
-    READ_GPIO1_BITS 28, 6
-    READ_GPIO1_BITS 18, 7
-    READ_GPIO1_BITS 15, 8
-    READ_GPIO1_BITS 14, 9
-    READ_GPIO1_BITS 19, 10
-    READ_GPIO2_BITS 2, 0
-    READ_GPIO2_BITS 3, 1
-    READ_GPIO2_BITS 5, 2
-    READ_GPIO2_BITS 4, 3
-    READ_GPIO2_BITS 1, 11
-    READ_GPIO2_BITS 22, 12
-    READ_GPIO2_BITS 24, 13
-    READ_GPIO2_BITS 23, 14
-    READ_GPIO2_BITS 25, 15
-//reg_gpio2_oe is now unused, so reg_temp1 is available for temporary storage from now on
-//reg_gpio2_datain is now unsued, so reg_temp2 is available for temporary storage from now on
+//read the datain
+    LBBO r2, r2, 0, 4
+    LBBO r3, r3, 0, 4
+//now read from r2 and r3 only the channels that are set as input in the lower word of r27 
+// and set their value in the high word of r27
+//GPIO1
+    READ_GPIO_BITS r2, 13, 4, r27
+    READ_GPIO_BITS r2, 12, 5, r27
+    READ_GPIO_BITS r2, 28, 6, r27
+    READ_GPIO_BITS r2, 18, 7, r27
+    READ_GPIO_BITS r2, 15, 8, r27
+    READ_GPIO_BITS r2, 14, 9, r27
+    READ_GPIO_BITS r2, 19, 10, r27
+//GPIO2
+    READ_GPIO_BITS r3, 2, 0, r27
+    READ_GPIO_BITS r3, 3, 1, r27
+    READ_GPIO_BITS r3, 5, 2, r27
+    READ_GPIO_BITS r3, 4, 3, r27
+    READ_GPIO_BITS r3, 1, 11, r27
+    READ_GPIO_BITS r3, 22, 12, r27
+    READ_GPIO_BITS r3, 24, 13, r27
+    READ_GPIO_BITS r3, 23, 14, r27
+    READ_GPIO_BITS r3, 25, 15, r27
+//r2, r3 are now unused
 
 //now all the setdataout and cleardataout are ready to be written to the GPIO register.
-//CLEARDATAOUT and SETDATAOUT are consecutive positions in memory, so we write 8 bytes to CLEARDATAOUT.
-//We can do this because we chose reg_gpio1_cleardataout and reg_gpioX_setdataout to be consecutive
+//CLEARDATAOUT and SETDATAOUT are consecutive positions in memory, so we just write 8 bytes to CLEARDATAOUT.
+//We can do this because we chose cleardata and setdata registers for a given GPIO to be consecutive
 //load the memory addresses to be written to
-    MOV reg_gpio1_datain, GPIO1 | GPIO_CLEARDATAOUT //reg_gpio1_datain is now unused and is used here as a temp
-    MOV reg_gpio2_datain, GPIO2 | GPIO_CLEARDATAOUT //reg_gpio2_datain is now unused and is used here as a temp
+    MOV r2, GPIO1 | GPIO_CLEARDATAOUT //use r2 as a temp register
+    MOV r3, GPIO2 | GPIO_CLEARDATAOUT //use r3 as a temp register
 //write 8 bytes for each GPIO
-//takes 30ns in total to go through the following two lines
-    SBBO reg_gpio1_cleardataout, reg_gpio1_datain, 0, 8 // takes 145ns to be effective when going low, 185ns when going high
-    SBBO reg_gpio2_cleardataout, reg_gpio2_datain, 0, 8 //takes 95ns to be effective when going low, 130ns when going high
+//takes 30ns in total to go through the following two instructions
+    SBBO r7, r2, 0, 8 //store r7 and r8 in GPIO1_CLEARDATAOUT and GPIO1_SETDATAOUT 
+                      //takes 145ns to be effective when going low, 185ns when going high
+    SBBO r4, r3, 0, 8 //store r4 and r5 in GPIO2_CLEARDATAOUT and GPIO2_SETDATAOUT 
+                     //takes 95ns to be effective when going low, 130ns when going high
 //reversing the order of the two lines above will swap the performances between the GPIO modules
 //i.e.: the first line will always take 145ns/185ns and the second one will always take 95ns/130ns, 
 //regardless of whether the order is gpio1-gpio2 or gpio2-gpio1
-JMP r28.w0 // go back to ADC_WRITE_GPIO
+JMP r28.w0 // go back to ADC_WRITE_AND_PROCESS_GPIO
 
-// DIGITAL new code ends here
-
-
-.macro HANG
+.macro HANG //useful for debugging
 DALOOP: 
 set r30.t14
 clr r30.t14
 QBA DALOOP
 .endm	
+
 // Bring CS line low to write to DAC
 .macro DAC_CS_ASSERT
       MOV r27, DAC_CS_PIN
@@ -515,12 +499,12 @@
 //TODO: it would be better to split the DIGITAL stuff in two parts:
 //- one taking place during DAC_WRITE which sets the GPIO_OE
 //- and the other during ADC_WRITE which actually reads DATAIN and writes CLEAR/SET DATAOUT
-                            //reg_digital is actually r27, so do not use r27 from here to ...
-      LBBO reg_digital, reg_digital_current, 0, 4 
-      JAL r28.w0, DIGITAL
-      SBBO reg_digital, reg_digital_current, 0,   4 
+                            //r27 is actually r27, so do not use r27 from here to ...
+      LBBO r27, r27_current, 0, 4 
+      JAL r28.w0, DIGITAL // note that this is not called as a macro, but with JAL. r28 will contain the return address
+      SBBO r27, r27_current, 0,   4 
                             //..here you can start using r27 again
-      ADD reg_digital_current, reg_digital_current, 4 //increment pointer
+      ADD r27_current, r27_current, 4 //increment pointer
 GPIO_DONE:
       ADC_WAIT_FOR_FINISH
       ADC_RX out
@@ -838,10 +822,10 @@
       MOV reg_frame_current, 0
       QBBS DIGITAL_BASE_CHECK_SET, reg_flags, FLAG_BIT_BUFFER1  //check which buffer we are using for DIGITAL
                   // if we are here, we are using buffer0 
-      MOV reg_digital_current, MEM_DIGITAL_BASE
+      MOV r27_current, MEM_DIGITAL_BASE
       QBA DIGITAL_BASE_CHECK_DONE
 DIGITAL_BASE_CHECK_SET: //if we are here, we are using buffer1 
-      MOV reg_digital_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately
+      MOV r27_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately
 DIGITAL_BASE_CHECK_DONE:
 
 WRITE_LOOP: