Modulo, or circular addressing provides an automated means to support circular data buffers using hardware. The objective is to remove the need that the software has to perform data address boundary checks when executing tightly looped code as is typical in many DSP algorithms. Any W register, except W15 (used as the stack pointer), can be selected as the pointer to the modulo buffer. Also the use of W14 register as the stack frame pointer register is recommended.
A frame is a user defined section of memory in the stack that is used by a single subroutine (function). The length of a circular buffer used in modulo addressing is not directly specified. The maximum possible length is 32K words. A location in the buffer can be either 16-bit (16-bit buffer) or 8-bit (8-bit buffer). However, modulo addressing always operates with 16-bit buffers, therefore the length of the 8-bit buffers has to be even. Another restriction on the 8-bit buffers is that they can not be in the Y space, but only in the X space or in the program memory. Modulo addressing is specified by the five registers: XMODSRT, XMODEND, YMODSRT, YMODEND, and MODCON. The register XMODSRT specifies the starting and XMODEND ending address in a circular buffer in the X space, if used. The register YMODSRT specifies the starting and YMODEND ending address in a circular buffer in the Y space, if used. The register MODCON is used for enabling/disabling modulo addressing and for its configuration. The structure of the MODCON register is shown at the end of this chapter. The registers XMODEND and YMODEND contain the address of the last occupied location in the buffer. The address of the last occupied location is always odd in both 16- bit and 8-bit buffers./*dsPIC30F6014A*/ int buff[10]; //Circular buffer int i; void main(){ TRISD = 0; for(i = 0;i <= 9;i++) //Init buff buff[i] = i; YMODSRT = &buff; //YMODSRT points to the first element of buff YMODEND = &buff+19; //YMODEND points to the end address of buff MODCON = 0x80AA; //Moduo address Y space asm nop; //After changing MODCON forced nop is recommended W10 = &buff; //W10 points to the first element of buff while(1){ asm{ MOV [W10++], W5 //Copy current element to W5,prepare for next MOV #$02D6, W4 //W4 points to LATD MOV W5, [W4] //Fill LATD with item } Delay_ms(200); } }Modulo addressing hardware is enabled only with indirect addressing ([W10++]). After the registers for configuring modulo addressing have been set, indirect addressing must not be used. Since the next instruction can be compiled by using indirect addressing, it is recommended that after setting these registers NOP (non-operation) is added. This ensures that the next instruction is executed correctly.