Time-Division Multiplexing (TDM) is a type of digital or (rarely) analog multiplexing in which two or more signals or bit streams are transferred apparently simultaneously as sub-channels in one communication channel, but physically are taking turns on the channel pLEDS pFlashA_PortB_Data pBUTTONS pFIO_FLAG_D AUDIO_IN iRxBuffer1[INTERNAL_ADC_L1] AUDIO_OUT iTxBuffer1[INTERNAL_DAC_L1] RESET_AUDIO *pDMA1_IRQ_STATUS = 0x0001 RESET_TIMER *pTIMER_STATUS = 0x0001 RESET_BUTTONS *pFIO_FLAG_C = 0x0F00 LED8 0x10 LED9 0x20 REC_LED PLAY_LED LED9 LED8 pSDRAM (volatile unsigned char *) 0x00000000 SDRAM_SIZE 0x08000000 SDRAM_SIZE = 32MBytes //--------------------------------------------------------------------------// // Init_EBIU initializes the EBIU for Flash memory and SDRAM access //--------------------------------------------------------------------------// void Init_EBIU(void) { *pEBIU_AMBCTL0 = 0x7bb07bb0; *pEBIU_AMBCTL1 = 0x7bb07bb0; *pEBIU_AMGCTL = 0x000f; //SDRAM *pEBIU_SDRRC = 0x00000817; *pEBIU_SDBCTL = 0x00000013; *pEBIU_SDGCTL = 0x0091998d; } There are also several variants on these types. All of the integer types plus the char are called the integral types. float The EBIU interfaces with various external memory such as SDRAM, ROMs, and FLASH memory. FLASH memory The FLASH memory provides the access to the LEDs. There are 2 main 'registers': FlashA_PortB_Dir and FlashA_PortB_Data. These registers have to be defined in the user code since it is not provided in the cdefBF533.h or defBF533.h. // C code #define pFlashA_PortB_Dir ((volatile unsigned char *) 0x20270007) #define pFlashA_PortB_Data ((volatile unsigned char *) 0x20270005) *pFlashA_PortB_Dir = 0x3f; // 6 LSBs represents the 6 LEDs. Set to 1 for // output *pFlashA_PortB_Data = 0x00; // Reset all LEDs to 0 (off) Programmable Flags (PFs) Each button is linked to a specific PF. Button PF# SW4 PF8 SW5 PF9 SW6 PF10 SW7 PF11 There are 4 registers that need to be configured. Each bit in the FIO_INEN register input enables the represented PF. FIO_EDGE configures the corresponding PF pin to be edge sensitive, FIO_POLAR sets the direction of the edge (positive/negative), and FIO_DIR sets the direction of the PF. // C++ code *pFIO_INEN = 0x0F00; // Set PF8-11 (all buttons) to be input enabled *pFIO_EDGE = 0x0F00; // Set PF8-11 to be edge sensitive *pFIO_DIR = 0x0000; // Set all PFs to act as inputs *pFIO_POLAR = 0x0000; // Set PF8-11 to be positive edge triggered X_INTERRUPT_HANDLER converts the user's code into an Interrupt Service Routine which saves registers and executes the RTI command, but clearing the interrupt must be handled inside the code. IVGX are general purpose interrupt signals, where X is the interrupt number ranging from 7 (highest priority) to 15 (lowest priority). All devices that require interrupts are assigned a IVG number upon reset (note: more than one interrupt can be assigned to a single IVG). Assignments can be changed by writing into the proper SIC_IAR register before enabling global interrupts The register_handler function allows the user to assign an Interrupt Service Routine to an IVG number. Assigning an interrupt to an ISR must be done before global interrupts are enabled. register_handler takes 2 parameters: register_handler(ik_ivgx, ISR_NAME); ik_ivgx is the IVG number, where x = 7 to 15. The ISR_NAME can be any name the user chooses, but must match the name provided in the EX_INTERRUPT_HANDLER. The EX_INTERRUPT_HANDLER is a defined macro located in 'sys/exception.h'. This macro assumes responsibility of saving registers and executing the Return From Interrupt (RTI) statement after the interrupt is finished. The register_handler function assigns the EX_INTERRUPT_HANDLER's code to the signal name. Blackfin supports 9 general purpose interrupts (IVG7-IVG15). Assignment to an interrupt is as follows: *pFIO_DIR = 0x0000; // Set PF8 to act as an input *pFIO_POLAR = 0x0000; // Set PF8 to be positive edge triggered *pFIO_EDGE = 0x0100; // Set PF8 to be edge sensitive *pFIO_INEN = 0x0100; // Set PF8 to enable input *pFIO_MASKA_D = 0x0100; // Assign Flag Interrupt A to PF8 SPORT Configuration registers Some of the available options on transmit and receive configuration registers are listed in the table below. Both transmit and receive share the same options, but have different names (T denoting transmit, and R denoting receive). SPORTx_TCR1 and SPORTx_RCR1 C++ Comment Clear bit to 0 def Set bit to 1 TFSR RFSR Frame sync required Does not require frame sync for every word Requires frame sync for every word ITFS IRFS Internal frame sync Use external frame sync Use internal frame sync ITCLK Internal clock IRCLK Use external clock Use internal clock TSPEN Enable RSPEN Disable transmit or receive Enable transmit or receive SPORTx_TCR2 and SPORTx_RCR2 C++ def Comment Clear bit to 0 Set bit to 1 SLEN 32 bit serial word length n/a n/a Note that you must specify the serial word length manually if you do not want a 32 bit serial word length. Information about how to do this, and other options can be found in Chapter 12 of the Hardware Reference Manual. SPORT Transmit/Receive Buffers There are 2 buffers that you can manipulate data from: SPORTx_TX and SPORTx_RX, where x = 0 or 1. Read access should not be allowed on the SPORTx_TX, and writes to the SPORTx_RX should not be allowed. Either of these conditions will produce a Peripheral Access Bus (PAB) error (more information in the hardware manual). The process of transferring data is follows: a write to the transmit buffer causes the SPORT to write out the data onto the external pins. The receiving end signals an interrupt whenever its associated buffer is full, which an ISR would commit the appropriate action on the data. Each of the transmit and receive buffers on the SPORT have a default DMA channel assigned. SPORT0_RX is on default DMA channel 1, while SPORT0_TX is on default DMA channel 2 Timers are "ivg11"; Buttons programmable flags are "ivg12” Call register_handler(ik_ivg#, YourFunction); (For example, register_handler(ik_ivg11, TimerInterrupt)) Turn on the interrupt by writing a "1" to the appropriate bit of SIC_IMASK (bit 16 for Timer0, bit 19 for the buttons). For example, *pSIC_IMASK = 0x00010000; to enable timer interrupts) To read the state of the buttons: In your code, call InitButtons(); *pFIO_FLAG_D, bits 8 - 11, read "1" for a pressed button, "0" otherwise. (For example, to look at the first button you can write: *pFIO_FLAG_D >> 8) & 0x01; To turn LEDs on and Off: Make sure that at the top of your code, you have: // addresses for Port B in Flash A (LED data) #define pFlashA_PortB_Dir (volatile unsigned char *)0x20270007 #define pFlashA_PortB_Data (volatile unsigned char *)0x20270005 In your code, call InitLEDs(); You can set turn LEDs on or off by writing 1 or 0 (respectively) to bits 0 - 5 of *pFlashA_PortB_Data, in backwards bit order. For example, *pFlashA_PortB_Data = 0x15; to turn on alternating LEDs). C Cheat Sheet Main Function void main(void) { } Printf #include <stdio.h> void main(void) { int i = 1; unsigned u = 2; long l = 3; float f = 4.0; double d = 5.0; char c = 6; unsigned char uc = 7; printf("i = %d, u = %u, l = %l, f = %f, d = %lf, c = %c, c = %d, uc = %d\n", i, u, l, f, d, c, c, uc); printf("print a tab by \t and new line by \n"); } Scanf #include <stdio.h> void main(void) { int i; printf("Print a prompt for i\n"); scanf("%d", &i); } Conditionals if(flag) { // put some statements here to execute if flag is true (flag != 0) } if(flag) { // put some statements here to execute if flag is true (flag != 0) } else { // put some statements here to execute if flag is false (flag == 0) } switch(flag) { case 0: // statements break; case 1: // statements break; case 2: // statements break; default: // statements } Looping while(flag) { // make sure there is some statement in here to change flag to become false. } for(i = 0; i < LAST; i++) { // statements } Math Functions #include <math.h> void main(void) { double th = pi/2; double x, y; // th is in radians x = cos(th); y = sin(th); th = atan2(y, x); } Creating Functions int functionname(type1 input1, ... , typeN *output1, ...); the ; int functionname(type1 input1, ... , typeN *output1, ...) { *output1 = // some function of the input variables. *output2 = // some function of the input varialbles. ... return(someintvalue); } // this is the function prototype with In the Process_Data() function, comment out the transfer of the input channels to the output channels and instead set all four channels to be a 440 Hz cosine wave with amplitude of 5,000,000. The code for this could look like this: 1. 2. 3. 4. #include <math.h> #define A 5000000000.0 #define Fs 48000.0 #define F 440.0 Sound sample you save in your buffer with samples being produced at 48KHz In Process_data.c, create a global array variable: int audio[BUFFERLEN] to save the audio inputs. In Talkthrough.h add the statements: #define BUFFERLEN 5000 extern int audio[BUFFERLEN]; This declares audio as an array of audio data that can be shared among files. References: FIO_INEN, FIO_DIR, and FIO_POLAR need to be initialized to read the buttons. See pages 14-23, 14-6, and 14-19 of the 533 Hardware Manual. EBIU_AMGCTL, EBIU_AMBCTL0, and EBIU_AMBCTL1 need to be initialized to use Flash memory, through which the LEDs are accessed. See pages 17-10 - 17-14 of the 533 Hardware Manual. SIC_IAR0, SIC_IAR1, SIC_IAR2, and SIC_IMASK need to be initialized to use interrupts. See 4-20 and 4-21 for the IVG to component mapping, and 4-30 - 4-34 (both of the 533 Hardware Manual) for initializing the interrupts. TIMER0_CONFIG, TIMER0_PERIOD, TIMER0_WIDTH, and TIMER0_ENABLE need to be initialized to use timer 0. See 15-5 and 15-10 - 15-15 of the 533 Hardware Manual.