EE 477 Final Report - Purdue University



ECE 477 Final Report

Spring 2007

[pic]

Team Code Name: Sounds Good Team ID: 7

Team Members (#1 is Team Leader):

#1: Joe Land Signature: _________________________ Date: _________

#2: Ben Fogle Signature: _________________________ Date: _________

#3: James O’Carroll Signature: _________________________ Date: _________

#4: Elizabeth Strehlow Signature: _________________________ Date: _________

REPORT EVALUATION

|Component/Criterion |Score |Multiplier |Points |

|Abstract |0 1 2 3 4 5 6 7 8 9 10 |X 1 | |

|Project Overview and Block Diagram |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Team Success Criteria/Fulfillment |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Constraint Analysis/Component Selection |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Patent Liability Analysis |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Reliability and Safety Analysis |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Ethical/Environmental Impact Analysis |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Packaging Design Considerations |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Schematic Design Considerations |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|PCB Layout Design Considerations |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Software Design Considerations |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Version 2 Changes |0 1 2 3 4 5 6 7 8 9 10 |X 1 | |

|Summary and Conclusions |0 1 2 3 4 5 6 7 8 9 10 |X 1 | |

|References |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Appendix A: Individual Contributions |0 1 2 3 4 5 6 7 8 9 10 |X 4 | |

|Appendix B: Packaging |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Appendix C: Schematic |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Appendix D: Top & Bottom Copper |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Appendix E: Parts List Spreadsheet |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Appendix F: Software Listing |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Appendix G: FMECA Worksheet |0 1 2 3 4 5 6 7 8 9 10 |X 2 | |

|Technical Writing Style |0 1 2 3 4 5 6 7 8 9 10 |X 8 | |

|CD of Project Website |0 1 2 3 4 5 6 7 8 9 10 |X 1 | |

| |TOTAL | |

TABLE OF CONTENTS

|Abstract |1 |

| 1.0 Project Overview and Block Diagram |1 |

| 2.0 Team Success Criteria and Fulfillment |4 |

| 3.0 Constraint Analysis and Component Selection |5 |

| 4.0 Patent Liability Analysis |9 |

| 5.0 Reliability and Safety Analysis |10 |

| 6.0 Ethical and Environmental Impact Analysis |13 |

| 7.0 Packaging Design Considerations |16 |

| 8.0 Schematic Design Considerations |18 |

| 9.0 PCB Layout Design Considerations |20 |

|10.0 Software Design Considerations |22 |

|11.0 Version 2 Changes |25 |

|12.0 Summary and Conclusions |25 |

|13.0 References |26 |

|Appendix A: Individual Contributions |A-1 |

|Appendix B: Packaging |B-1 |

|Appendix C: Schematic |C-1 |

|Appendix D: PCB Layout Top and Bottom Copper |D-1 |

|Appendix E: Parts List Spreadsheet |E-1 |

|Appendix F: Software Listing |F-1 |

|Appendix G: FMECA Worksheet |G-1 |

Abstract

The Digital Steerable Sound System (DS3) is designed to digitally steer sound through a pair of stationary loudspeakers. Each loudspeaker element will have its own delay and volumes control settings to direct the sound. The modern design will also incorporate a control box with a user interface. This interface will allow the user to set up the speakers in a non-idealized room and have a clear stereo image projected towards a desired location. These loudspeakers will also be time-aligned to enhance their performance.

1. Project Overview and Block Diagram

The idea behind the Digital Steerable Sound System (DS3) was to create a digitally steering loudspeaker available at the consumer level. Since the sound can be pointed in different directions, the speakers can be placed in non-ideal locations. Effectively, the sound is independent of the acoustics of the room and can be limited to only the intended users. The set of two loudspeakers and control box will be easy to use and modern in design.

Each tower contains eight steering woofers and four subwoofers. The loudspeaker will operate at nearly the full audible spectrum. The control box houses a user interface that allows the user to adjust the settings of the loudspeakers from across the room. The control box and the towers communicate wirelessly. This interface includes a display with eight touch buttons for the user to control all setup and normal operation settings. An infrared sensor is also incorporated into the control box so that a universal remote can be used to change the volume and toggle between audio inputs. In order to facilitate these requirements, the design incorporates a DSP. The DSP controls the volume, delay, equalization, and filtering of each of the eight woofers per enclosure.

[pic]

[pic]

[pic]

Figure 3 - Completed Speakers

[pic]

Figure 4 – Completed Control Box

2. Team Success Criteria and Fulfillment

The ability to receive and act upon command from an IR remote.

This PSSC was proven by showing the volume of the speakers increasing by using the volume increase on the remote control.

The ability to delay-steer the wave-front of a loudspeaker array (up/down, left/right).

This PSSC was proven by showing a change in one of the sound modes. This change produced an audible shift in the signal, which is produced by a mix of delay-steering and amplitude-shading the wave-front.

The ability to amplitude-shade the wave-front of a loudspeaker array (adjust effective array length).

This PSSC was proven by showing a change in one of the sound modes. This change produced an audible shift in the signal, which is produced by a mix of delay-steering and amplitude-shading the wave-front.

The ability to perform preset equalization.

This PSSC was proven by changing the equalization modes and noting the audible shift in the equalization.

The ability to control loudspeaker settings thorough a user interface.

This PSSC was proven by showing the volume of the speakers increasing by using the volume increase on the remote control. This was also proven by changing the equalization and sound modes.

Constraint Analysis and Component Selection

Each loudspeaker unit will contain a Digital Signal Processor (DSP) that will be used to create delays, control volume, generate filters, and allow for equalization of the loudspeaker response. The DSP will interface the CODEC which contains A/D and D/A converters. The DSP will also control an analog switch to select from two different audio inputs. Once the audio signal was processed, it would go one audio amplifier per channel, in this case, eight audio amplifiers. The user interface unit will have a microcontroller used for decoding of the IR remote, input from touch buttons, output to a built LCD display, and communicate these commands to each loudspeaker unit.

The loudspeaker system will need to be able to perform real time audio signal processing to

generate delays, each element and total volume, filters, and equalizers. The processing requires one channel audio input and eight channels audio output. Achieving all of these tasks in real time would also require a sufficient amount of computational power and memory. Selection of a DSP, CODEC, and any external memory would need to meet this criterion. The user interface would not be as demanding computationally. The microcontroller would need to IR decode, interface buttons, drive a serial to video conversion module, and communicate with the DSP in each loudspeaker.

Both the DSP and the microcontroller require general purpose I/O to interface external sources. The DSP will use most of its general I/O (16) in the parallel port to interface with the SRAM and Flash memory. This general I/O is also used for the select signals to access the memory. The microcontroller will be interfacing with an infrared receiver module, a graphical display and set of buttons for the user interface. Buttons will be read with standard I/O (8). The touch buttons are designed around the Quantum Qtouch design guide using the E240B evaluation kit [1]. The infrared receiver requires a supply voltage similar to that of the microcontroller’s in order to produce the proper voltage swing, and requires the microcontroller to sink 5 mA.

The DSP and the microcontroller require different on-chip peripheral to interface to external sources. The DSP requires the use of a standard JTEG 10 pin interface for connection to the programming/BDM module. This interface was designed with the aid of the JTEG interface reference [2]. Also required are the SPI and digital applications interface (DAI) to interface directly with the CODEC. The SPI uses 4 pins and the DAI uses 6 pins. The DSP will communicate with the microcontroller also through the SPI interface requiring 3 pins. The microcontroller will require 1 A/D pin for the IR remote sensor. Also in order to communicate with the graphical display the microcontroller will use both its transmit and receive serial communication pins at a 8N1 9600 baud communication setting through the SCI port, 3 pins. The video module requires a100 mA at 5V and connects to a television via RCA connector.

The loudspeaker unit also requires additional off-chip peripherals. The DSP will directly interface to the CODEC, in this case the Analog Devices AD1835A. This contains 2 ADC and 8 DAC channels at 24-bit 96 kHz [3]. This allows each loudspeaker to meet the requirements specified earlier of at least 1 ADC and 8 DAC channels. Each CODEC output channel will be connected to 10 W audio power amplifier used to drive each of the eight loudspeakers. The user interface use a 5.5” LCD TV monitor to display the menu generated by the serial to video converter.

This system requires the use of many power amplifiers per loudspeaker unit due to the nature of the delay steering concept. This device is an A.C. powered only and would require each loudspeaker unit to be powered separately. Eight 10 W power amplifiers are required in addition to the 55 W subwoofer amplifier used for low frequency generation. Each 10 W amplifier would consume 1.0A at +12V as calculated from the data sheet for the TPA3001D1 [4]. If all amplifiers were to be at max output it would require 8 A at +12V. Also the TPA3001D1 is a Class D audio amplifier that would operate at approximately 85% when driving a 8Ω load [4]. This amplifier uses the printed circuit board to dissipate its heat because it is so efficient and would not require a heat sink.

The loudspeaker unit was designed to be a small tower loudspeaker that would be relatively easy for a home audio consumer to move on independently. The overall enclosure would be constructed of medium density fiberboard (MDF). Each of the eight loudspeakers and the subwoofer would be individually enclosed to create separate acoustic enclosures to minimize interference between loudspeakers. The printed circuit board, power supply, and subwoofer amplifier are in a separate enclosure that has a screen on cover and will be located in the back each loudspeaker unit. The back of the loudspeaker enclosure would be for audio inputs (RCA) and an A.C. power input.

The concept of the delay steering loudspeaker is similar to one product on the market. This product is the Yamaha Digital Sound Projector with an MSRP of $1499 [5]. Our particular project contains two loudspeaker units and one separate user interface unit that can interface to a TV for setup too. The goal of our project is to create modern pair of loudspeakers that would allow the end user superior control of the sound that is economically competitive. The cost of the major components for a pair of loudspeaker units and one user interface unit are show in Appendix E.

The main component to the loudspeaker system is the DSP. Once the original design established, criteria for the DSP was established. The DSP needed to have the power to process at least 8 channels of audio in real time and easily manipulate these processes in real time. Examples of functions the DSP would need to be able to control are delay, amplitude, filters, and equalizers. When looking on the market for an audio based DSP, we narrowed the search to the TI Aureus™ TMS320DA708 and the Analog Devices SHARC™ ADSP-21262. The both DSP processor seemed capable of satisfying our specifications. Both are floating point 32 bit DSP that are available in 144-pin QFP packages targeted at low cost high performance audio applications. The Analog development environment fit the application required with our project, where as the TI development environment focused on multi-channel sound sources. The SHARC™ comes with 4Mbit ROM and 2Mbit SRAM [7] as compared to the Aureus™ which came with 64kbit ROM and 24kbit SRAM [6]. The SHARC™ was selected based on the development environment, on chip memory, and fit for our application best.

Now that the DSP was selected, the actual audio interface between the DSP and the analog audio source needed to be considered. Many different options exist such as separate ADC and DAC for each channel or one entire CODEC that includes all ADC and DAC. One CODEC seemed a really good fit, the Analog Devices AD1835A. This contains 2 ADC and 8 DAC channels at 24-bit 96 kHz [3]. This would be a simpler and more cost effective solution to use one CODEC in place of 2 ADC and 8 DACs per loudspeaker unit.

The next major component selection was the audio amplifiers used to power each element in the loudspeaker array. One major consideration is that the amplifier use only a +12V power supply to decrease power supply cost as compared to having a split power supply and that it could drive a 8Ω load. First consideration was the ST TDA2006, a Class AB amplifier, which would draw 2A at +12V requiring a heat sink compared to the TI TPA3001D1, a Class D amplifier, which is 85% efficient and would draw 1A at +12V not requiring a heat sink [4]. The TI TPA3001D1 was selected for its high efficiency and lower power consumption.

The final major component to be selected was the microcontroller. Both the Freescale 9S12 family and the Atmel ATmega16 were considered for interfacing with an infrared receiver module, a graphical display, 8 touch buttons for the user interface, and the DSP engine for each speaker tower. The 9s12 is a CISC processor and the ATmega16 is a RISC processor. Both microcontrollers have good development support for C programming and low cost. The Atmel processor was selected because it is a RISC processor and the familiarity with the C based development.

The goal of this project is to build a loudspeaker that generates a sound field that can be steered up/down and left/right through the use of a delay steering and amplitude shading. This loudspeaker system design consists of a two stereo loudspeaker units controlled by one touch button user interface unit. In addition to the loudspeaker functions, the user can use an IR remote to control the entire system and select between two audio input sources. Major design constraints such as DSP, CODEC, power amplifiers, and microcontroller were carefully considered and the appropriate components were selected in order to achieve these key aspects of this digital loudspeaker project.

3. Patent Liability Analysis

The Yamaha Digital Sound Projector line (YSP-1, YSP-1000, YSP-1100, and YSP-800) performs a similar function to our project [13]. Like our project, these speakers are self-contained units (minus the subwoofer) that use the phased speaker array technique to create zones of localized sound. In the Yamaha speakers, these “beams” reflect off surfaces of the room in which the speaker is placed in order to create faux surround sound from a single speaker system. They also have the capability to produce simple stereo effects and localized regions of sound.

Another product with similar functionality is the Pioneer PDSP-1, which uses a large number of speakers to produce a surround sound system in almost exactly the same way as the Yamaha line [12]. These two products are very similar to one another in many respects and both products have capability to be controlled by a remote control, as ours will.

Both of these products use Digital Sound Project technology licensed from 1 Ltd, who holds U.S. Patent No. 7,130,430 on a “phased array sound system,” filed on December 18, 2001 and granted on October 31, 2006 [11]. The patent describes the technique to use several speakers with digitally controlled delays in the inputs to each speaker to create localized regions of sound. The text of the abstract follows:

An array of speakers are fed from a single source of audio frequency sound but each speaker transmits the sound delayed by an amount which is determined by the distance between a particular speaker and a selected region in space, so that sound from each speaker constructively adds at the selected region in space. […] This simple technique allows audio frequency sound to be heard in only selected regions within the room or other auditory space. Multiple regions with multiple soundtracks can be created by simultaneously playing variously delayed soundtracks over each of the speakers in the array.

There is significant prior art relating to this patent. In Dr. Meyer’s dissertation, the concepts and uses of “a digitally controlled, dynamically reconfigurable phased loudspeaker array” are discussed [9]. Note the similarity between a schematic representation of the patented method (Fig. 1) and a schematic representation of a reconfigurable array in this thesis (Fig. 2) [11],[9]. Another paper, also by Dr. Meyer, details a multiple beam delay-steered system mounted horizontally on a ceiling, a specific claim made by the patent as well [10],[11].

Although our product is unlikely to be deemed sufficiently different from the technology patented by 1 Ltd., a successful court challenge is likely based on the amount of prior art. The only reason to comply with 1 Ltd.’s patent would be if it proves cheaper to license the phased array technology from 1 Ltd. that to incur legal costs associated with fighting the patent in court. The best course of action would be to simply ignore the patent, as 1 Ltd. has no legal claim to the technology.

[pic] [pic]

Figure 5 – Patent Schematic Figure 6 – Thesis Schematic

4. Reliability and Safety Analysis

The failure rate of a MOS device is defined as λp = (C1*πT + C2*πE)*πQ*πL in the Military Handbook Reliability Prediction of Electronic Equipment [14]. The ADP3336ARMZ dropout voltage regulator falls under this category. C1 is calculated by the number of transistors on the chip and is equal to .01 [15]. πT can be taken from the provided table based on the worst case junction temperature of 150°C and the structure of the chip. πT is equal to 120. C2 is based on the number of pins the chip has, specifically eight, and its surface-mount design, and is equal to .0026. The environment may or may not be climate controlled, nor will it necessarily have the clean conditions described for a “ground benign” climate. Therefore, πE is equal to 2.0 based on “ground fixed” conditions. πL is equal to 1.0 because the production life, seven years, exceeds the specified production time of two years. Finally, the device is not military certified and thus πQ is equal to 10. The TPA3001D1 audio amplifier stability properties are very similar to those of the illustrated voltage regulator. C1, by transistor count, is also equal to .01 [16]. The worst case junction temperature is also 150°C so πT is equals 120. The chip has twenty four pins and is surface mount, so through the lookup table of the military handbook C2 equals .0087. The environment is the same so πE is equal to 2.0. The production lifetime is approximately five years, πL is equal to 1.0. This chip is also not military certified and so has a πQ value of 10.

The ADSP-21262 processor is the single most complicated and essential device used in the product and its failure rate should also be addressed. The processor is a MOS device with 32 or 40 bit capability depending on how it is used [17]. Because the handbook only addresses processors with up to 32-bit operation, C1 is set to .56. πT, based on its maximum junction temperature of 125°C and MOS properties, is equal to 3.1. C2 is based on the number of functional pins the processor has, in this case 144. The table does not have an entry for this number of pins, so C2 is calculates as C2 = 2.8*10-4*1441.08 = .06. πE is, as with the other parts, 2.0. πL will be set to 2.0: the processor has been produced for over two years, but the specific packaging variant is new to the point of only being available through sampling. The chip is MIL-STD-883 certified and, from the military handbook table, πQ is equal to 2.0. Overall, the statistics available were very applicable to the parts addressed and the results can be considered accurate, if conservative. A summary of these results is available in the following table:

|Component |Description |[pic] |MTTF |

|ADP3336ARMZ |Dropout Voltage Regulator |1.2052E+01 |8.2974E+04 |

|TPA3001D1 |Audio Power Amplifier |1.2174E+01 |8.2142E+04 |

|ADSP-21262 |DSP Processor |7.4240E+00 |1.3470E+05 |

The divided functional blocks of the schematic are the power supply, the Digital Signal Processor, Audio Output, Audio Input, and the circuit to handle interfacing with the user. Possible failures are classified as either “high” or “low”, the difference being potential harm to the user. Critical high failures are to have a λ < 10-9, low failures have a λ value between 10-5 and 10-9. The schematics and failure mode tables are located in Appendix G. Block A, the power supply circuit, has the hardware to convert the standard alternating current in a given home to all of the voltage levels required by the audio and processing electronics. Possible failures include over voltage, no voltage, and noisy voltage. Over voltage has the potential to create excess heat in the regulator IC which may develop into a threat to the user. No voltage may be attributed to a shorted circuit, which can also create excess heat and damage components. It may also be indicative of a destroyed or nonfunctioning component. Noisy voltage could be caused by a poor connection or damaged or incorrect resistors or capacitors. Block B, the digital signal processor, raises the possible danger of maximum audio output. If all speakers work in phase at the maximum gain, it is possible for an output of 110 dB to be produced. This is well within the range of sound output that can cause permanent hearing damage. Possible high criticality errors that can cause this include a software error or damage to the processor in block B, damage to the digital amplifier found in audio output, or a short in audio input. A danger also exists if the user chooses to turn the audio output to a dangerous volume and is later unable to change it because of a communication error between the speakers and control box. A scenario like this may be attributed to a failure of the control box IR receiver, video output, or communications to the wireless transceiver from any of the processors. It is also notable that wireless communication failure can be attributed to other devices operating at the 2.4 GHz frequency, such as wireless video cameras. Other potential errors of less critical significance include the destruction of a particular component or connection that will cause no audio output. Obvious possibilities are improper audio inputs, extended use that may cause component failure, or a poorly soldered component. Circuit or software conditions that may cause operation failures in the IR sensor or video output will likely be caused by physical damage to the control box given that, while the circuit is much simpler, the control box is very mobile and thus subject to accidental impact. While circuit damage and the potential for excessive heat is best prevented with good design and redundant circuits, errors that could cause dangerous volume output can be handled with software that will check for communication errors or irregular swings in the audio signal.

While the Digital Sound Projector can be expected to be in a controlled environment and contains few components that are prone to failure, it does rely on a large number of duplicate components in order to achieve high quality directed sound. Some of these parts, including the ADP3336ARMZ voltage regulator and the TPA3001D1 audio amplifier can be expected to be running above ambient temperature and will be more error prone. Additionally, the required processing power necessitates complex processors such as the ADSP-21262 digital signal processor. While the analysis of these parts revealed a reasonable failure expectation, it is notable that many of these circuits are duplicated two to eight times, with some failures causing errors that are difficult to recognize. The FMECA analysis also emphasizes the complexity of the system and the possibly dangerous effects of component failure, creating a strong importance on good hardware design and software routines that will catch and prevent dangerous operation.

5. Ethical and Environmental Impact Analysis

Following is a discussion of the testing that will be performed, warning labels that should be attached to the product, cautions to the user contained in the documentation, and any added safety mechanisms necessary to ensure a safe, high-quality product..

Testing of this product is important not only to verify that the product is safe, but also to guarantee that it is reliable. All of the tests would be performed in conditions that would simulate the inside of a house since this is the operating environment for the system. The temperature range in which the DS3 can operate is 0°C - 50°C (32°F - 122°F) with a humidity range of 5% - 95%. These environmental conditions are based on the specifications for the power supply [18]. It will be important to set up rigorous software tests to verify that the product is up to the desired level of quality. Required testing includes making certain that the delays are implemented correctly so that the loudspeakers are able to steer sound as intended. The delay for each element of the loudspeakers will have to be tested independently. Amplitude shading is another important feature of the product, and therefore will have to be implemented well and tested thoroughly. Testing the amplitude shading will require verifying that the volume output of the individual elements can change independent of the other elements. One final software check is to verify what will happen in the case of a loss of power. The software will need to respond appropriately to this event, since this event is likely to happen at some point during its lifetime. In this case, the speaker will reload information from the control box. The control box will have the previous settings stored, so there should be no change from the previous state once power resumes.

While there are few warnings that need to be located directly on the loudspeakers, one example stands out. That is the label that alerts the user that prolonged exposure to high volume could result in damaged hearing. These speakers are capable of outputting sounds at the 120 dB level, which is well above the threshold at which hearing damage can occur. This label will be found on the back of the speaker, located near the cable connections. The only reason the label will not be placed more on a more visible part of the loudspeakers is to keep up the appearance of the system. With the label placed near the connections, the user who sets up the speakers will see it and will know that the loudspeakers should not be used at a high volume for a lengthy amount of time. In addition to the warning mentioned above, other warnings that the user should be aware of will be included in the user manual. One such warning is “do not bring liquids near speakers.” The obvious implications of this include damage to the boards, power supply, speaker elements, etc. In case the user is not aware of the damage that can be caused by wires that have been sliced or stripped, a that states “do not operate if wires appear to be damaged” will be included that the speakers should not be used if the cables are damaged. As noted in the Yamaha Digital Sound Projector owner’s manual [19], the user should be instructed “do not open (the casing) due to the risk of electric shock”. This will also be near the warning that there are “no user changeable parts inside,” alerting the user that there really is no reason to open the casing anyway. If there were a warranty associated with the product, it would be voided upon opening the casing, for which there would be another warning.

The last important item to discuss regarding the ethics discussion is safety mechanisms that should be put into place to prevent the user from harming themselves or the product. No safety mechanisms are built into the product. As was previously mentioned, the most likely manner in which this system could harm the user is by prolonged exposure to high volume. It will be up to the user to follow the guidelines for responsible use of the product.

When it comes to the environmental impact analysis of the DS3, it is easiest to break it down into different subsystems to study how these parts will affect the environment. The major areas that will be reviewed are the printed circuit boards (PCBs), power requirements, enclosure materials, and then the system as a whole. Discussion of each of these subsystems will detail how these components affect the environment from their manufacture, normal use, and disposal.

The PCBs will be made by [20]. According to their website, the boards will have a “lead free solder finish.” Since lead is harmful to the environment and especially dangerous to humans, this is an important step towards making a green product. It will also be important to keep the size of the PCBs as small as possible. There are a lot of components that need to go into the boards for this project, especially since each of the eight speakers has its own audio amplifier circuit. Keeping the boards as small as possible will allow for more boards to be printed in a smaller area, thus reducing waste. Another benefit to keeping the board size small is to reduce the amount of etchant needed to create the board, thus eliminating some of the waste that is generated in the board-making process. All of the components will be attached to the board with lead free solder, which also helps keep the product environmentally friendly. During the normal use of the product, the PCBs should not create any sort of environmental impact. When the product has finished its useable life, the PCBs should be sent for recycling. At a recycling center for PCBs, the metals will be removed from the board before disposal. The boards are then typically shredded and used for aggregate purposes [21].

The power requirements are another important aspect of the design. The audio amplifiers were chosen for their efficiency. Class D amplifiers are most advantageous in regards to power consumption. Each of the audio amplifiers is a Class D power amplifier, and require approximately 1.3 A [4]. Class AB amplifiers that feature the same output power, require 4 A [22]. A linear power supply was selected for this project. Each tower will have its own power supply. The control box will have its own power supply as well, a 12 V wall wart. At the end of the product lifecycle, the power supplies should be taken to an electronics recycling location to reclaim parts that could be harmful to the environment.

The wood and paint used for the enclosure of the prototype are important to mention in this analysis. The wood being used is medium density fiberboard (MDF). According to design- [23], there are some potential health risks to using this material. In some cases, formaldehyde resins are used to hold the pressed board together. These resins have mostly been phased out, however, and would not be used in production materials. Also according to the article, the environmental impact of MDF has improved greatly over the years. A lot of the materials going into MDF are recycled from other processes. The wood should not cause any harm during the lifecycle of the product and should be recycled after the speaker has run the course of its lifecycle. The BASF Limco paint that is being used for the prototype is also harmful to the environment. This paint is typically used to refinish automobiles. It contains four steps, which are an alkyd enamel, acrylic enamel, urethane, and the base coat. With the proper personal protective equipment, the paint is not harmful to the person applying it. However, the toxins that are released from the paint are damaging to the environment. This paint should not cause any problems during the life of the speakers, but care should be taken when disposing of them at the end of its life due to the impact of the paint. It is important to note that this paint would only be used for the prototype, and a more suitable paint would be used for production of the DS3.

6. Packaging Design Considerations

The controlling interface, software, and display need to be capable of displaying and changing the relatively complicated settings available in such a product, and must also be either attractive or unobtrusive. Considerations such as total size, individual speaker layout, and construction materials rely primarily on the need for parts of sufficiently high quality to promote the unique sound directing features of the project, and to also create a balance between aesthetics and overall cost.

Two forms of products that implement digitally project able sound are commercially available today. The first is a set of one or more line arrays, or columns or rows of speakers, which working together are capable of producing clearer sound in a controlled area with fewer total speakers [24]. As previously explained, these are typically implemented in medium to large scale areas and systems. The second form is that of a typically horizontal array of speakers that use similar but more complex techniques to direct and bounce sound around a room in order to produce an effect similar to that of surround sound systems. These are available and appropriate for a range of room sizes that may be found in any given house or apartment, but implement proprietary and protected algorithms which would make a similar project inadvisable given cost, time, and complexity constraints.

The packaging for this project can be divided into two sections, the structure and supporting elements of each tower and the user display elements of the control box. The body of each speaker tower will be constructed out of medium density fiberboard (MDF). MDF is dense, flat, stiff, and has no knots or voids [25]. It is very easy to machine, and cut edges will not tear like plywood. Overall, the substance is very dense, will not shake or rattle if properly mounted, is well acoustically damped, and is the standard material of choice for speaker enclosures. The power supply, digital processor, and circuit board will be mounted within the rear base of each speaker with standoffs and appropriate fasteners to make the electronics stable enough for any handling of the speakers. The speaker arrangement is chosen for the option to direct sound both vertically and horizontally. Each individual speaker is mounted into the frame of the tower with appropriate screws and an insulating adhesive. A subwoofer is included at the base of the tower. It is also notable that the nature of the speakers and insulating adhesive used, each speaker and subwoofer will be in its own isolated “chamber”, preventing vibration from interacting between speakers. 9” is the minimum width of the tower to accommodate the subwoofer and speaker arrangement, and a tower height set between 3’ and 4’ is an acceptable compromise between tower size and a minimum height to effectively project sound to specific regions of the room. A 12” square base should provide sufficient room for the subwoofer and included electronics. The control box will likely be a plastic enclosure with a Lexan plate protecting a 5.5” LCD monitor and two sets of capacitance touch buttons. Assembly can be completed with relatively simple tools including a circular and jig saw, drill, soldering iron, and wire cutters and strippers. The weight of the speaker towers can be estimated at 50 to 60 lbs each. The majority of this will be for the enclosure, which should weigh roughly 35 lbs. Dense and possibly thick versions of MDF will be used in order to prevent resonating or shaking. The power supply, subwoofer, and individual speakers will make up the majority of the remaining weight estimate. As shown in the bill of materials in Appendix B, the expected cost of each tower is about $510.

The figure in Appendix C illustrates the PCB layout required in each speaker assembly. The most important factor in placement of the parts and headers is the accessibility of the digital amplifiers, the DSP communication and programming headers, and the audio input connection. The DSP and codec chips have the form of a low form quad pack [17], [3] while each of the eight digital amplifiers are shrink small outline packages. The DSP headers make the SPI and JTAG pins available. The only restriction on the total board size is that it must fit within the 12” by 9” space at the base of the tower. If a PCB is required for the control box, the microcontroller will need a 28 to 40 pin dual in-line package or quad pack depending on the specific model and package choice [26]. It will require headers to the SPI, reset pin, and serial pins. Connectors for the infrared module, capacitance touch buttons, and a possible multiplexer will also need to be included. These consist of standard I/O ports and are variable. The main constraint is that the board and the ezVID video module, a 2” square board [27], must be able to fit in the box.

By producing a versatile digital sound projector with a range of configuration options to enable users of all skill levels, this project brings a product previously only available to public or industrial groups into the consumer market. The design constraints require a set of speaker towers and control center that are no more obtrusive than a traditional unit, but provide high quality sound with strong customization of where the output is directed and digitally modified. At the same time the speakers should be sturdy, reasonably priced, and incorporate aesthetics as is possible.

7. Schematic Design Considerations

The major components of the loudspeaker system are the DSP [17], the memory and the audio portion of the circuit. The DSP sends delays individually to the eight speaker elements. It also controls the power shading by controlling the volume of each element. There are two kinds of memory, SRAM and flash. The SRAM stores the filter coefficients and delay times. The processor boots from the flash memory into the SRAM [28]. As for the audio portion of the circuit, an analog switch is connected to the DSP through the parallel port. This switch toggles between two audio inputs. The signal leads into a 55 W Class AB power amplifier, which leads to four 8” subwoofers and also into a pre-A/D circuit. This circuit takes the unbalanced signal from the RCA input, removes any DC offset and creates a differential output, which is required by the ADC of the codec [3]. The codec converts the signal from analog to digital, passes the signal to the DSP, and then converts the signal back to analog. The codec has eight DAC channels [3], which allows for individual signals to be passed to each of the eight speaker elements. Following the codec are eight identical amplifier modules. Each consists of a post-D/A circuit, a 10 W Class D power amplifier and finally a 1” full range driver. The post-D/A mainly serves as a low pass filter that converts the differential signal output from the codec back to an unbalanced audio signal. The unbalanced audio signal is then passed to a power amplifier, which drives the speaker element.

The control box consists of a microcontroller, IR sensor, touch button interface and an interface to an LCD TV. The microcontroller is the heart of the control box. It will take the signals received by the IR sensor and touch buttons and accordingly output information to the display. The IR sensor, which receives signals at a frequency of 38 kHz as per the RC5 standard [29], receives its signal from a universal remote. The IR sensor is connected to the microcontroller through the ATD port. The user can use the remote to move through the various speaker settings. To give the user a second method of changing the speaker settings, two sets of four touch buttons and their control circuits are connected to the microcontroller via GPIO pins. The touch buttons are used in conjunction with the LDC TV to create a display featuring an ATM style setup with buttons next to the display options. The LCD TV is a 5.5” display, which is large enough to display the necessary information in a clear format. A serial to video converter converts the signal output from the SCI port of the microcontroller to color text and graphics [30].

The power supply is the other major component of this system. A linear power supply is incorporated into each of the speaker towers. The supplies are capable of switching between 120 VAC and 230 VAC inputs [18]. Various power levels will be required by the components, +12 V at 14 A, -12 V at 0.8 A, +5 V at 34 A, -5 V at 0.5 A, +3.3 V at 28 A, and 1.2 V at 500 mA. The control box will receive its power via a 12 V wall wart.

An ATmega32 microcontroller [26] is at the heart of the control box. General purpose I/O pins are used to interface with the touch buttons. There touch button kit requires simple interface between the buttons and the microcontroller. Timer 0 is an 8-bit timer which is used to determine when to change the data on the display. It checks for differences in the data to be sent to the screen as the timer overflows a number of times. Timer 1 is a 16-bit timer that is used with the IR sensor because the timer can automatically use the Input Capture Register (ICR). The value of timer 1 can be automatically captured when the interrupt high or interrupt low is triggered so the timer capturing more uniform. The interrupt pin is used in conjunction with timer 1 to measure pulse lengths from the IR sensor. This pin switches between interrupt high and interrupt low on the fly. The SPI port is used to program the microcontroller. This port remains in master mode. Finally, the SCI port communicates with the ezVID serial to video converter at a 9600 baud rate with 8-bit data packets, and 1 stop bit without parity. This communication requires both Tx and Rx for timing and command confirmation. The port can also be used to debug with a terminal application on the PC, but this requires a CMOS to RS232 converter. While debugging, the baud rate can be increased, but not when using the ezVID. Finally, the interface with each of the loudspeakers is through the SPI port.

The ADSP-21262 DSP is the other major component in the system. Most of this circuit is similar to the ADSP-21262 EZ-KIT Lite ® Evaluation System [28]. The memory (SRAM and flash) are interfaced via the parallel port. Also connected to the parallel port is the analog switch at the beginning of the audio stream. As mentioned before, this switch will determine which of the audio inputs the system will output. The 25 MHz oscillator, from which the core frequency of the processor is derived, is connected to the CLKIN pin. As expected, a JTAG header will be used to program the DSP. The codec communicates with the DSP through both the Digital Audio Interface (DAI) and through the SPI interface. The internal configuration registers of the codec are configured using the SPI port [28]. The interface between the towers and the control box is conducted wirelessly. This module is also connected through the SPI port.

8. PCB Layout Design Considerations

The power amplifiers, digital signal processor (DSP), CODEC, power supply components, and microcontroller all have specific requirements that must taken into account when designing the PCB in order insure proper operation of the loudspeaker. Both analog and digital circuits are combined onto one common board. Although on one common board, each section is split into a separate circuit. Analog circuits are more susceptible to noise than most digital circuits. Digital circuits often generate noise that can cause problems in analog circuits. Techniques for reducing ground noise should be addressed through out the layout process. One key to reducing the ground noise is to decrease inductance in the traces connecting the circuit. This decrease in inductance can be done by using short, wide traces and by using 45-degree turns instead of 90-degree turns to decrease transmission reflections [31]. Electromagnetic interference (EMI) is also another undesirable problem. One possible source of EMI is ground loops. Proper decoupling capacitor placement, commonly placed as close as possible to the integrated circuit (IC), and avoidance of creating power and ground loops are two ways to minimize EMI in the circuit [31]. The board layouts in this project use these techniques and are described in the following sections.

Another key constraint in this project is proper design the audio amplifier layout. The TI TPA3001D1, a Class D amplifier, is 75% efficient and does not require a heat sink. The TI TPA3001D1 thermally connects to the PowerPAD™ located on the bottom IC. The manufacturer recommends making a copper pour slightly larger than the PowerPAD™ and then using thermal vias (large vias) to connect to the ground plane on the opposite side of the two layer board, both at GND potential [32]. This thermally couples the audio amplifier with the PCB.

The board includes a plated through hole in each corner of the board to create a spot for the board to mount. Standard 4-40 standoffs are used to connect the PCB to the chassis. Another key is to leave 50 mils around the outside edge of the board with out copper. This part of the board gets covered with solder mask and this can help prevent possible problems, such as component failure due to placement on the edge of the board both in manufacturing.

This project is using the Analog Devices SHARC™ ADSP-21262 DSP in the 144-pin LQFP package. This PCB design has an analog section and a digital section that are isolated from each other. The DSP will be located near the center of the digital section of the board to allow access to all sides of the LQFP package. If the DSP was located in the corner of the board it would be difficult to route lines to all sides of the package. The external oscillator for the DSP requires 3.3V power with a 0.10µF bypass capacitor and must be physically close to DSP on the board. The DSP also requires that a specific number of 1000pF, 0.01µF, 0.10µF, and 10.0µF bypass capacitors be located physically close to both the 3.3V and 1.2V input power pins [28]. These capacitors are used to decouple noise in the two supply voltages. A 14-pin JTAG header should also be physically located near the JTAG port on the DSP. The DSP interfaces to both a flash and SRAM memory through the parallel port and a latch for enables. Both the memory modules and the latches need to be relatively close the DSP, but are not as critical as the oscillator and bypass capacitor locations. An additional header is added to allow use of the remaining I/O pins. Trace widths of 10 to 15 mil should be used for signal routing the near the DSP. The power traces feeding the DSP should be increased where possible.

The microcontroller selected for this project does not have as stringent layout constraints as the DSP. The entire user interface is contained on a board independent of the DSP board. The user interface contains the Atmel ATmega16, in the 44-pin TQFP package, microcontroller that interfaces to an infrared receiver module, a graphical display, 8 touch buttons for the user interface, and serially to the DSP in each loudspeaker tower. The ATmega16 requires no external oscillator circuit, because it is integrated into the microcontroller already. This user interface board contains the ATmega16 centered on a small PCB with bypass capacitors located next to the power pins and a header close to the serial port used for programming. A +5V linear regulator in a TO-220 package is used for the power to the board and located near the edge to allow for the use of an external heat sink if necessary. Similar to the DSP, trace widths of 10 to 15 mil should be used for signal routing the near the microcontroller while increasing the size of the power traces where possible.

This system requires the use of many power amplifiers per loudspeaker unit due to the nature of the delay steering concept. The DSP/Audio Amplifier board requires +12V at 8A, +5V at 1A, +3.3V at 500mA, and +1.2V at 500mA. Due to the large power requirement, a separate enclosed power supply is used to provide the +12V. Linear voltage regulators are used to create the +5.0V, +3.3V and the +1.2V. The +12V line should enter the board through a 16 gauge wire that feeds directly into the power trace on the board. This power trace needs to be very large to handle the large DC current needed to supply all eight audio amplifiers. Using a trace width calculator online, a minimum trace width of 104 mils was recommend for a temperature rise of 10°C from an ambient temperature of 25°C [33]. Each 10 W amplifier would consume 1.0A at +12V as calculated from the data sheet for the TPA3001D1 [4]. If all amplifiers were to be at max output it would require 8 A at +12V. This trace needs to be at least 100 mils wide and larger if possible. Also, four 100uF capacitors are added throughout the +12V trace to assist in supplying current when all amplifiers are operated at max with an input music signal. The +5V and the GND signal enter the board through a header. The +5V supply then connects to the +3.3V voltage regulator and the +1.2V voltage regulator. Trace width of 20 to 50 mils should be used for power routing each supply voltage on the board. This width is limited by the maximum trace allowed to exit each pad for a given component. After all components are placed and routed in layout, a copper pour is added over the entire board. This copper pour is then connected to the GND, forming a ground plane on the entire board. The ground place is on both the top and bottom of the board and then stitched together using free vias.

The board is designed to minimize EMI and ground noise in the circuit. Many different design aspects must be considered developing the printed circuit board (PCB) layout for this particular project. Trace widths, signal routing, and ground planes are also key elements of the PCB that must be addressed in order to have a successful design. In order to achieve these key elements, different design constraints must be in place when designing the PCB.

9. Software Design Considerations

The software needed for the DS3 falls into two categories: interfacing and audio processing. The requirements for each are different, and the software for each needs separate treatment. Whereas the design considerations for the audio processing are primarily driven by the need to perform a large amount of computational work sufficiently quickly to avoid a loss of audio quality, the requirements of the interfacing necessitate a solution capable of providing control over a wide variety of both internal and external peripheral devices and coordinating their operation.

The software for the audio processing runs on a SHARC DSP, chosen for its processing power [36]. The SHARC boasts hardware support for integer, fixed-point, and IEEE 754 32-bit floating point arithmetic, at a maximum sustained calculation rate of 800 MFLOPS and 400 MMACS when running at 200 MHz. It uses Harvard architecture, dividing its memory into program and data memory, and it also features a DMA controller that can move arbitrarily sized blocks of memory to or from any of the peripherals while the processor continues with other calculations [34] [35]. The SHARC has 1 Mbit of on chip SRAM each for program and data memories, but must be booted from external Flash. External SRAM is also required by the Flash programmer application. Note that even though the two memory banks are nominally for program memory and data memory, either bank can hold code or data. This is very important for optimization. For example, the equalizer puts the delay line in data memory and the coefficients in program memory. In this way the DSP can access both sets of data simultaneously, instead of loading each one individually. This halves the time needed to complete the entire loop.

The software running the DSP is a real-time, interrupt-driven system. When the codec sends an audio sample to the DSP, it generates an interrupt. The data is equalized using a FIR filter, and then the equalized output is placed in another delay line. The delay values for each speaker element determine which index of the delay line is used to output data to the speaker elements. Outside of the audio interrupt, the DSP monitors the wireless module’s data-ready line, and clocks data in when it goes high. The DSP will ensure data integrity, requesting a re-transmit if needed, and then use the data received to adjust the steering of the sound, equalizer, volume, etc. The coefficients needed to generate the delays and amplitude shading used for steering will be stored in look up tables loaded into memory via the DMA. If any calculations are needed (such as for an equalizer) this will be performed in the main loop outside of any interrupts. The loading of new delays and generation of the new coefficients is not time critical, as there is a considerable amount of CPU time available until the end user would notice any lag.

To perform its function, the DSP software makes use of many of the on-chip peripherals. The codec chip being used for AD and DA uses three serial ports (SPORT0 through SPORT2) and the SPI port. The wireless connection between the microcontroller and DSP also interfaces through the SPI port. Flash memory will interface through the parallel port (though SPI Flash has not been ruled out entirely). The DSP also has provision for attaching a JTEG header to the chip, which allows us to program and debug using the same tools as are available for the development board as well as giving us a convenient method for in-circuit programming the Flash.

The Atmel processor running the interfacing code will need a wide variety of peripherals [37]. The SCI interface is used to interface to the TV/LCD display and SPI port to send and receive data via the wireless module. Additionally general purpose I/O pins are needed to read the status of the buttons and an external IRQ is needed to correctly decode data from the IR receiver.

The interface software is a command driven and polled system. The IR receiver needs to generate an interrupt for accurate timing (possibly in conjunction with the timer module), but when a whole command is received, a flag will be set that will be processed in the main loop. The buttons can be polled periodically in a similar fashion. These are the only inputs that can cause the system to change state, and the system is not time-critical. The interface software also needs to have the capability to retransmit lost packets. The system can be programmed in circuit using the SPI interface, and external components (aside from maybe an external oscillator) are not required.

The interface software sits in an idle loop polling flags. When the IR module detects a change in the signal, an interrupt is generated. The length of this pulse is timed to detect a one or zero in the command sequence. When enough bits are detected for a command to be recognized, the corresponding flag is set. When a flag indicating that a either a button on the control box has been pressed or an IR command has been received is set, the user interface is updated accordingly, and if needed, data is sent to the speaker units to indicate the change in settings.

If the speaker box transmits data, the system will enter an interrupt where it will process the data received, triggered by an external IRQ connected to the wireless module. The only data received by the speaker should be acknowledge or resend requests. In the case of the former, the next set of data in the buffer will be sent, while in the case of the latter, the last data will be resent.

10. Version 2 Changes

If going through this design effort again, there a few changes would be made. This first change would be use a touch screen interface for the control box instead of the video screen and touch buttons with the serial to video module. After ordering the parts for the touch button and video screen, a touch screen was found which would have been easier to implement and cheaper than the combination of parts that was purchased.

The DSP would also change during the second version. The new selection would be Analog Device’s Sigma DSP (AD1859) instead of their SHARC DSP (ADSP-21262). The Sigma incorporates the codec into the chip, creating a “digital audio playback subsystem on a single chip.”[38]

Summary and Conclusions

The Digital Steerable Sound System (DS3) is a loudspeaker system that can be used to point sound in any direction. The idea behind this concept is that the speakers can be placed in non-ideal room settings. Effectively, the sound is independent of the acoustics of the room and can be limited to only the intended users. The typical customer for this type of system is one that would purchase high-end audio equipment for use in the home. This system would work well in the average living room or even in an in-home movie theater. As was previously mentioned, the goal of this product was to develop a loudspeaker system that could direct sound based on the user’s input. This steering is possible up and down as well as left and right. One of the other features incorporated into the project is a control interface for the user to step through the speaker settings. This unit is separate from the towers and communicates with them wirelessly. The user can also adjust settings via an infrared remote control. Another feature of the system is to amplitude shade the wave-front. This is done by altering the volume of the individual woofers. The final feature was also mentioned previously. This feature consists of preset equalization modes from which the user may select how they would like audio to be output.

Throughout this project, many new skills and concepts have been learned. Of course further audio knowledge was picked up by everyone on the team. By figuring out how to change the different sound modes via delay-steering and amplitude-shading the team learned a lot about audio technology. The team also learned quite a bit about DSP’s and how to incorporate them into a design. Prior to this course no one on the team had any experience with them, but now the team is able to successfully use one to control the output of the speakers. Finally, this project taught the team a lot about working together to bring about the final product. The whole team realized early on that it was important to be working on the project extensively throughout the semester. By setting goals and keeping them (for the most part), the team was able to prove the concept behind this large project in only sixteen weeks.

References

1] Quantum Research Group. (2005) Secrets of Success Qtouch Design. [online]. Available:

2] Analog Devices. (2004) Analog Devices JTEG Emulation Technical Reference. [online]. Available:

3] Analog Devices (2003 Dec.) AD1835A Data Sheet. Rev. A. [online] Available:

4] Texas Instruments. (2002) TPA3001D1 Data Sheet. [online] Available:

5] Yamaha Electronics Corporation. (2006) YSP-1100 Brochure. [online]. Available:

6] Texas Instruments. (2005) Aureus™ TMS320DA708 Features. [online]. Available:

7] Analog Devices. (2003) ADSP-21262 Product Highlights. [online]. Available:

8] ST. (2003) “TDA2006 Data Sheet,” [online]. Available:

9] Meyer, D.G., “A Multi-Microprocessor Controlled Dynamically Reconfigurable Phased Loudspeaker Array for Sound Reinforcement Applications,” Ph.D. dissertation, Dept. Elec. Eng., Purdue University, West Lafayette, IN, 1981.

10] Meyer, D.G., “Multiple-Beam, Electronically Steered Line-Source Arrays for Sound-Reinforcement Applications,” Journal of the Audio Engineering Society, Vol. 38, No. 4, pp. 237-249, Apr. 1990.

11] Milsap, J. P., “Phased array sound system,” U.S. Patent no. 7130430, Oct. 2006.

12] Pioneer Europe. PDSP-1 Loudspeakers – Pioneer Product Archive. [online]. Available:

13] Yamaha. (2006). YAMAHA :: YSP-1. [online]. Available:

14] Department of Defense. (1990). Jan. Military Handbook Reliablity Prediction of Electronic Equipment. [online]. Available:

15] Analog Devices. (2000). AD3336 Datasheet. [online] Available:

16] Texas Instruments (2006 Jul.). 20-W Class-D Audio Power Amplifier. [online]. Available:

17] Analog Devices. (2005 Oct.) ADSP-21262 Data Sheet. Rev. B. [online] Available:

18] Power-One. Linear Power Supplies Data Sheet. [online], Available:

19] Yamaha Corporation. YSP-1000: Digital Sound Projector Owner’s Manual. [online]. Available:

20] Advanced Circuits. Circuit board equipment for testing and fabrication of pcbs. [online], Available:

21] The A to Z of Materials. Computer and Electronic Scrap Recycling”. [online]. Available:

22] National Semiconductor. LM1875. [online], Available:

23] Design Technology Department. Medium Density Fibreboard. [online], Available:

24] Audio Engineering Society, (2001 Nov. 30). Directional Radiation Characteristics of Articulating Line Array Loudspeaker Systems. [online]. [online]. Available:

25] Wikipedia, (2007 Jan. 23). Medium Density Fibreboard, [online]. Available:

26] Atmel Corporation. (2006 Oct.) ATmega32(L): Summary. Rev. J. [online]. Available:

27] Multilabs. (2004). ezVID Serial Video Module. [online]. Available:

28] Analog Devices. (2006 Aug.). ADSP-21262 EZ-KIT Lite® Evaluation System Manual. Rev 3.0. [online]. Available:

29] Spark Fun Electronics. (2004 Mar.). TRF-2.4G Reference Guide. Rev 1.01. [online]. Available:

30] MULTILABS. (2004). ezVID User Manual. Rev. B.[online]Available:

31] Freescale. (1995) Freescale Semiconductor Application Note AN1259. Available:

32] Texas Instruments. (2006) PowerPAD™ Layout Guidelines SLOA120. Available:

33] Advanced Circuits. (2007) Online Trace Width Calculator. Available:

34] Analog Devices, “ADSP-2126x SHARC DSP: Core Manual,” [Datasheet], Analog Devices, 2004.

35] Analog Devices, “ADSP-2126x SHARC Processor: Peripherals Manual,” [Datasheet], Analog Devices, 2005.

36] Analog Devices, “SHARC Embedded Processor: ADSP-21262,” [Datasheet], Analog Devices, 2005.

37] Atmel, “ATmega64: 8-bit AVR Microcontroller with 65K Bytes In-System Programmable Flash,” [Datasheet], Atmel, 2006.

38] P. Predella. Single-Chip Digital Stereo Subsystem. Analog Dialogue. [online]. Available:

Appendix A: Individual Contributions

A.1 Contributions of Joe Land:

For over 12 years now, I have been fascinated by loudspeaker design. As I progressed through my electrical engineering courses, I had always wanted to develop a modern loudspeaker system for my Senior Design Project. After reading about line arrays and building two different pairs of line array loudspeakers, I thought I would design a new system based on traditional loudspeaker styling, with a new twist. This was to use an eight element loudspeaker array and try to recreate the effects of a larger line array. This design project focused on building a loudspeaker that generates a sound field that can be steered up/down and left/right through the use of a delay steering and amplitude shading. This loudspeaker system design uses two stereo loudspeaker units controlled by one touch button user interface unit. After coming up with the initial design, I convinced my three team members that this would be a fantastic Senior Design Project.

During the project, I contributed by designing and developing all of the hardware systems, designing and building the physical enclosures for the loudspeakers and control units, designing and simulating the acoustical aspect of the loudspeaker system, and all wiring involved with the construction of the loudspeakers. After researching different types of digital signal processors available on the market, I selected the Analog Devices SHARC™ processor do to its development environment. Once we found the development kit in lab, I started looking into the different possibilities for audio power amplifiers that we could use for the project. After considering a Class AB and Class D amplifiers, I selected a TI Class D amplifier because of its low external parts count, high efficiency, and its power output. Next after using most of the same design as the development kit, I added in a new power regulation design and the audio amplifiers to the entire system. Once the schematic was developed with Elizabeth, I began assignment of component footprints and started the design of the PCB layout. This was a very challenging design because of the mixed signal nature of the board. I chose to make a two separate ground planes and spent 76 hours creating the board design.

Over my spring break, I designed and built the loudspeaker enclosures. This was fun to watch the design finally come to life. I have developed a construction process for loudspeaker enclosures and painting over the past 4 years that I applied to the construction of this loudspeaker system. After we received the PCB, I worked with Elizabeth to populate the PCB with all of its components. I troubleshoot a few problems with the board design and modified the design for the second PCB. During the stuffing of the board, I soldered 98% of the components onto both boards. Once the PCB was testing and functioning properly, I loaded into the rear of the loudspeaker enclosures. At this point I had wired all of the AC and other circuits needed to make the loudspeaker function properly.

Once the loudspeaker was working with the control box, Ben and I began to tweak the loudspeaker settings. I designed all of the sound modes that are currently implemented in the loudspeaker system with a spreadsheet I developed to predict the steering of the sound. This was a tremendous project that I spent over 377 hours during the semester. I was excited to see this loudspeaker system working after all of the effort put into the project. It was also exciting to see an idea I had on paper for a long time final become a fully functional product.

A.2 Contributions of Ben Fogle:

My largest contribution was in implementing DSP related functionality, most notably the software. In addition to writing all the audio processing and peripheral interface software, I also wrote several utility programs, including a Flash memory programmer and a Flash memory test. All of the code was placed in a CVS repository he set up for easy retrieval of older versions and convenient remote access.

The software had to interface with the codec using a combination of the SPI and three I2C interfaces, interface with the wireless using the SPI and three GPIO pins, and interface with the memory using a parallel bus. For audio processing, the software had to implement cascaded biquad filters to adjust the speaker response and apply equalizers to the sound output. It also had to implement a delay line and amplitude shading for steering the sound. All of these functions had to be done sufficiently quickly or in such a way as to avoid degradation of the sampled audio stream. A large amount of time was spent getting the wireless module to work correctly. The wireless module has very slow timing requirements compared to the DSP and a function to implement long waits (~100 ms maximum) while still allowing audio processing interrupts to proceed without losing accuracy was developed. I also devised a communication protocol between the control box and the speakers allowing for separate control of each speaker and verification of data integrity.

The Flash programmer had to take the output of the compiler, linker, and loader and program it into the Flash along with data describing the equalizers, delays, and amplitude shading. All of the data to be programmed needed to be stored in external SRAM, which required me to define memory segments for each block of data to be programmed, because the linker cannot correctly calculate the address of external memory unless it is at the beginning of a segment (whose address is manually specified).

I was also responsible for learning the development tools for the DSP and its architecture. It was important to learn how the compiler used the super-Harvard architecture of the DSP to produce optimized code in order to make code execute fast enough to keep up with the sample rate. Optimization related extensions to the language were also needed. Although the software was written in C++, I had to learn a small amount of SHARC assembly to understand some of the assembly language examples provided by Analog Devices. I also needed to understand how memory organization was influenced by extensions to the C/C++ language, and how other extensions and built-in functions allowed me to work with non-memory-mapped system registers. The output of the loader, a utility that produces a file suitable for loading from Flash, also needed to be learned, as the Flash programmer needed some special settings to produce a file suitable for use with my custom programmer. A feature that appears to be unique to Analog’s DSPs is the signal routing unit, which routes functional blocks to physical pins at run-time. The signal routing unit took some time to understand and make functional.

I was responsible for the selection of the memory chips used in the final design, as we were unable to obtain the exact part used in the development kit. The different Flash memory had a slightly different programming interface which necessitated further modifying the Flash programmer. I also soldered components onto the final PCB and buddy board and helped add fly wires to repair the PCB. I also helped troubleshoot the PCB.

A.3 Contributions of James O’Carroll:

As the final member of the group, added on the first day of class, my first task was to make clear my specific skills and abilities to the rest of the group in relation to what I had learned about the project.  Having explained that I was specifically capable with the Atmel series of microcontrollers and could personally handle any software aspects of the project relating to communicating with peripherals, the team eventually decided upon a method for a user to change and view the numerous setting possibilities the speakers would have: the control box.  The control box has been my primary responsibility for the duration of the class, and for the greater part of the class it was largely independent of progress on the speaker towers.  In addition to this I made an initial form of the team website and later maintained and added content to the newer website that Joe developed.  Finally, I contributed as required to team presentations, reports, and the technical challenges of communication between the SHARC and Atmel processors.

            In the earliest part of the semester, I focused on portions of the control box that were not subject to change, specifically communication with a standard infrared remote control and communication with the speaker tower.  I personally selected a standard infrared receiver module and the Philips RC5 IR communication scheme and over the first half of the semester developed a robust algorithm for receiving and processing the received signals.  To communicate with the speaker tower, I proposed using the TRF 2.4G transceiver module.  It is worth expressing here that this module has a communication scheme that is fairly complex, has moderately poor documentation, and is very difficult to debug.  Hence, I spent a good deal of time attempting to make successful transmissions between two modules.  When I eventually succeeded I expanded the algorithms to the communication scheme proposed by Ben.  When communicating between the SHARC and TRF proved difficult, I developed a microcontroller program to emulate the TRF and learn firsthand what the specific problems were.  Finally, the team eventually decided to use an ezVID video module and embedded television to display data to the user.  I had initially written a very complex function involving variable input arguments and dynamically allocated space in order to introduce a layer of abstraction into the fairly specific requirements of the ezVID, but had to discard it in favor of a less capable program in order to allow for saving long term variables in flash memory.  The better part of my time in the final weeks of the

class were spent bringing the independent software functions together into one package, testing communications between the two processors before and after the decision to make communications only one way, and some changes to the menu system to accommodate an additional set of touch buttons that were to be added.  My main administrative task was to maintain the group website, adding links to homework assignments, documents, pictures, and so on.

A.4 Contributions of Elizabeth Strehlow:

I was responsible for various tasks throughout the duration of this project. Some of these tasks include working on the schematics and PCB layout, helping populate the board, creating the final video, and helping with some of the more administrative tasks such as documentation.

At the start of the project the team was building off of Analog Device’s EZ-KIT Lite development board. My task was to recreate the portions of their board that we would be replicating for our design. I also helped set up some of the footprints for the resistors and capacitors. For my part with the PCB layout, I assisted the team leader in laying out the amplifiers along one side of the board. The amplifiers were laid out based on the advice from Texas Instruments. The last part I had with the schematics and PCB layout was to work on the parts list for ordering the parts. Since there were almost 600 components on each board it was important to group the parts by their like components to make ordering easier.

One of the challenges associated with this project was the large number of parts. During the time that the boards were being populated, I helped keep the parts organized and assisted the team leader to populate the boards. My role in this was mostly to make sure he had the correct parts in hand and help him determine where to place each part. I was also there to look up datasheets to ensure that the parts were being placed in the correct orientation. While the first board was being populated, I also helped keep track of changes we wanted to make to the PCB design before sending out for the second board and then helped the team leader implement the necessary changes.

Since I own a video camera, I took on the responsibility of creating the video to demonstrate the project. I used video editing software that was on my computer. Unfortunately with the idea of the project it was difficult to prove the PSSC’s with the microphone built into the camera.

While I was not the team leader on this project, I did help him with organization and keeping track of what was going on. Starting at the beginning of the semester I took notes of each of our team meetings to ensure that everyone was on the same track. I also wrote up the first few homework assignments based on our discussion from those first few meetings. From that point on I was there to help remind the team when assignments were due and who was responsible for each of them. While everyone contributed to the mid-semester design review, I put together the actual presentation and made sure the team had the appropriate documentation ready for the presentation itself. I also took on the role of organizing the final documentation for the project. This task involved creating the first draft of the user manual and senior design report as well as compiling the edited homework assignments from the rest of the team members.

Appendix B: Packaging

[pic]

[pic]

Appendix C: Schematic [pic]

[pic]

[pic]

[pic]

[pic]

[pic]

[pic]

[pic]

[pic]

Appendix D: PCB Layout Top and Bottom Copper

[pic]

Figure 18 – Top Copper Pour (First Board)

[pic]

Figure 19 –Bottom Copper Pour (First Board)

[pic]

Figure 20 – Top Copper Pour (Second Board)

[pic]

Figure 21 –Bottom Copper Pour (Second Board)

Appendix E: Parts List Spreadsheet

|Vendor |Manufacturer |Part Number |Description |Price Each|Quantity |Total Cost|

|Mouser |AVX |08051C103KAT2A |Multilayer Ceramic Chip Capacitor |0.17 |12 |2.04 |

| | | |(MLCC) 0805 0.01uF 100volts X7R 10%| | | |

|Mouser |Murata |GRM21BR61A106KE19L |High Capacitance SMD Ceramic Chip |0.48 |7 |3.36 |

| | | |Capacitors 0805 10uF 10volts X5R | | | |

| | | |10% | | | |

|Mouser |AVX |08055C221KAT2A |Multilayer Ceramic Chip Capacitor |0.17 |8 |1.36 |

| | | |(MLCC) 0805 220pF 50volts X7R 10% | | | |

|Mouser |Kemet |C0805C104K5RACTU |0805 SMD Ceramic Chip Capacitors |0.06 |31 |1.86 |

| | | |50volts 0.1uF X7R 10% | | | |

|Mouser |Kemet |C0805C104K5RACTU |0805 SMD Ceramic Chip Capacitors |0.06 |1 |0.06 |

| | | |50volts 0.1uF X7R 10% | | | |

|Mouser |AVX |TPSD476K016R0150 |SMD Tantalum Capacitors 47uF 16V |2.34 |1 |2.34 |

| | | |10% L ESR | | | |

|Mouser |AVX |08055A471JAT2A |Multilayer Ceramic Chip Capacitor |0.17 |1 |0.17 |

| | | |(MLCC) 0805 470pF 50volts C0G 5% | | | |

|Mouser |TDK Corp |C1608C0G1H680J |0603 Ceramic Chip Capacitors 0603 |0.08 |1 |0.08 |

| | | |68pF 50volts C0G 5% | | | |

|Digi-Key |Panasonic-ECG |EEE-0JA470WR |CAP ELECT 47UF 6.3V VS SMD |0.16 |1 |0.16 |

|Mouser |AVX |TAJB225K035R |SMD Tantalum Capacitors 35V 2.2UF |0.53 |1 |0.53 |

| | | |10% | | | |

|Digi-Key |AVX |08055A331JAT2A |CAP CERM 330PF 5% 50V NP0 0805 |0.11 |8 |0.88 |

|Mouser |Kemet |C0805C681J5GACTU |0805 SMD Ceramic Chip Capacitors |0.30 |12 |3.60 |

| | | |50volts 680pF C0G 5% | | | |

|Mouser |Murata |GRM2165C2A101JA01D |0805 SMD Monolithic Ceramic Chips |0.10 |4 |0.40 |

| | | |0805 100pF 100volts C0G 5% | | | |

|Mouser |AVX |12061A101JAT2A |1206/1812 SMD Ceramic Capacitors |0.25 |14 |3.50 |

| | | |1206 100pF 100volts C0G 5% | | | |

|Mouser |AVX |12061A221JAT2A |1206/1812 SMD Ceramic Capacitors |0.25 |9 |2.25 |

| | | |1206 220pF 100volts C0G 5% | | | |

|Digi-Key |AVX |12065A222JAT2A |CAP CERM 2200PF 5% 50V NP0 1206 |0.59 |8 |4.69 |

|Digi-Key |Panasonic-ECG | EEE-1CA100SR |CAP ELECT 10UF 16V VS SMD |0.14 |12 |1.73 |

|Digi-Key |Panasonic-ECG |ECJ-2VF1C474Z |CAP .47UF 16V CERAMIC Y5V 0805 |0.06 |16 |0.90 |

|Vendor |Manufacturer |Part Number |Description |Price Each|Quantity |Total Cost|

|Mouser |AVX |08055C102JAT2A |Multilayer Ceramic Chip Capacitor |0.37 |16 |5.92 |

| | | |(MLCC) 0805 1000pF 25volts X7R 5% | | | |

|Mouser |AVX |LD02YC102KAB2A |MLCC Tin/Lead Termination "B" |0.27 |20 |5.40 |

| | | |16volts 1000pF 10% 0402 X7R | | | |

|Mouser |NTE |SMC1206J121 |replacement Capacitors 1206 120pF |0.14 |2 |0.28 |

| | | |50volts NP0 5% | | | |

|Digi-Key |AVX |08055A102JAT2A |CAP CERM 1000PF 5% 50V NP0 0805 |0.22 |4 |0.88 |

|Mouser |Kemet |C0805C300J1GACTU |: 0805 SMD Ceramic Chip Capacitors |0.28 |1 |0.28 |

| | | |100volts 30pF C0G 5% | | | |

|Mouser |TDK Corp |C2012X7R1E105K |High Capacitance SMD Ceramic Chip |0.35 |55 |19.25 |

| | | |Capacitors 0805 1uF 25volts X7R 10%| | | |

|Mouser |AVX |080560106KAT2A |0805 SMD Ceramic Capacitors 0805 |1.10 |2 |2.20 |

| | | |10uF 6.3volts X5R 10% | | | |

|Mouser |AVX |1206YD106KAT2A |Multilayer Ceramic Chip Capacitor |2.40 |2 |4.80 |

| | | |(MLCC) 1206 10uF 16volts X5R 10% | | | |

|Digi-Key |Panasonic-ECG |ECJ-2VF1C224Z |CAP .22UF 16V CERAMIC Y5V 0805 |0.06 |16 |0.93 |

|Mouser |Kemet |T491D106K035AT |SMD Tantalum Chip Capacitors 35V |0.48 |8 |3.84 |

| | | |10uF 10% | | | |

|Jameco |Jameco Valuepro |100UF/16V 6X7 |CAP,RADIAL,MINI,7MM,100uF16V |0.15 |5 |0.75 |

|Digi-Key |Panasonic-SSG |LN1261CTR |LED RED GW-TYPE SMD NO HDR/TRLR |0.33 |1 |0.33 |

|Digi-Key |Infineon Technologies |BAS16INCT-ND |DIODE SWITCHING 85V SOT-23 |0.16 |1 |0.16 |

|Digi-Key |Vishay/General |SL22-E3/52T |DIODE SCHOTTKY 2A 20V SMB |0.43 |1 |0.43 |

| |Semiconductor | | | | | |

|Digi-Key |Micro Commercial Co. |1N4002-TP |RECTIFIER 1A 100V DO-41 |0.04 |2 |0.09 |

|Digi-Key |Diodes Inc |B130-13 |DIODE SCHOTTKY 30V 1A SMA |0.58 |16 |9.28 |

|Digi-Key |TDK Corp |445-2014-1-ND |INDUCTOR SHIELD PWR 10UH 7045 |1.31 |1 |1.31 |

|Digi-Key |TDK Corp |445-2029-1-ND |INDUCTOR SHIELD PWR 6.8UH 7045 |1.31 |1 |1.31 |

|Digi-Key |Steward |240-2390-1-ND |FERRITE CHIP POWER 600 OHM SMD |0.11 |4 |0.45 |

|Mouser |Fair-Rite |2512067007Y3 |EMI Shield Beads 1206 Z=70@100MHz |0.30 |16 |4.80 |

|Digi-Key |STMicroelectronics |497-2539-5-ND |TRANS NPN DARL 60V 5A TO-220 |0.74 |1 |0.74 |

|Vendor |Manufacturer |Part Number |Description |Price Each|Quantity |Total Cost|

|Mouser |Vishay/Dale |CRCW080510R0FKEA |0805 Thick Film Chip Resistors |0.05 |1 |0.05 |

| | | |1/8watt 10ohms 1% | | | |

|Digi-Key |Vishay/Dale |CRCW080533R0JNEA |RES 33 OHM 1/8W 5% 0805 SMD |0.04 |2 |0.08 |

|Digi-Key |Vishay/Dale |CRCW08054K70JNEA |RES 4.7K OHM 1/8W 5% 0805 SMD |0.04 |1 |0.04 |

|Mouser |Xicon |292-210K-RC |1/10W 1% 0805 Chip Resistors |0.04 |2 |0.08 |

| | | |1/10WATT 210KOHMS | | | |

|Mouser |Vishay/Dale |CRCW080564K9FKEA |0805 Thick Film Chip Resistors |0.05 |2 |0.10 |

| | | |1/8watt 64.9Kohms 1% | | | |

|Mouser |KOA Speer |RK73H1JTTD2492F |: 0603 SMD Thick Film Chip |0.08 |1 |0.08 |

| | | |Resistors 1/10watts 24.9Kohms | | | |

|Digi-Key |Yageo Corporation |RC0603FR-0780K6L |RES 80.6K OHM 1/10W 1% 0603 SMD |0.08 |1 |0.08 |

|Mouser |KOA Speer |RK73H2ATTD2553F |0805 SMD Thick Film Chip Resistors |0.08 |1 |0.08 |

| | | |1/8watts 255Kohms 1% | | | |

|Digi-Key |Vishay/Dale |WSL0805R0500FEA |RES .05 OHM 1/8W 1% 0805 SMD |1.02 |1 |1.02 |

|Mouser |Xicon |290-10K-RC |1/8W 1% 1206 Chip Resistors 1/8WATT|0.05 |2 |0.10 |

| | | |10KOHMS 1% | | | |

|Digi-Key |Vishay/Dale |CRCW08051K00FKEA |RES 1.00K OHM 1/8W 1% 0805 SMD |0.04 |4 |0.16 |

|Digi-Key |Yageo Corporation |RC0805FR-076K04L |RES 6.04K OHM 1/8W 1% 0805 SMD |0.08 |3 |0.24 |

|Digi-Key |Yageo Corporation |RC1206FR-074K7L |RES 4.70K OHM 1/4W 1% 1206 SMD |0.09 |1 |0.09 |

|Digi-Key |Yageo Corporation |RC1206FR-07200RL |RES 200 OHM 1/4W 1% 1206 SMD |0.09 |1 |0.09 |

|Digi-Key |Yageo Corporation |RC1206FR-07200KL |RES 200K OHM 1/4W 1% 1206 SMD |0.09 |1 |0.09 |

|Mouser |Xicon |263-0-RC |1206 SMD Chip Resistors 1/8WATT |0.05 |17 |0.85 |

| | | |0OHMS 5% | | | |

|Mouser |Vishay/Dale |CRCW120611K0FKEA |1206 Thick Film Chip Resistors |0.07 |10 |0.70 |

| | | |1/4watt 11Kohms 1% | | | |

|Digi-Key |Yageo Corporation |RC1206FR-075K49L |RES 5.49K OHM 1/4W 1% 1206 SMD |0.09 |20 |1.76 |

|Mouser |Vishay/Dale |CRCW12062K74FKEA |1206 Thick Film Chip Resistors |0.07 |8 |0.56 |

| | | |1/4watt 2.74Kohms 1% | | | |

|Vendor |Manufacturer |Part Number |Description |Price Each|Quantity |Total Cost|

|Digi-Key |Yageo Corporation |9C12063A1651FKHFT |RES 1.65K OHM 1/4W 1% 1206 SMD |0.09 |8 |0.70 |

|Digi-Key |Panasonic-ECG |ERJ-8ENF6040V |RES 604 OHM 1/4W 1% 1206 SMD |0.12 |8 |0.94 |

|Digi-Key |Vishay/Dale |CRCW120649K9FKEA |RES 49.9K OHM 1/4W 1% 1206 SMD |0.05 |8 |0.40 |

|Digi-Key |Panasonic-ECG |ERJ-6ENF3321V |RES 3.32K OHM 1/8W 1% 0805 SMD |0.09 |8 |0.73 |

|Mouser |Vishay/Dale |CRCW12065K76FKEA |1206 Thick Film Chip Resistors |0.07 |4 |0.28 |

| | | |1/4watt 5.76Kohms 1% | | | |

|Digi-Key |Vishay/Dale |CRCW080510K0JNEA |RES 10K OHM 1/8W 5% 0805 SMD |0.04 |12 |0.48 |

|Digi-Key |Vishay/Dale |CRCW1206750KFKEA |RES 750K OHM 1/4W 1% 1206 SMD |0.05 |2 |0.10 |

|Mouser |Vishay/Dale |CRCW1206237RFKEA |1206 Thick Film Chip Resistors |0.07 |4 |0.28 |

| | | |1/4watt 237ohms 1% | | | |

|Digi-Key |Vishay/Dale |CRCW1206270RJNEA |RES 270 OHM 1/4W 5% 1206 SMD |0.04 |1 |0.04 |

|Mouser |Xicon |263-0-RC |1206 SMD Chip Resistors 1/8WATT |0.05 |3 |0.15 |

| | | |0OHMS 5% | | | |

|Mouser |Xicon |260-0-RC |0805 SMD Chip Resistors 1/10WATT |0.04 |3 |0.12 |

| | | |0OHMS 5% | | | |

|Digi-Key |Vishay/Dale |CRCW0805124KFKEA |RES 124K OHM 1/8W 1% 0805 SMD |0.04 |1 |0.04 |

|Mouser |Vishay/Dale |CRCW0805249KFKEA |0805 Thick Film Chip Resistors |0.05 |1 |0.05 |

| | | |1/8watt 249Kohms 1% | | | |

|Digi-Key |Panasonic-ECG |ERJ-6GEYJ124V |RES 120K OHM 1/8W 5% 0805 SMD |0.08 |32 |2.46 |

|Digi-Key |Panasonic-ECG |ERJ-6GEYJ510V |RES 51 OHM 1/8W 5% 0805 SMD |0.08 |16 |1.23 |

|Digi-Key |Vishay/Dale |CRCW08051K20JNEA |RES 1.2K OHM 1/8W 5% 0805 SMD |0.04 |4 |0.16 |

|Digi-Key |TI |SN74LVC373APWR |IC OCTAL TRANSP LATCH 20-TSSOP |0.48 |2 |0.96 |

|Digi-Key |Cypress Semiconductor |CY7C1049CV33-15VXC |IC SRAM 512KX8 3.3V ASYNC 36SOJ |5.30 |1 |5.30 |

|Digi-Key |STMicroelectronics |M29W800DB70N6E |IC FLASH MEM 8MBIT 3V 48-TSOP |4.19 |1 |4.19 |

|Digi-Key |Analog |AD1835AASZ-ND |IC CODEC 2ADC/8DAC 24BIT 52-MQFP |14.33 |1 |14.33 |

|Digi-Key |Analog |ADG412BRZ-ND |IC SW ANLG QUAD SPST 16SOIC |3.87 |1 |3.87 |

|Digi-Key |Analog |ADM708SARZ-ND |IC SUPERVISOR MPU 2.93 WD 8SOIC |1.08 |1 |1.08 |

|Digi-Key |Lineat Technology |LTC1877EMS8#PBF-ND |IC REG STP-DWN SYNC HI-EFF 8MSOP |6.13 |1 |6.13 |

|Vendor |Manufacturer |Part Number |Description |Price Each|Quantity |Total Cost|

|Digi-Key |Analog |AD8606ARZ-ND |IC OPAMP DUAL R-R I/O LN 8-SOIC |2.70 |8 |21.60 |

|TI |TI |TPA3001D1PWPR |Mono, High Power, Filter-Free |5.00 |8 |40.00 |

| | | |Class-D Audio Amplifier | | | |

|Analog |Analog |ADP3336ARMZ-REEL7TR-ND |IC REG LDO ADJ 500MA 8-MSOP |1.61 |2 |3.21 |

|Digi-Key |Analog |ADP1864AUJZ-R7CT-ND |IC CTRLR DC/DC STEP-DOWN SOT23-6 |2.36 |1 |2.36 |

|Mouser |Fairchild Semiconductor|FDC658P |MOSFETs SSOT-6 P-CH -30V |0.71 |1 |0.71 |

|Digi-Key |Texas Insturments |LM317KCS |IC VOLT REG POS ADJ 3TERM TO-220 |0.84 |1 |0.84 |

|Analog |Analog |AD5160BRJ50-RL7 |256 Position SPI Compatible Digital|0.63 |1 |0.63 |

| | | |Potentiometer | | | |

|Digi-Key |Analog |ADSP-21262SKSTZ200 |32-Bit Floating-Point SHARC DSP |28.89 |1 |28.89 |

|Digi-Key |TI |SN74LVC138AD |IC 3-TO-8 DECOD/DEMUX 16-SOIC |0.45 |1 |0.45 |

|Digi-Key |Digi-Key |SGR-8002DC-PCC-ND |OSCILLATOR CMOS PROG 3.3V 0E |5.15 |1 |5.15 |

| | | |(25MHz) | | | |

|Digi-Key |Digi-Key |SGR-8002DC-PCC-ND |OSCILLATOR CMOS PROG 3.3V 0E |5.15 |1 |5.15 |

| | | |(12.288 MHz) | | | |

|MCM |MCM  |G8270 |5" LCD screen |49.95 |1 |49.95 |

|Digi-Key |Quantum Research Group |E240B |touchbutton evaluation kit |19.00 |1 |19.00 |

|Digi-Key |Atmel |ATmega32 |microcontroller |8.17 |1 |8.17 |

|Spark Fun |Nordic Semiconductor |TRF-2.4G |wireless transceiver |20.00 |3 |60.00 |

| |and Laipac Technologies| | | | | |

|Multilabs |Multilabs |ezVID 2.0 |serial-to-video module |64.95 |1 |64.95 |

|Radio Shack |Radio Shack |276-640 |38 kHz Infrared Receiver |3.69 |1 |3.69 |

|Digi-Key |Maxim Integrated |MAX3001 |IC TRANSLATOR LEVEL 8CH 20TSSOP |2.10 |1 |2.10 |

| |Products | | | | | |

|Home Depot |Home Depot |99167678085 |3/4" 2' X 4' MDF |7.37 |1 |7.37 |

|Home Depot |Home Depot |99167702186 |1/4" 2' X 4' MDF |3.67 |1 |3.67 |

|Home Depot |Home Depot |715487158716 |1/2" 4' X 8' MDF |15.97 |1 |15.97 |

|Home Depot |Home Depot |9420004100383 |1" X 2' X 6' Trim Wood |2.65 |1 |2.65 |

|Klipsch |Klipsch |N/A |8" Subwoofer |20.00 |8 |160 |

|Vendor |Manufacturer |Part Number |Description |Price Each|Quantity |Total Cost|

|Parts Express |Tang Band |264-860 |W1-1070SE |10.62 |16 |169.92 |

|Digikey |Power-One |179-2047-ND |Power Supply |115.00 |2 |230 |

|BASF |BASF |  |Limco Paint |60.00 |1 |60 |

|  |  |  |Wire Cost |10.00 |1 |10 |

|Parts Express |  |090-278 |RCA Connectors |1.95 |6 |11.7 |

|Marchand |Marchand Electronics |WM8 |Bass EQ |70.00 |2 |140 |

|Electronics | | | | | | |

|Marchand |Marchand Electronics |PS10 |15V / -15V Supply |45.00 |2 |90 |

|Electronics | | | | | | |

Appendix F: Software Listing

Speaker Software Listing

File: ad1835.h

/******************************************************************************

* Title: AD1835

* Version: $Revision: 0.0 $

* Filename: $Source: /home/shay/a/477grp7/repository/Project/DSP/ad1835.h,v $

* Author(s): Analog Devices

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Register definitions for AD1835 Stereo Codec

* Supplied by Analog Devices as example code.

*

* Update history:

* $Log: ad1835.h,v $

* Revision 0.0 2007/01/18 19:53:28 477grp7

* Definitions for AD1835 codec supplied by Analog Devices

*

*

*

*****************************************************************************/

///////////////////////////////////////////////////////////////////////////////////////

//NAME: ad1835.h

//DATE: 9/18/03

//PURPOSE: Header file with AD1835 Register definitions

//

////////////////////////////////////////////////////////////////////////////////////////

#ifndef _AD1835_H_

#define _AD1835_H_

//

// AD1835.h

//

// Configuration values for the AD1835A codec

//

#define DACCTRL1 (0x0000) // DAC control register 1 (R/W)

#define DACCTRL2 (0x1000) // DAC control register 2 (R/W)

#define DACVOL_L1 (0x2000) // DAC volume - left 1 (R/W)

#define DACVOL_R1 (0x3000) // DAC volume - right 1 (R/W)

#define DACVOL_L2 (0x4000) // DAC volume - left 2 (R/W)

#define DACVOL_R2 (0x5000) // DAC volume - right 2 (R/W)

#define DACVOL_L3 (0x6000) // DAC volume - left 3 (R/W)

#define DACVOL_R3 (0x7000) // DAC volume - right 3 (R/W)

#define DACVOL_L4 (0x8000) // DAC volume - left 4 (R/W)

#define DACVOL_R4 (0x9000) // DAC volume - right 4 (R/W)

#define ADCPEAKL (0xA000) // ADC left peak (R)

#define ADCPEAKR (0xB000) // ADC right peak (R)

#define ADCCTRL1 (0xC000) // ADC control 1 (R/W)

#define ADCCTRL2 (0xD000) // ADC control 2 (R/W)

#define ADCCTRL3 (0xE000) // ADC control 3 (R/W)

#define RD (0x0800)

#define WR (0x0000) // Write to register

// DAC control register 1

#define DEEMPH44_1 (0x0100) // Deemphasis filter for 44.1 KHz

#define DEEMPH32 (0x0200) // Deemphasis filter for 32.0 KHz

#define DEEMPH48 (0x0300) // Deemphasis filter for 48.0 KHz

#define DACI2S (0x0000) // DAC receives I2S format

#define DACRJ (0x0020) // DAC receives I2S format

#define DACDSP (0x0040) // DAC receives I2S format

#define DACLJ (0x0060) // DAC receives I2S format

#define DACPACK256 (0x0080) // DAC receives I2S format

#define DAC24BIT (0x0000) // 24-bit output word length

#define DAC20BIT (0x0008) // 20-bit output word length

#define DAC16BIT (0x0010) // 16-bit output word length

#define DACPOWERDN (0x0004) // DAC into power-down mode

#define DACFS48 (0x0000) // Sample rate = 48 KHz (x8)

#define DACFS96 (0x0001) // Sample rate = 96 KHz (x4)

#define DACFS192 (0x0002) // Sample rate = 192 KHz (x2)

// DAC control register 2

#define DACREPLICATE (0x0100) // Replicate output of DAC 1/2 on 3/4, 5/6 & 7/8

#define DACMUTE_R4 (0x0080) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_L4 (0x0040) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_R3 (0x0020) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_L3 (0x0010) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_R2 (0x0008) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_L2 (0x0004) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_R1 (0x0002) // Mute DAC output channel (clear to un-mute)

#define DACMUTE_L1 (0x0001) // Mute DAC output channel (clear to un-mute)

//-------------------------------------------------------------------------------

//DAC Volume Control - 10-bit granularity (1024 levels)

#define DACVOL_MIN (0x000)

#define DACVOL_LOW (0X100)

#define DACVOL_MED (0X200)

#define DACVOL_HI (0X300)

#define DACVOL_MAX (0x3FF)

#define DACVOL_MASK (0x3FF) // Volume in dB is in 10 LSBs

// 3FF = 0 dBFS = 1023/1023

// 3FE = -0.01 dBFS = 1022/1023

// ...

// 002 = -50.7 dBFS = 3/1023

// 001 = -54.2 dBFS = 2/1023

//-------------------------------------------------------------------------------

// ADC Control 1

#define ADCHPF (0x0100) // High pass filter (AC-coupled)

#define ADCPOWERDN (0x0080) // DAC into power-down mode

#define ADCFS48 (0x0000) // Sample rate = 48 KHz

#define ADCFS96 (0x0001) // Sample rate = 96 KHz

//-------------------------------------------------------------------------------

// ADC Control 2

#define AUXSLAVE (0x0000) // Aux input is in slave mode

#define AUXMASTER (0x0200) // Aux input is in master mode

#define ADCI2S (0x0000) // ADC transmits in I2S format

#define ADCRJ (0x0040) // ADC transmits in right-justified format

#define ADCDSP (0x0080) // ADC transmits in DSP (TDM) format

#define ADCLJ (0x00C0) // ADC transmits in left-justified format

#define ADCPACK256 (0x0100) // ADC transmits in packed 256 format

#define ADCAUX256 (0x0180) // ADC transmits in packed 128 format

#define ADC24BIT (0x0000) // 24-bit output word length

#define ADC20BIT (0x0010) // 20-bit output word length

#define ADC16BIT (0x0020) // 16-bit output word length

#define ADCMUTER (0x0002) // Mute right channel from ADC

#define ADCMUTEL (0x0001) // Mute right channel from ADC

//-------------------------------------------------------------------------------

// ADC Control 3

#define IMCLKx2 (0x0000) // Internal MCLK = external MCLK x 2

#define IMCLKx1 (0x0080) // Internal MCLK = external MCLK

#define IMCLKx23 (0x0100) // Internal MCLK = external MCLK x 2/3

#define PEAKRDEN (0x0020) // Enable reads of peak ADC levels

#endif

File: audio.h

/******************************************************************************

* Title:

* Version: $Revision: 1.5 $

* Filename: $RCSfile: audio.h,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Contains all audio related functions, variables, etc.

*

* Update history:

* $Log: audio.h,v $

* Revision 1.5 2007/04/26 15:35:15 477grp7

* Futher code cleanup. Changed how the subwoofer volume is calculated

* based on a change in the subwoofer volume circuit

*

* Revision 1.4 2007/04/24 01:39:52 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.3 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.2 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.1 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.0 2007/03/25 16:45:57 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#ifndef AUDIO_H

#define AUDIO_H

/******************************************************************************

* Constants

*****************************************************************************/

/******************************************************************************

* Functions

*****************************************************************************/

void InitAudio();

void OnRecieved(int sig_int); // Interrupt routine

void DisableAudio(); // For loss of communication. Does _not_ power down

void EnableAudio(); // (Re)establisment of communication.

void SetVolume(int vol);

void SetWoofer(float relvol); // Set relative volume of the woofer

void SetDelays(int stereo, int* Data);

void SetShading(int stereo, float* Data);

/******************************************************************************

* Variables

*****************************************************************************/

#endif

File: commands.h

/******************************************************************************

* Title:

* Version: $Revision: 1.4 $

* Filename: $RCSfile: commands.h,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Contains functions for processing commands received from the

* control box via the wireless interface. These are high-level

* functions. The low-level i/o is in system.h and io.cpp

*

* Update history:

* $Log: commands.h,v $

* Revision 1.4 2007/04/24 01:39:53 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.3 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.2 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.1 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.0 2007/03/25 16:45:57 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.2 2007/03/19 16:58:49 477grp7

* Added hardware timer support. Added framework for command processing

*

* Revision 0.1 2007/03/14 16:20:17 477grp7

* Began adding framework for wireless command handling

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#ifndef COMMANDS_H

#define COMMANDS_H

/******************************************************************************

* Constants

*****************************************************************************/

#define CMD_SET 0x1

#define CMD_SET_DELAY 0x6

#define CMD_SET_SHADING 0x5

/******************************************************************************

* Classes

*****************************************************************************/

// These classes can only be created by the ExtractPacket() function

// It is essential that all classes friend that function

class CReceivePacket

{

protected:

CReceivePacket(int* RawData) {}

CReceivePacket() {}

friend CReceivePacket* ExtractPacket(int* RawData);

public:

int Destination; // Left = 0, Right = 1

int Type;

};

class CSetPacket : public CReceivePacket

{

protected:

CSetPacket(int* RawData);

CSetPacket() {}

friend CReceivePacket* ExtractPacket(int* RawData);

public:

int CustomEq;

int CustomSteering;

int Power;

int InputSelect;

int Volume;

int Steering;

int Equalizer;

};

class CDlyPacket : public CReceivePacket

{

protected:

CDlyPacket(int* RawData);

CDlyPacket() {}

friend CReceivePacket* ExtractPacket(int* RawData);

public:

int Stereo;

int Delay[8];

};

class CShdPacket : public CReceivePacket

{

protected:

CShdPacket(int* RawData);

CShdPacket() {}

friend CReceivePacket* ExtractPacket(int* RawData);

public:

int Index;

int Stereo;

int Values[4];

};

/******************************************************************************

* Functions

*****************************************************************************/

CReceivePacket* ExtractPacket(int* RawData); // RawData is 2 word array

int ProcessCommand(CReceivePacket* pPacket);

#endif

File: DSP.h

/******************************************************************************

* Title:

* Version: $Revision: 1.9 $

* Filename: $RCSfile: DSP.h,v $

* Author(s): Benjamin Fogle

* $Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Main include file for the project

*

* Update history:

* $Log: DSP.h,v $

* Revision 1.9 2007/04/26 15:35:15 477grp7

* Futher code cleanup. Changed how the subwoofer volume is calculated

* based on a change in the subwoofer volume circuit

*

* Revision 1.8 2007/04/24 17:54:41 477grp7

* Cascaded equalizer and crossover filters to make 4th order filters.

*

* Revision 1.7 2007/04/24 01:39:53 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.6 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.5 2007/04/18 23:54:25 477grp7

* Added support for multiple 'voices' with different sets of shading/delays.

* Added PCB_PATCH and AUDIO_TEST defines to make testing easier

*

* Revision 1.4 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.3 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.2 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.1 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.0 2007/03/25 16:45:57 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.28 2007/03/14 16:19:51 477grp7

* Began adding framework for wireless command handling

*

* Revision 0.27 2007/03/09 02:53:45 477grp7

* Cleaned up comments / old code slightly

*

* Revision 0.26 2007/03/08 22:11:45 477grp7

* Moved FIR coefficients to program memory, allowing the time spent in the

* inner loop to be cut in half. Working on wireless reciever.

*

* Revision 0.25 2007/03/01 15:53:11 477grp7

* Fixed a bug in the SPI flag settings that caused the codec to be active

* while the wireless module was being configured, causing data corruption.

* Loads equalizers from Flash memory.

*

* Revision 0.24 2007/02/26 18:21:29 477grp7

* Working on loading data from Flash memory.

*

* Revision 0.23 2007/02/26 14:35:48 477grp7

* Adding support for loading new delay coefficients. Contintuing work on

* wireless module

*

* Revision 0.22 2007/02/21 16:23:37 477grp7

* no message

*

* Revision 0.21 2007/02/20 22:17:45 477grp7

* Moved delay line back to main memory, since 100ms delays will suffice

*

* Revision 0.20 2007/02/20 16:53:12 477grp7

* no message

*

* Revision 0.19 2007/02/12 16:54:16 477grp7

* Fixed bug in interfacing to external SRAM

*

* Revision 0.18 2007/02/07 03:51:04 477grp7

* no message

*

* Revision 0.17 2007/02/06 19:51:58 477grp7

* Attempting to move delay line to external memory

*

* Revision 0.16 2007/02/06 03:07:56 477grp7

* Cleaned up old comments. Trying to make EqCoeff work as program memory to speed up loop.

*

* Revision 0.15 2007/02/05 18:08:22 477grp7

* Began adding wifi transmitter support

*

* Revision 0.14 2007/02/05 15:56:33 477grp7

* Finished converting data structures to C++ support. Amplitude shading and

* delays seem to work.

*

* Revision 0.13 2007/02/02 21:16:25 477grp7

* Added C++ classes to make the updating algorithm more clear.

*

* Revision 0.12 2007/01/31 04:43:09 477grp7

* no message

*

* Revision 0.10 2007/01/30 18:43:32 477grp7

* Began seperating audio channels and adding capability for

* two channels per speaker.

*

* Revision 0.9 2007/01/24 17:38:04 477grp7

* *** empty log message ***

*

* Revision 0.8 2007/01/24 14:21:16 477grp7

* Got talk-thru working. Optimization MUST be enabled or it won't be fast enough to process at 42000. MAX_TAPS doesn't work at 1024, but does at 512.

*

* Revision 0.7 2007/01/23 18:28:18 477grp7

* Preliminary delay / equilizer created.

*

* Revision 0.6 2007/01/23 16:41:37 477grp7

* *** empty log message ***

*

* Revision 0.5 2007/01/23 15:12:48 477grp7

* Began adding code to get the audio in/out working.

*

* Revision 0.4 2007/01/19 18:57:55 477grp7

* Began adding codec support. Changed project to be a loader file that can be programmed into flash.

*

* Revision 0.3 2007/01/18 03:42:05 477grp7

* Initial test of DSP functions. Tests LEDs/external memory access

* via DMA parallel port write.

*

* Revision 0.2 2007/01/17 18:12:16 477grp7

* Added inline DMA parallel port read routines

*

* Revision 0.1 2007/01/17 01:18:59 477grp7

* Began adding function prototypes

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#ifndef DSP_H

#define DSP_H

/*****************************************************************************

* Testing modes

****************************************************************************/

// Uncomment to activate

#define PCB_PATCH // Defined when running from the final PCB

//#define AUDIO_TEST // Bypass all wireless functions and play

//#define PING_TEST // Enable audio by default and accept any receive as valid

//#define PASSTHRU_TEST // Bypass all filters/delays/etc.

/*****************************************************************************

* Constants

****************************************************************************/

// Misc numerical constants

#define NUM_SAMPLES 4800 // = sample rate * max delay

#define NUM_CHANNELS 8 // # of elements

#define STEREO_LEFT 0

#define STEREO_RIGHT 1

#define VOICE_MAIN 0

#define VOICE_CENTER 1

#define VOICE_AUX 2

#define ADC_MAX ((float)0x007FFFFF)

// Woofer control

#define WOOFER_VOL 1.0f // Default relative woofer volume

#define BASE_EQ_WOOFER 2.0f // Bass volume in bass mode

#define WOOFER_BASELINE 0x7F // setting that is equivalent to 0dB

// Addresses

#define FLASH_START 0x1000000

#define EQ_START 0x1080000

#define DELAY_START 0x10F0000

#define SHADING_START 0x10F8000

#define SRAM_START 0x1200000 // only for in-circuit programming now

// Wireless constants

#define SPEAKER_LEFT 0x01

#define SPEAKER_RIGHT 0x02

#define SPEAKER_SIDE SPEAKER_LEFT // which speaker this is loaded into

#define PACKET_SIZE 64 // in bits

#define SPEAKER_ADDR 0x18E7 // Address of this speaker. (High byte always 0x18)

#define CONTROL_ADDR 0x18E7 // address of control box. never changes

#define RX_CHANNEL 2 // Wireless channel

#define BLACKOUT_TIME 50000 // Approx max time between packets (in 0.1 ms)

// Filters

#define CORRECTION_FILTER 32 // Which index it's stored at

#define CROSSOVER_FILTER 33

/*****************************************************************************

* Classes/Types

****************************************************************************/

typedef unsigned int UINT;

/*****************************************************************************

* Functions

****************************************************************************/

void Init(); // Initialize everything. Do bare minimum and call the others

/*****************************************************************************

* Variables

****************************************************************************/

#endif

File: system.h

/******************************************************************************

* Title:

* Version: $Revision: 1.8 $

* Filename: $RCSfile: system.h,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Contains system status and low-level i/o functions and

* variables

*

* Update history:

* $Log: system.h,v $

* Revision 1.8 2007/04/24 01:41:34 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.7 2007/04/24 01:39:53 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.6 2007/04/22 18:58:39 477grp7

* no message

*

* Revision 1.5 2007/04/18 23:54:25 477grp7

* Added support for multiple 'voices' with different sets of shading/delays.

* Added PCB_PATCH and AUDIO_TEST defines to make testing easier

*

* Revision 1.4 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.3 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.2 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.1 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.0 2007/03/25 16:45:58 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#ifndef SYSTEM_H

#define SYSTEM_H

/******************************************************************************

* Constants

*****************************************************************************/

/******************************************************************************

* Data types

*****************************************************************************/

// Forward declarations. Declared in commands.h

class CReceivePacket;

class CSendPacket;

/******************************************************************************

* Variables

*****************************************************************************/

/******************************************************************************

* Functions

*****************************************************************************/

// System status routines

void LoadSteering(int index);

void LoadEq(int index);

void SelectInput(int input);

void PowerDown();

void PowerUp();

// Init routines

void InitIO();

void InitSystem();

void InitWireless(int Channel, int RxAddr, int rx);

// Wireless communication

CReceivePacket* ReadWireless(); // returns "static" object. Not thread safe

// Misc

void Wait(int us); // Idles until 'us' microseconds elapse. (Very accurate)

#endif

File: main.cpp

/******************************************************************************

* Title:

* Version: $Revision: 1.14 $

* Filename: $RCSfile: main.cpp,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose:

*

* Update history:

* $Log: main.cpp,v $

* Revision 1.14 2007/04/26 15:35:15 477grp7

* Futher code cleanup. Changed how the subwoofer volume is calculated

* based on a change in the subwoofer volume circuit

*

* Revision 1.13 2007/04/24 17:54:42 477grp7

* Cascaded equalizer and crossover filters to make 4th order filters.

*

* Revision 1.12 2007/04/24 01:39:53 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.11 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.10 2007/04/22 18:58:39 477grp7

* no message

*

* Revision 1.8 2007/04/18 23:54:25 477grp7

* Added support for multiple 'voices' with different sets of shading/delays.

* Added PCB_PATCH and AUDIO_TEST defines to make testing easier

*

* Revision 1.7 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.6 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.5 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.4 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.3 2007/04/11 00:52:48 477grp7

* no message

*

* Revision 1.2 2007/04/08 23:02:40 477grp7

* Got wireless working finally.

*

* Revision 1.1 2007/03/28 13:53:00 477grp7

* no message

*

* Revision 1.0 2007/03/25 16:45:58 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.18 2007/03/08 22:11:45 477grp7

* Moved FIR coefficients to program memory, allowing the time spent in the

* inner loop to be cut in half. Working on wireless reciever.

*

* Revision 0.17 2007/02/26 18:21:29 477grp7

* Working on loading data from Flash memory.

*

* Revision 0.16 2007/02/26 14:35:48 477grp7

* Adding support for loading new delay coefficients. Contintuing work on

* wireless module

*

* Revision 0.15 2007/02/21 01:42:50 477grp7

* no message

*

* Revision 0.14 2007/02/20 22:17:45 477grp7

* Moved delay line back to main memory, since 100ms delays will suffice

*

* Revision 0.13 2007/02/20 16:53:12 477grp7

* no message

*

* Revision 0.12 2007/02/19 15:23:10 477grp7

* no message

*

* Revision 0.11 2007/02/16 15:11:45 477grp7

* working on WiFi configuration

*

* Revision 0.10 2007/02/06 19:51:58 477grp7

* Attempting to move delay line to external memory

*

* Revision 0.9 2007/02/06 03:07:56 477grp7

* Cleaned up old comments. Trying to make EqCoeff work as program memory to speed up loop.

*

* Revision 0.8 2007/02/05 15:56:33 477grp7

* Finished converting data structures to C++ support. Amplitude shading and

* delays seem to work.

*

* Revision 0.7 2007/02/02 21:16:25 477grp7

* Added C++ classes to make the updating algorithm more clear.

*

* Revision 0.6 2007/01/30 18:43:32 477grp7

* Began seperating audio channels and adding capability for

* two channels per speaker.

*

* Revision 0.5 2007/01/24 17:38:04 477grp7

* *** empty log message ***

*

* Revision 0.4 2007/01/24 14:21:16 477grp7

* Got talk-thru working. Optimization MUST be enabled or it won't be fast enough to process at 42000. MAX_TAPS doesn't work at 1024, but does at 512.

*

* Revision 0.3 2007/01/23 18:28:18 477grp7

* Preliminary delay / equilizer created.

*

* Revision 0.2 2007/01/18 03:42:05 477grp7

* Initial test of DSP functions. Tests LEDs/external memory access

* via DMA parallel port write.

*

* Revision 0.1 2007/01/17 01:18:07 477grp7

* no message

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#include

#include

#include

#include

#include

#include "DSP.h"

#include "commands.h"

#include "system.h"

#include "audio.h"

// Optimization does funny things to called functions

#pragma optimize_off

void main()

{

CReceivePacket* pPacket = 0;

int i;

int power = 0;

Init();

#if defined(AUDIO_TEST) || defined(PING_TEST)// Testing mode

PowerUp();

LoadEq(0);

SetVolume(0xFFFF); //Max

LoadSteering(0);

EnableAudio();

power = 1;

#endif // defined(AUDIO_TEST) || defined(PING_TEST)

while(1)

{

#if !defined(AUDIO_TEST)

// If after 3s we hear nothing valid, assume comm was lost

for (i = 0; i < BLACKOUT_TIME; i++)

{

pPacket = ReadWireless(); // get data or time out at 0.1ms

if(ProcessCommand(pPacket))

{

break; // if it was good, restart the loop

}

}

if (i == BLACKOUT_TIME)

{

// Timed out. Re-establish communication. Everything will

// go back to normal once we receive a SET packet again.

PowerDown(); // no sound comes out when we don't have communication

DisableAudio();

power = 0;

}

#endif // !defined(AUDIO_TEST)

}

}

File: audio.cpp

/******************************************************************************

* Title:

* Version: $Revision: 1.12 $

* Filename: $RCSfile: audio.cpp,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Code for all audio-related classes and functions

*

* Update history:

* $Log: audio.cpp,v $

* Revision 1.12 2007/04/26 15:35:15 477grp7

* Futher code cleanup. Changed how the subwoofer volume is calculated

* based on a change in the subwoofer volume circuit

*

* Revision 1.11 2007/04/24 17:54:40 477grp7

* Cascaded equalizer and crossover filters to make 4th order filters.

*

* Revision 1.10 2007/04/24 01:39:52 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.9 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.8 2007/04/22 18:58:39 477grp7

* no message

*

* Revision 1.7 2007/04/19 01:34:21 477grp7

* fixed bug in PCB_PATCH preprocessor logic.

*

* Revision 1.6 2007/04/18 23:54:25 477grp7

* Added support for multiple 'voices' with different sets of shading/delays.

* Added PCB_PATCH and AUDIO_TEST defines to make testing easier

*

* Revision 1.5 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.4 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.3 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.2 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.1 2007/03/28 13:53:00 477grp7

* no message

*

* Revision 1.0 2007/03/25 16:45:57 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#include

#include

#include

#include

#include

#include

#include "DSP.h"

#include "audio.h"

#include "ad1835.h"

#include "system.h"

/*****************************************************************************

* Class declarations

****************************************************************************/

// Not a class declaration, but used by inline functions in the classes, and

// so must appear here

static int Stereo = 1;

// Note most functions are inline for performance reasons

// CDelayList holds a set of delays for each speaker element and each

// stereo pair, making a total of 16 delays.

class CDelayList

{

public:

CDelayList();

~CDelayList() {}

// Each stereo channel (L/R) a delay, and there are 8 elements in all

// stereo = STEREO_LEFT,STEREO_RIGHT. element = 0-7

int operator() (int stereo, int element) const

{

return List[stereo][element];

}

int& operator() (int stereo, int element)

{

return List[stereo][element];

}

// Functions for modifying _active_ elements (elemnts 0-3 or 4-7 depending

// on cycle) stereo = STEREO_LEFT,STEREO_RIGHT. element = 0-3

int GetActive(int stereo, int element) const

{

return List[stereo][(Stereo * 4) + element];

}

void Load(int index, int subindex);

private:

int List[2][NUM_CHANNELS];

friend void SetDelays(int stereo, int* Data); // external interface

};

// CShadingList holds a set of shading for each speaker element and each

// stereo pair, making a total of 16 delays.

class CShadingList

{

public:

CShadingList();

~CShadingList() {}

// Each stereo channel (L/R) a delay, and there are 8 elements in all

// stereo = STEREO_LEFT,STEREO_RIGHT. element = 0-7

float operator() (int stereo, int element) const

{

return List[stereo][element];

}

float& operator() (int stereo, int element)

{

return List[stereo][element];

}

// Functions for modifying _active_ elements (elemnts 0-3 or 4-7 depending

// on cycle). stereo = STEREO_LEFT,STEREO_RIGHT. element = 0-3

float GetActive(int stereo, int element) const

{

return List[stereo][(Stereo DAI18

SRU(FLAG14_O, DAI_PB18_I);

SRU(HIGH, PBEN18_I);

// Set to off initially

sysreg_bit_set(sysreg_FLAGS, FLG14);

// PB17 -- audio osc input

// Set PB17 to input (MCLK in)

SRU(LOW,DAI_PB17_I);

SRU(LOW,PBEN17_I);

// ADC --> SPORT0

#ifndef PCB_PATCH

SRU(DAI_PB07_O,SPORT0_CLK_I); // SPORT0_CLK = PB07

#else

SRU(DAI_PB03_O,SPORT0_CLK_I); // SPORT0_CLK = PB03

#endif

SRU(DAI_PB08_O,SPORT0_FS_I); // SPORT0_FS = PB08

SRU(DAI_PB05_O,SPORT0_DA_I); // SPORT0_DA (Rx channel A) = PB05

// Tie their unused buffers low to avoid rare errors, (according to specs)

#ifndef PCB_PATCH

SRU(LOW,DAI_PB07_I);

#else

SRU(LOW,DAI_PB03_I);

#endif

SRU(LOW,DAI_PB08_I);

SRU(LOW,DAI_PB05_I);

// make inputs

#ifndef PCB_PATCH

SRU(LOW,PBEN07_I);

#else

SRU(LOW,PBEN03_I);

#endif

SRU(LOW,PBEN08_I);

SRU(LOW,PBEN05_I);

// Connect DACs to SPORTs (note that each SPORT does double-duty)

// SPORT1 --> DAC1

SRU(SPORT1_DB_O, DAI_PB11_I); // Tx channel B to pb9

// SPORT1 --> DAC2

SRU(SPORT1_DA_O, DAI_PB12_I); // Tx channel A to pb10

// SPORT2 --> DAC3

#ifndef PCB_PATCH

SRU(SPORT2_DB_O, DAI_PB09_I);

#else

SRU(SPORT2_DB_O, DAI_PB02_I);

#endif

// SPORT2 --> DAC4

SRU(SPORT2_DA_O, DAI_PB10_I);

// clk and fs signals generated by the input are reproduced exactly

// on the outputs of SPORT1 and SPORT2. Do this by routing the inputs

// of the pins running SPORT0 directly to the inputs of SPORT1 and SPORT2,

// and then also connect them to the outputs.

#ifndef PCB_PATCH

SRU(DAI_PB07_O, SPORT1_CLK_I);

SRU(DAI_PB07_O, SPORT2_CLK_I);

#else

SRU(DAI_PB03_O, SPORT1_CLK_I);

SRU(DAI_PB03_O, SPORT2_CLK_I);

#endif

SRU(DAI_PB08_O, SPORT1_FS_I);

SRU(DAI_PB08_O, SPORT2_FS_I);

#ifndef PCB_PATCH

SRU(DAI_PB07_O,DAI_PB13_I);

#else

SRU(DAI_PB03_O,DAI_PB13_I);

#endif

SRU(DAI_PB17_O,DAI_PB06_I);

SRU(DAI_PB08_O,DAI_PB14_I);

// Set SPORT1 and SPORT2 pins as outputs

SRU(HIGH,PBEN06_I);

#ifndef PCB_PATCH

SRU(HIGH,PBEN09_I);

#else

SRU(HIGH,PBEN02_I);

#endif

SRU(HIGH,PBEN10_I);

SRU(HIGH,PBEN11_I);

SRU(HIGH,PBEN12_I);

SRU(HIGH,PBEN13_I);

SRU(HIGH,PBEN14_I);

// Now initialize the serial ports themselves

*pSPMCTL01 = 0;

*pSPMCTL23 = 0;

// SPORT0 is recieving in I2C mode, 24bit, using channel A

*pSPCTL0 = (BHD | SPEN_A | OPMODE | SLEN24);

// SPORT1 is transmitting in I2C mode, 24bit, using channels A and B

*pSPCTL1 = (BHD | SPEN_A | SPEN_B | OPMODE | SPTRAN | SLEN24);

// SPORT2 is transmitting in I2C mode, 24bit, using channels A and B

*pSPCTL2 = (BHD | SPEN_A | SPEN_B | OPMODE | SPTRAN | SLEN24);

// Now init the codec via spi

// set up SPI

*pSPICTL |= TXFLSH | RXFLSH; // clear invalid data

*pSPIFLG = 0;

*pSPIBAUD = 100; // 0.5Mbps

*pSPIFLG = 0xF708; // FLAG3

*pSPICTL = SPIEN | SPIMS | MSBF | WL16 | TIMOD1;

WriteSPICodec(WR | DACCTRL1 | DACI2S | DAC24BIT | DACFS48);

WriteSPICodec(WR | DACCTRL2 );

WriteSPICodec(WR | DACVOL_L1 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_R1 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_L2 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_R2 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_L3 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_R3 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_L4 | DACVOL_MAX);

WriteSPICodec(WR | DACVOL_R4 | DACVOL_MAX);

WriteSPICodec(WR | ADCCTRL1 | ADCFS48);

WriteSPICodec(WR | ADCCTRL2 | ADCI2S | ADC24BIT);

WriteSPICodec(WR | ADCCTRL3 | IMCLKx2);

// Load crossover and correction filters

CorrectionFilter.Load(CORRECTION_FILTER);

CrossoverFilter[0].Load(CROSSOVER_FILTER);

CrossoverFilter[1].Load(CROSSOVER_FILTER);

// interrupts

// Note that the main interrupt (SIG_SP0) is left undefined. This

// ensures that the audio starts in a disabled state

interrupts(SIG_SP0, SIG_IGN);

interrupts(SIG_IRQ1, SIG_IGN);

interrupts(SIG_IRQ2, SIG_IGN);

}

void OnRecieved(int sig_int)

{

int temp;

float x;

float y;

int LeftIndex[3];

int RightIndex[3];

// Read the sample

temp = *pRXSP0A;

#if !defined(PASSTHRU_TEST)

if (temp & 0x00800000) // sign extend from 24-bit signed to 32-bit signed

temp |= 0xFF000000;

// convert to float in range [-1.0, 1.0]

x = (float)temp / ADC_MAX;

// Run it through all the filters

y = CrossoverFilter[0].Calc(x); // Crossover filter is 2 cascaded biquads

y = CrossoverFilter[1].Calc(y); // to make a 4th order filter

y = CorrectionFilter.Calc(y);

y = EqFilter[0].Calc(y); // Eq is also cascaded to make 4th order

y = EqFilter[1].Calc(y);

// put the equalized output into the delay line

DelayLine.Push(y);

// Output 4 of the 8 speaker elements.

// If Stereo = STEREO_LEFT we can update 0-3, otherwise we can update 4-7

// Each element's output the sum of each input line (left and right) after

// it has been equalized and all three delays applied

LeftIndex[0] = DelayList[0].GetActive(STEREO_LEFT,0);

RightIndex[0] = DelayList[0].GetActive(STEREO_RIGHT, 0);

LeftIndex[1] = DelayList[1].GetActive(STEREO_LEFT,0);

RightIndex[1] = DelayList[1].GetActive(STEREO_RIGHT, 0);

LeftIndex[2] = DelayList[2].GetActive(STEREO_LEFT,0);

RightIndex[2] = DelayList[2].GetActive(STEREO_RIGHT, 0);

*pTXSP1A = (int)(ADC_MAX * MasterVolume * (

ShadingList[0].GetActive(STEREO_LEFT, 0) *

DelayLine(STEREO_LEFT, LeftIndex[0]) +

ShadingList[1].GetActive(STEREO_LEFT, 0) *

DelayLine(STEREO_LEFT, LeftIndex[1]) +

ShadingList[2].GetActive(STEREO_LEFT, 0) *

DelayLine(STEREO_LEFT, LeftIndex[2]) +

ShadingList[0].GetActive(STEREO_RIGHT,0) *

DelayLine(STEREO_RIGHT,RightIndex[0]) +

ShadingList[1].GetActive(STEREO_RIGHT,0) *

DelayLine(STEREO_RIGHT,RightIndex[1]) +

ShadingList[2].GetActive(STEREO_RIGHT,0) *

DelayLine(STEREO_RIGHT,RightIndex[2])

));

LeftIndex[0] = DelayList[0].GetActive(STEREO_LEFT,1);

RightIndex[0] = DelayList[0].GetActive(STEREO_RIGHT, 1);

LeftIndex[1] = DelayList[1].GetActive(STEREO_LEFT,1);

RightIndex[1] = DelayList[1].GetActive(STEREO_RIGHT, 1);

LeftIndex[2] = DelayList[2].GetActive(STEREO_LEFT,1);

RightIndex[2] = DelayList[2].GetActive(STEREO_RIGHT, 1);

*pTXSP1B = (int)(ADC_MAX * MasterVolume * (

ShadingList[0].GetActive(STEREO_LEFT, 1) *

DelayLine(STEREO_LEFT, LeftIndex[0]) +

ShadingList[1].GetActive(STEREO_LEFT, 1) *

DelayLine(STEREO_LEFT, LeftIndex[1]) +

ShadingList[2].GetActive(STEREO_LEFT, 1) *

DelayLine(STEREO_LEFT, LeftIndex[2]) +

ShadingList[0].GetActive(STEREO_RIGHT,1) *

DelayLine(STEREO_RIGHT,RightIndex[0]) +

ShadingList[1].GetActive(STEREO_RIGHT,1) *

DelayLine(STEREO_RIGHT,RightIndex[1]) +

ShadingList[2].GetActive(STEREO_RIGHT,1) *

DelayLine(STEREO_RIGHT,RightIndex[2])

));

LeftIndex[0] = DelayList[0].GetActive(STEREO_LEFT,2);

RightIndex[0] = DelayList[0].GetActive(STEREO_RIGHT, 2);

LeftIndex[1] = DelayList[1].GetActive(STEREO_LEFT,2);

RightIndex[1] = DelayList[1].GetActive(STEREO_RIGHT, 2);

LeftIndex[2] = DelayList[2].GetActive(STEREO_LEFT,2);

RightIndex[2] = DelayList[2].GetActive(STEREO_RIGHT, 2);

*pTXSP2A = (int)(ADC_MAX * MasterVolume * (

ShadingList[0].GetActive(STEREO_LEFT, 2) *

DelayLine(STEREO_LEFT, LeftIndex[0]) +

ShadingList[1].GetActive(STEREO_LEFT, 2) *

DelayLine(STEREO_LEFT, LeftIndex[1]) +

ShadingList[2].GetActive(STEREO_LEFT, 2) *

DelayLine(STEREO_LEFT, LeftIndex[2]) +

ShadingList[0].GetActive(STEREO_RIGHT,2) *

DelayLine(STEREO_RIGHT,RightIndex[0]) +

ShadingList[1].GetActive(STEREO_RIGHT,2) *

DelayLine(STEREO_RIGHT,RightIndex[1]) +

ShadingList[2].GetActive(STEREO_RIGHT,2) *

DelayLine(STEREO_RIGHT,RightIndex[2])

));

LeftIndex[0] = DelayList[0].GetActive(STEREO_LEFT,3);

RightIndex[0] = DelayList[0].GetActive(STEREO_RIGHT, 3);

LeftIndex[1] = DelayList[1].GetActive(STEREO_LEFT,3);

RightIndex[1] = DelayList[1].GetActive(STEREO_RIGHT, 3);

LeftIndex[2] = DelayList[2].GetActive(STEREO_LEFT,3);

RightIndex[2] = DelayList[2].GetActive(STEREO_RIGHT, 3);

*pTXSP2B = (int)(ADC_MAX * MasterVolume * (

ShadingList[0].GetActive(STEREO_LEFT, 3) *

DelayLine(STEREO_LEFT, LeftIndex[0]) +

ShadingList[1].GetActive(STEREO_LEFT, 3) *

DelayLine(STEREO_LEFT, LeftIndex[1]) +

ShadingList[2].GetActive(STEREO_LEFT, 3) *

DelayLine(STEREO_LEFT, LeftIndex[2]) +

ShadingList[0].GetActive(STEREO_RIGHT,3) *

DelayLine(STEREO_RIGHT,RightIndex[0]) +

ShadingList[1].GetActive(STEREO_RIGHT,3) *

DelayLine(STEREO_RIGHT,RightIndex[1]) +

ShadingList[2].GetActive(STEREO_RIGHT,3) *

DelayLine(STEREO_RIGHT,RightIndex[2])

));

#else // !defined(PASSTHRU_TEST)

*pTXSP1A = *pTXSP1B = *pTXSP2A = *pTXSP2B = temp;

#endif // !defined(PASSTHRU_TEST)

// Each time the interrupt is called, it's for the other

// stereo channel.

Stereo ^= 0x01;

}

void EnableAudio()

{

// Set interrupt

interrupts(SIG_SP0, OnRecieved);

}

void DisableAudio()

{

// Turn off the interrupt

interrupts(SIG_SP0, SIG_IGN);

}

void SetVolume(int volume)

{

volume &= 0x0000FFFF;

MasterVolume = ((float)volume) / ((float)0x0000FFFF);

SetWoofer(WooferVolume); // Update woofer

}

void LoadSteering(int index)

{

// Set up PP for flash read

for(int i = 0; i < 3; i++)

{

DelayList[i].Load(index, i);

ShadingList[i].Load(index, i);

}

}

void SetDelays(int stereo, int* Data)

{

// Whe setting delays manually, only one set of delays

// are used

for(int i = 0; i < NUM_CHANNELS; i++)

DelayList[0].List[stereo][i] = Data[i];

for (int i = 0; i < NUM_CHANNELS; i++)

{

DelayList[1].List[0][i] =

DelayList[1].List[1][i] =

DelayList[2].List[0][i] =

DelayList[2].List[1][i] = 0;

}

}

void SetShading(int stereo, float* Data)

{

for (int i = 0; i < NUM_CHANNELS; i++)

ShadingList[0].List[stereo][i] = Data[i];

for (int i = 0; i < NUM_CHANNELS; i++)

{

ShadingList[1].List[0][i] =

ShadingList[1].List[1][i] =

ShadingList[2].List[0][i] =

ShadingList[2].List[1][i] = 0.0f;

}

}

void LoadEq(int index)

{

EqFilter[0].Load(2*index);

EqFilter[1].Load(2*index + 1);

// One exception: For bass mode, we also turn up the woofer

if (index == 3)

{

SetWoofer(BASE_EQ_WOOFER);

}

else

{

SetWoofer(WOOFER_VOL);

}

}

void SetWoofer(float relvol)

{

WooferVolume = relvol;

int woofer = WOOFER_BASELINE +

((MasterVolume * WooferVolume) - 1.0) * 0x7F;

// Update the woofer volume control

// Temporarily disable wireless

while (!(*pSPISTAT & SPIF)); // Wait for SPI to be free

sysreg_bit_clr_nop(sysreg_FLAGS, FLG11);

Wait(100);

*pSPICTL |= TXFLSH | RXFLSH; // clear invalid data

*pSPIFLG = 0;

*pSPIBAUD = 100; // 0.5Mbps

*pSPIFLG = 0xFE01; // FLAG0

*pSPICTL = SPIEN | SPIMS | MSBF | WL16 | TIMOD1;

*pTXSPI = 0x1100 | woofer;

while(!(*pSPISTAT & SPIF));

Wait(100);

sysreg_bit_set_nop(sysreg_FLAGS, FLG11);

}

/******************************************************************************

* Class Member functions

*****************************************************************************/

CStereoDelayLine::CStereoDelayLine()

{

Start[0] = Start[1] = 0;

int n = 0;

for (int i = 0; i < sizeof(NUM_SAMPLES); i++)

{

Data[0][i] = 0;

Data[1][i] = 0;

}

}

CDelayList::CDelayList()

{

}

CShadingList::CShadingList()

{

}

void CDelayList::Load(int index, int subindex)

{

int addr = DELAY_START + (3*64)*index + 64*subindex;

// wait for DMA to be free

while (*pPPCTL & (PPDS | PPBS));

// Enter crit section (we don't want interruptions here)

sysreg_bit_clr(sysreg_MODE1, IRPTEN);

*pPPCTL = 0;

*pIIPP = (int)List;

*pIMPP = 1;

*pICPP = sizeof(List);

*pECPP = sizeof(List) * 4;

*pEIPP = addr;

*pEMPP = 1;

*pPPCTL = PPEN|PPDUR23|PPBHC|PPDEN;

sysreg_bit_set(sysreg_MODE1, IRPTEN); // exit crit section

}

void CShadingList::Load(int index, int subindex)

{

int addr = SHADING_START + (3*64)*index + 64*subindex;

// wait for DMA to be free

while (*pPPCTL & (PPDS | PPBS));

// Enter crit section (we don't want interruptions here)

sysreg_bit_clr(sysreg_MODE1, IRPTEN);

*pPPCTL = 0;

*pIIPP = (int)List;

*pIMPP = 1;

*pICPP = sizeof(List);

*pECPP = sizeof(List) * 4;

*pEIPP = addr;

*pEMPP = 1;

*pPPCTL = PPEN|PPDUR23|PPBHC|PPDEN;

sysreg_bit_set(sysreg_MODE1, IRPTEN); // exit crit section

}

CFilter::CFilter()

{

for(int i = 0; i < 2; i++)

{

x_data[i][0] = x_data[i][1] = x_data[i][2] =

y_data[i][0] = y_data[i][1] = y_data[i][2] = 0;

}

Start[0] = Start[1] = 0;

}

CFilter::~CFilter()

{

}

void CFilter::Load(int index)

{

int addr = EQ_START + (index * 5 * 4);

// wait for DMA to be free

while (*pPPCTL & (PPDS | PPBS));

// Enter crit section (we don't want interruptions here)

sysreg_bit_set(sysreg_MODE1, IRPTEN);

*pPPCTL = 0;

*pIIPP = (int)x_coeff;

*pIMPP = 1;

*pICPP = 5;

*pECPP = 5*4;

*pEIPP = addr;

*pEMPP = 1;

*pPPCTL = PPEN|PPDUR23|PPBHC|PPDEN;

sysreg_bit_clr(sysreg_MODE1, IRPTEN); // exit crit section

}

float CFilter::Calc(float x)

{

float res;

int i = Start[Stereo];

// Add to delay line

x_data[Stereo][i] = x;

y_data[Stereo][i] = x_coeff[0] * x_data[Stereo][i] +

x_coeff[1] * x_data[Stereo][(i + 1) % 3] +

x_coeff[2] * x_data[Stereo][(i + 2) % 3] +

y_coeff[0] * y_data[Stereo][(i + 1) % 3] +

y_coeff[1] * y_data[Stereo][(i + 2) % 3];

res = y_data[Stereo][i];

if (--i < 0)

Start[Stereo] = 2;

else

Start[Stereo] = i;

return res;

}

File: commands.cpp

/******************************************************************************

* Title:

* Version: $Revision: 1.10 $

* Filename: $RCSfile: commands.cpp,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Contains high-level logic for interpreting commands sent to the

* speaker via the wireless interface

*

* Update history:

* $Log: commands.cpp,v $

* Revision 1.10 2007/04/26 15:35:15 477grp7

* Futher code cleanup. Changed how the subwoofer volume is calculated

* based on a change in the subwoofer volume circuit

*

* Revision 1.9 2007/04/24 17:54:40 477grp7

* Cascaded equalizer and crossover filters to make 4th order filters.

*

* Revision 1.8 2007/04/24 01:39:52 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.7 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.6 2007/04/22 18:58:39 477grp7

* no message

*

* Revision 1.5 2007/04/18 23:54:25 477grp7

* Added support for multiple 'voices' with different sets of shading/delays.

* Added PCB_PATCH and AUDIO_TEST defines to make testing easier

*

* Revision 1.4 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.3 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.2 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.1 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.0 2007/03/25 16:45:57 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.2 2007/03/19 16:58:49 477grp7

* Added hardware timer support. Added framework for command processing

*

* Revision 0.1 2007/03/14 16:20:17 477grp7

* Began adding framework for wireless command handling

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#include

#include

#include

#include

#include

#include "DSP.h"

#include "commands.h"

#include "system.h"

#include "audio.h"

/******************************************************************************

* Constants

*****************************************************************************/

#ifndef NULL

#define NULL 0

#endif

/******************************************************************************

* Global variables (static linkage)

*****************************************************************************/

/******************************************************************************

* Functions

*****************************************************************************/

//#pragma optimize_off

CReceivePacket* ExtractPacket(int* RawData)

{

// We need to trick the compiler into reusing

// the same block of memory (w/o library functions)

// since union members may not have member functions with

// this compiler

static int Memory[16]; // big enough for all packets

void* pMemory = Memory;

// Command is bits 19-16

int command = (RawData[0] & 0x000F0000) >> 16;

switch (command)

{

case CMD_SET:

{

CSetPacket* pPacket = (CSetPacket*)pMemory;

(*pPacket) = CSetPacket(RawData);

return (CReceivePacket*)pMemory;

}

case CMD_SET_DELAY:

{

CDlyPacket* pPacket = (CDlyPacket*)pMemory;

(*pPacket) = CDlyPacket(RawData);

return (CReceivePacket*)pMemory;

}

case CMD_SET_SHADING:

{

CShdPacket* pPacket = (CShdPacket*)pMemory;

(*pPacket) = CShdPacket(RawData);

return (CReceivePacket*)pMemory;

}

default:

return NULL;

}

}

//#pragma optimize_off

int ProcessCommand(CReceivePacket* pPacket)

{

static int index = 0; // for multiple-packet data

if (!pPacket)

return 0;

#if defined(PING_TEST)

PowerUp(); // Turn on if needed

EnableAudio(); // Turn on if needed

return 1; // Always report good for any nonnull packet

#else

// Only respond if it was sent to us

if (!(pPacket->Destination & SPEAKER_SIDE))

return 0;

switch(pPacket->Type)

{

case CMD_SET:

{

index = 0; // housekeeping

CSetPacket* pSet = (CSetPacket*)pPacket;

SetVolume(pSet->Volume);

SelectInput(pSet->InputSelect);

LoadEq(pSet->Equalizer);

if (!pSet->CustomSteering)

{

LoadSteering(pSet->Steering);

}

if (pSet->Power && pSet->Volume != 0)

{

EnableAudio();

PowerUp();

}

else // Power down for mute or power off bit

{

PowerDown();

DisableAudio();

}

return 1;

}

case CMD_SET_DELAY:

{

index = 0;

int DelayValues[8];

CDlyPacket* pDly = (CDlyPacket*)pPacket;

for (int i = 0; i < 8; i++)

DelayValues[i] = 12 * pDly->Delay[i]; // 0.25ms = 12 samples

SetDelays(pDly->Stereo, DelayValues);

// Also set the right?

return 1;

}

case CMD_SET_SHADING:

{

CShdPacket* pShd = (CShdPacket*)pPacket;

static float ShadeValues[8];

if (index != pShd->Index)

{

index = 0;

break; // Ignore and discard changes

}

if (pShd->Index == 0)

{

ShadeValues[0] = (float)(pShd->Values[0]) / 100.0f;

ShadeValues[1] = (float)(pShd->Values[1]) / 100.0f;

ShadeValues[2] = (float)(pShd->Values[2]) / 100.0f;

ShadeValues[3] = (float)(pShd->Values[3]) / 100.0f;

index = 1;

}

else if (pShd->Index == 1)

{

ShadeValues[4] = (float)(pShd->Values[0]) / 100.0f;

ShadeValues[5] = (float)(pShd->Values[1]) / 100.0f;

ShadeValues[6] = (float)(pShd->Values[2]) / 100.0f;

ShadeValues[7] = (float)(pShd->Values[3]) / 100.0f;

// Apply changes

index = 0;

SetShading(pShd->Stereo, ShadeValues);

}

else

{

// Invalid now

index = 0;

break;

}

return 1;

}

default:

index = 0;

return 0; // Invalid

}

return 0; // Shouldn't happen

#endif // defined(PING_TEST)

}

/******************************************************************************

* Class member functions

*****************************************************************************/

CShdPacket::CShdPacket(int* RawData)

{

Destination = (RawData[0] & 0x00300000) >> 20;

Type = (RawData[0] & 0x000F0000) >> 16;

Index = (RawData[0] & 0x0000F000) >> 12;

Stereo = (RawData[0] & 0x00000100) >> 8;

Values[0] = (RawData[0] & 0x000000FF);

Values[1] = (RawData[1] & 0xFF000000) >> 24;

Values[2] = (RawData[1] & 0x00FF0000) >> 16;

Values[3] = (RawData[1] & 0x0000FF00) >> 8;

}

CDlyPacket::CDlyPacket(int* RawData)

{

Destination = (RawData[0] & 0x00300000) >> 20;

Type = (RawData[0] & 0x000F0000) >> 16;

Stereo = (RawData[0] & 0x00000100) >> 8;

Delay[0] = (RawData[0] & 0x000000F8) >> 3;

Delay[1] = ((RawData[0] & 0x00000007) > 30);

Delay[2] = (RawData[1] & 0x3E000000) >> 25;

Delay[3] = (RawData[1] & 0x01F00000) >> 20;

Delay[4] = (RawData[1] & 0x000F8000) >> 15;

Delay[5] = (RawData[1] & 0x00007C00) >> 10;

Delay[6] = (RawData[1] & 0x000003E0) >> 5;

Delay[7] = (RawData[1] & 0x0000001F);

}

CSetPacket::CSetPacket(int* RawData)

{

Destination = (RawData[0] & 0x00300000) >> 20;

Type = (RawData[0] & 0x000F0000) >> 16;

CustomEq = (RawData[0] & 0x00000008) >> 3;

CustomSteering = (RawData[0] & 0x00000004) >> 2;

Power = (RawData[0] & 0x00000002) >> 1;

InputSelect = (RawData[0] & 0x00000001);

Volume = (RawData[1] & 0xFFFF0000) >> 16;

Steering = (RawData[1] & 0x0000F000) >> 12;

Equalizer = (RawData[1] & 0x00000F00) >> 8;

}

File: io.cpp

/******************************************************************************

* Title:

* Version: $Revision: 1.11 $

* Filename: $RCSfile: io.cpp,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Contains code for communicating with the wireless and other

* chips on the board (such as turning on/off the amplifiers)

*

* Update history:

* $Log: io.cpp,v $

* Revision 1.11 2007/04/26 15:35:15 477grp7

* Futher code cleanup. Changed how the subwoofer volume is calculated

* based on a change in the subwoofer volume circuit

*

* Revision 1.10 2007/04/24 17:54:41 477grp7

* Cascaded equalizer and crossover filters to make 4th order filters.

*

* Revision 1.9 2007/04/24 01:39:53 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.8 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.7 2007/04/22 18:58:39 477grp7

* no message

*

* Revision 1.6 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.5 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.4 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.3 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.2 2007/04/08 23:02:40 477grp7

* Got wireless working finally.

*

* Revision 1.1 2007/03/28 13:53:00 477grp7

* no message

*

* Revision 1.0 2007/03/25 16:45:58 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.20 2007/03/19 16:58:49 477grp7

* Added hardware timer support. Added framework for command processing

*

* Revision 0.19 2007/03/09 02:53:45 477grp7

* Cleaned up comments / old code slightly

*

* Revision 0.18 2007/03/08 22:11:45 477grp7

* Moved FIR coefficients to program memory, allowing the time spent in the

* inner loop to be cut in half. Working on wireless reciever.

*

* Revision 0.17 2007/03/07 01:53:29 477grp7

* Worked on wifi definitions

*

* Revision 0.16 2007/03/05 14:16:33 477grp7

* no message

*

* Revision 0.15 2007/03/01 15:53:11 477grp7

* Fixed a bug in the SPI flag settings that caused the codec to be active

* while the wireless module was being configured, causing data corruption.

* Loads equalizers from Flash memory.

*

* Revision 0.14 2007/02/26 18:21:29 477grp7

* Working on loading data from Flash memory.

*

* Revision 0.13 2007/02/26 14:35:48 477grp7

* Adding support for loading new delay coefficients. Contintuing work on

* wireless module

*

* Revision 0.12 2007/02/21 16:23:37 477grp7

* no message

*

* Revision 0.11 2007/02/21 01:42:50 477grp7

* no message

*

* Revision 0.10 2007/02/20 22:17:45 477grp7

* Moved delay line back to main memory, since 100ms delays will suffice

*

* Revision 0.9 2007/02/20 16:53:12 477grp7

* no message

*

* Revision 0.8 2007/02/19 22:12:42 477grp7

* no message

*

* Revision 0.7 2007/02/19 22:09:48 477grp7

* Working on wireless module config

*

* Revision 0.6 2007/02/19 15:23:10 477grp7

* no message

*

* Revision 0.5 2007/02/17 23:17:22 477grp7

* *** empty log message ***

*

* Revision 0.4 2007/02/16 15:11:45 477grp7

* working on WiFi configuration

*

* Revision 0.3 2007/02/15 16:25:45 477grp7

* Adding support for wifi module

*

* Revision 0.2 2007/02/06 19:51:58 477grp7

* Attempting to move delay line to external memory

*

* Revision 0.1 2007/02/06 03:07:56 477grp7

* Cleaned up old comments. Trying to make EqCoeff work as program memory to speed up loop.

*

* Revision 0.0 2007/02/05 18:09:13 477grp7

* Began adding wifi transmitter support

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#include

#include

#include

#include

#include

#include

#include "DSP.h"

#include "ad1835.h"

#include "audio.h"

#include "system.h"

#include "commands.h"

/******************************************************************************

* Constants

*****************************************************************************/

#define BYTE_DELAY 10000

#define CE_CS_DELAY 300

typedef unsigned int UINT;

/******************************************************************************

* Data types / Global static variables

*****************************************************************************/

// EACH UINT REPRESENTS ONE BYTE. Upper bytes not used

// can't seem to get around this and still configure

// the wireless correctly

static struct

{

UINT Data2Size;

UINT Data1Size;

UINT Addr2[5];

UINT Addr1[5];

UINT Reserved1 : 24; // Unused. For packing

UINT AddrSize : 6;

UINT CRCSize : 1; // 1=16-bit 0=8-bit

UINT CRCEn : 1;

UINT Reserved2 : 24; // Unused. For packing

UINT TwoChannels: 1;

UINT CommMode : 1; // shock burst or direct

UINT DataRate : 1; // 1=1Mpbs 0=250kbps

UINT Xtal : 3; // constant. Set to 0x3

UINT RFPwr : 2; // constant. Set to 0x3

UINT Reserved3 : 24; // Unused. For packing

UINT Channel : 7;

UINT Mode : 1; // 1=Rx 0=Tx

} ConfigData;

#if defined(PING_TEST)

static int PowerState = 1;

#else

static int PowerState = 0;

#endif

/******************************************************************************

* Functions

*****************************************************************************/

void InitIO()

{

// Set the input select lines

SRU(FLAG12_O, DAI_PB19_I);

SRU(FLAG13_O, DAI_PB20_I);

SRU(HIGH, PBEN19_I);

SRU(HIGH, PBEN20_I);

sysreg_bit_set(sysreg_FLAGS, FLG12O | FLG13O);

// Set the power up/down line

SRU(FLAG14_O, DAI_PB01_I);

SRU(HIGH, PBEN01_I);

sysreg_bit_set_nop(sysreg_FLAGS, FLG14O);

sysreg_bit_clr_nop(sysreg_FLAGS, FLG14);

}

void SelectInput(int input)

{

if (input)

{

sysreg_bit_clr(sysreg_FLAGS, FLG13);

sysreg_bit_set(sysreg_FLAGS, FLG12);

}

else

{

sysreg_bit_set(sysreg_FLAGS, FLG13);

sysreg_bit_clr(sysreg_FLAGS, FLG12);

}

}

void PowerUp()

{

PowerState = 1;

sysreg_bit_set_nop(sysreg_FLAGS, FLG14);

}

void PowerDown()

{

PowerState = 0;

sysreg_bit_clr_nop(sysreg_FLAGS, FLG14);

}

inline void SetCS()

{

sysreg_bit_set_nop(sysreg_FLAGS, FLG10);

sysreg_bit_set_nop(sysreg_FLAGS, FLG10);

sysreg_bit_set_nop(sysreg_FLAGS, FLG10);

}

inline void ClearCS()

{

sysreg_bit_clr_nop(sysreg_FLAGS, FLG10);

sysreg_bit_clr_nop(sysreg_FLAGS, FLG10);

sysreg_bit_clr_nop(sysreg_FLAGS, FLG10);

}

inline void SetCE()

{

sysreg_bit_set_nop(sysreg_FLAGS, FLG11);

sysreg_bit_set_nop(sysreg_FLAGS, FLG11);

sysreg_bit_set_nop(sysreg_FLAGS, FLG11);

}

inline void ClearCE()

{

sysreg_bit_clr_nop(sysreg_FLAGS, FLG11);

sysreg_bit_clr_nop(sysreg_FLAGS, FLG11);

sysreg_bit_clr_nop(sysreg_FLAGS, FLG11);

}

//#pragma optimize_off

void InitWireless(int Channel, int RxAddr, int rx)

{

// Set FLAG10 to PB15 and FLAG11 to PB16

// CS and CE for wireless

// Set FLAG2 as input

SRU(FLAG10_O, DAI_PB15_I); //CS

SRU(FLAG11_O, DAI_PB16_I); //CE

SRU(FLAG12_O, DAI_PB04_I);

SRU(HIGH, PBEN15_I);

SRU(HIGH, PBEN16_I);

SRU(HIGH, PBEN04_I);

sysreg_bit_set_nop(sysreg_FLAGS, FLG12O | FLG10O | FLG11O);

sysreg_bit_set_nop(sysreg_FLAGS, FLG12);

ClearCS();

ClearCE();

Wait(10000);

// Set up all the data

ConfigData.Mode = rx; // Recieving

ConfigData.Channel = Channel;

ConfigData.RFPwr = 3; // Highest power

ConfigData.Xtal = 3; // Presetfor 16 MHz. do not change

ConfigData.DataRate = 0; // 250 kbps

mMode = 1; // ShockBurst

ConfigData.TwoChannels = 0; // one channel recieve

ConfigData.CRCEn = 1; // CRC enabled

ConfigData.CRCSize = 1; // 16-bit CRC

ConfigData.AddrSize = 16; // 16 bit addr

ConfigData.Addr1[0] = 0x00; // Address we are listening for

ConfigData.Addr1[1] = 0x00;

ConfigData.Addr1[2] = 0x00;

ConfigData.Addr1[3] = (RxAddr & 0xFF00) >> 8; // High byte 0x18;

ConfigData.Addr1[4] = (RxAddr & 0x00FF); // Low byte 0xE7;

ConfigData.Addr2[0] = 0x00; // Address2. Not used

ConfigData.Addr2[1] = 0x00;

ConfigData.Addr2[2] = 0x00;

ConfigData.Addr2[3] = 0x00;

ConfigData.Addr2[4] = 0x00;

ConfigData.Data1Size = PACKET_SIZE;

ConfigData.Data2Size = 0; // unused

// Wait for SPI to be free

// Note: for some reason config baud must be ~50kbps,

// while the data baud can be ~0.5Mbps

while((*pSPIDMAC & SPIDMAS) && !(*pSPISTAT & SPIF)) asm("nop;");

*pSPICTL |= TXFLSH | RXFLSH; // Flush registers

*pSPISTAT |= TUNF | ROVF; // Clear errors

*pSPIDMAC = 0;

*pSPIFLG = 0xFF00; // no flags

*pSPIBAUD = 10000;

*pSPICTL = GM | TIMOD1 | WL8 | SPIMS | SPIEN | MSBF;

ClearCE();

SetCS();

Wait(100);

// The wireless doesn't like it when you

// send everything all at once. Need to send

// it byte by byte

for (int i = 0; i < sizeof(ConfigData); i++)

{

*pSPICTL |= TXFLSH | RXFLSH;

*pSPISTAT |= TUNF | ROVF;

sysreg_bit_clr(sysreg_FLAGS, FLG12);

*pTXSPI = *((int*)&ConfigData + i);

Wait(BYTE_DELAY);

while (!(*pSPISTAT & SPIF)) asm("nop;");

sysreg_bit_set(sysreg_FLAGS, FLG12);

}

*pSPIDMAC = 0;

*pSPICTL |= TXFLSH | RXFLSH;

*pSPISTAT |= TUNF | ROVF;

Wait(100);

// exit config mode and set for recieving

ClearCS();

SetCE();

}

int rxcnt = 0;

//#pragma optimize_off

CReceivePacket* ReadWireless()

{

sysreg_bit_clr_nop(sysreg_FLAGS, FLG12);

// clock data in

//RecievePacket packet;

int data[2] = {0,0};

// Look for vaild data. This will time out after 0.1 ms

int i;

for (i = 0; i < 100; i++)

{

if(sysreg_bit_tst(sysreg_FLAGS, FLG2))

break;

Wait(1);

}

if (i == 100) // Timed out

return 0;

rxcnt++;

Wait(1000);

*pSPICTL |= TXFLSH | RXFLSH;

*pSPISTAT |= TUNF | ROVF;

*pSPIDMAC = 0;

*pSPIFLG = 0xFF00; // no flags

*pSPIBAUD = 200; // 0.5 Mbps

*pSPICTL = TIMOD2 | WL32 | SPIMS | SPIEN | MSBF;

*pIISPI = (int)data;

*pIMSPI = 1;

*pCSPI = sizeof(data);

*pSPIDMAC = SPIDEN | SPIRCV;

Wait(10000);

// Strobe CE

sysreg_bit_clr(sysreg_FLAGS,FLG11);

Wait(1000);

sysreg_bit_set(sysreg_FLAGS,FLG11);

Wait(100);

sysreg_bit_set_nop(sysreg_FLAGS, FLG12);

return ExtractPacket(data);

}

File: system.cpp

/******************************************************************************

* Title:

* Version: $Revision: 1.12 $

* Filename: $RCSfile: system.cpp,v $

* Author(s): Benjamin Fogle

$Author: 477grp7 $

* Created: 1/16/2007

*

* Purpose: Contains initialization code and helper functions

*

* Update history:

* $Log: system.cpp,v $

* Revision 1.12 2007/04/24 01:39:53 477grp7

* Cleaned up code, moved some functions to more logical places (e.g., Wait())

* and removed obsolete declarations.

*

* Revision 1.11 2007/04/23 15:43:57 477grp7

* no message

*

* Revision 1.10 2007/04/22 18:58:39 477grp7

* no message

*

* Revision 1.9 2007/04/19 01:34:21 477grp7

* fixed bug in PCB_PATCH preprocessor logic.

*

* Revision 1.8 2007/04/18 23:54:25 477grp7

* Added support for multiple 'voices' with different sets of shading/delays.

* Added PCB_PATCH and AUDIO_TEST defines to make testing easier

*

* Revision 1.7 2007/04/18 01:23:41 477grp7

* Finishing wireless commands and also modifying the steering routine for

* multiple sets of delays on one channel.

*

* Revision 1.6 2007/04/12 18:46:55 477grp7

* no message

*

* Revision 1.5 2007/04/11 20:11:12 477grp7

* Major update to command processing/packet interpretation. Was going

* to optimize wireless initialization routine, but wireless was acting very very

* strange.

*

* Revision 1.4 2007/04/11 02:28:52 477grp7

* Working on wireless commands. Cleaning up code a little

*

* Revision 1.3 2007/04/11 00:52:49 477grp7

* no message

*

* Revision 1.2 2007/04/08 23:02:40 477grp7

* Got wireless working finally.

*

* Revision 1.1 2007/03/28 13:53:00 477grp7

* no message

*

* Revision 1.0 2007/03/25 16:45:58 477grp7

* Made major revisions to the structure of the project. It is now organized

* more closely according to funtion. (All audio related routines are in

* audio.cpp, and all wireless command routines are in commands.cpp, etc.)

* More work has been done on the framework for the command routine.

* The old files are preserved to make the log of changes easily available.

* (io.h, wifi.h, interrupts.cpp, classes.cpp are now unused.)

*

* Revision 0.0 2007/01/17 00:22:05 477grp7

* Initial project creation

*

*

*****************************************************************************/

#include

#include

#include

#include

#include

#include

#include "DSP.h"

#include "ad1835.h"

#include "commands.h"

#include "audio.h"

#include "system.h"

/******************************************************************************

* Helper function declarations

*****************************************************************************/

void OnWaitTimer(int sig); // For the Wait() function

/******************************************************************************

* Global variables (static linkage)

*****************************************************************************/

static volatile int WaitTimerFlag = 0;

/******************************************************************************

* Functions

*****************************************************************************/

void OnWaitTimer(int)

{

WaitTimerFlag = 0;

}

void Wait(int us)

{

WaitTimerFlag = 1;

timer_off();

interrupts(SIG_TMZ, OnWaitTimer);

timer_set(us * 200, us * 200);

timer_on();

while(WaitTimerFlag);

timer_off();

}

void Init()

{

// Interrupts initially disabled

InitIO();

InitSystem(); // Power off, etc.

Wait(10000); // 10ms startup time from power on for devices (wireless)

InitWireless(RX_CHANNEL, SPEAKER_ADDR, 1); // Initially receiving

InitAudio();

}

void InitSystem()

{

interrupts(SIG_TMZ, OnWaitTimer); // For wait function

// Set initial system state

PowerDown();

DisableAudio();

SelectInput(0);

SetVolume(0); // Initially mute

LoadSteering(0);

LoadEq(0);

}

Flash Programmer Software Listing (Modified Analog Example Code)

File: ppflash.h

///////////////////////////////////////////////////////////////////////////////////////

//NAME: ppflash.h (AMD Parallel Flash Programmer)

//DATE: 9/18/03

//PURPOSE: contains the definitions and declarations for use across the project files

////////////////////////////////////////////////////////////////////////////////////////

#ifndef _PPFLASH_H_

#define _PPFLASH_H_

//Include the ADSP-21262 Definition file

#include

#include

//LED address on the ADSP-21262 Ezkit Lite

#define LED_ADDRESS 0x1400000

#define FLASH_START 0x1000000

//Sector Size for the AMD Am29LV081B

#define SECTOR_SIZE 0x10000

//Declarations of buffers and subroutines used between files

extern int ppInterruptFlag;

void blockWrite(int *, int *, int);

void flashReset(int *);

void sectorErase(int *, int);

void chipErase(int *);

void programBlock(int *, int *, int);

void verifyBlock(int *, int *, int);

void writeToPP(int *, int *, int);

int readFromPP(int *);

int pollFlash(int *);

void writeToLEDs(int);

void ppInterruptHandler(int);

void WriteByte(int* addr, int data);

int ReadByte(int* addr);

#endif

File: main.c

///////////////////////////////////////////////////////////////////////////////////////

//NAME: main.c (AMD Parallel Flash Programmer)

//DATE: 9/18/03

//PURPOSE: Program the Parallel Flash for the ADSP-21262 Ezkit

//

//USAGE: This file contains the main code for programming the PP flash on the

// ADSP-21262 Ezkit lite.

//

// If more than one file is to be programmed, either include all files in the

// same buffer (for contiguous location), or make sure that the files will not

// occupy any common 64K sectors in the flash, as programming the subsequent

// buffers will erase parts of the previously programmed buffers.

//

// For the AMD Am29LV081B the sectors occupy the following byte addresses:

// Sector Address Range

// SA0 0x00000 - 0x0FFFF

// SA1 0x10000 - 0x1FFFF

// SA2 0x20000 - 0x2FFFF

// SA3 0x30000 - 0x3FFFF

// SA4 0x40000 - 0x4FFFF

// SA5 0x50000 - 0x5FFFF

// SA6 0x60000 - 0x6FFFF

// SA7 0x70000 - 0x7FFFF

// SA8 0x80000 - 0x8FFFF

// SA9 0x90000 - 0x9FFFF

// SA10 0xA0000 - 0xAFFFF

// SA11 0xB0000 - 0xBFFFF

// SA12 0xC0000 - 0xCFFFF

// SA13 0xD0000 - 0xDFFFF

// SA14 0xE0000 - 0xEFFFF

// SA15 0xF0000 - 0xFFFFF

//

//

////////////////////////////////////////////////////////////////////////////////////////

#include "ppflash.h"

#include

//Declare the destination address in the flash of the file

#define LDR_START_ADDR 0x1000000

#define FLASH_START 0x1000000

#define EQ_START 0x1080000

#define DELAYS_START 0x10F0000 // good enough for 15 divisions h & v

#define SHADING_START 0x10F8000

#define SRAM_START 0x1200000 // only for in-circuit programming now

//Declare the width of the data in the file to determine the number of bytes

//Change this declaration in the LDF file also for correct packing.

#define FILE_DATA_WIDTH 32

//Declare a semaphore variable to use in the parallel port interrupt

int ppInterruptFlag = 0;

//Declare a variable in external memory to hold the file data to program

#pragma section("seg_ext", DMAONLY)

int ldr_source[] = {

//#include "input.ldr"

#include "..\DSP\Debug\DSP.ldr"

};

// Load the equalizers

#pragma section("seg_coeff", DMAONLY)

float coeff_data[] = {

#include "EqPreset0.csv"

};

// Load the delays

#pragma section("seg_delays", DMAONLY)

int delays[] = {

#include "Delay0.csv"

,

#include "Delay1.csv"

,

#include "Delay2.csv"

,

#include "Delay3.csv"

,

#include "Delay4.csv"

,

#include "Delay5.csv"

,

#include "Delay6.csv"

,

#include "Delay7.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

,

#include "Delay0.csv"

};

#pragma section("seg_fade", DMAONLY)

float fades[] = {

#include "Fade0.csv"

,

#include "Fade1.csv"

,

#include "Fade2.csv"

,

#include "Fade3.csv"

,

#include "Fade4.csv"

,

#include "Fade5.csv"

,

#include "Fade6.csv"

,

#include "Fade7.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

,

#include "Fade0.csv"

};

//Main routine - add calls to blockWrite for each buffer holding file data

void main()

{

*pPPCTL &= ~(PPEN|PPDEN);

//Set up the interrupt for the parallel port

interrupt(SIG_PP,ppInterruptHandler);

//Workaround for C Runtime problem (fixed with patch released 10/03/2003)

interrupt(SIG_SP1, SIG_IGN);

flashReset((int*)FLASH_START);

chipErase((int *) LDR_START_ADDR);

blockWrite(ldr_source,(int *) LDR_START_ADDR,sizeof(ldr_source)*FILE_DATA_WIDTH/8);

blockWrite((int*)coeff_data, (int*)EQ_START, sizeof(coeff_data)*FILE_DATA_WIDTH/8);

blockWrite((int*)delays, (int*)DELAYS_START, sizeof(delays)*FILE_DATA_WIDTH/8);

blockWrite((int*)fades, (int*)SHADING_START, sizeof(fades)*FILE_DATA_WIDTH/8);

}

File: blockWrite.c

///////////////////////////////////////////////////////////////////////////////////////

//NAME: blockWrite.c (AMD Parallel Flash Programmer)

//DATE: 9/18/03

//PURPOSE: Program the Parallel Flash for the ADSP-21262 Ezkit

//

//USAGE: This file calls the subroutines used to program and verify the Flash,

// call this routine with the buffer address, destination address, and byte

// length from the main program.

//

////////////////////////////////////////////////////////////////////////////////////////

#include "ppflash.h"

//----------------------------------------

//BLOCK WRITE SUBROUTINE

//Calls all of the Flash subroutines necessary to program the flash

//Inputs - buffer_src_addr - address of the buffer holding the 32-bit words to write (pointer)

// buffer_dest_addr - address to write to in external memory (pointer)

// buffer_length - number of bytes to write.

//Returns- none

void blockWrite(int *buffer_src_addr,int *buffer_dest_addr,int buffer_length)

{

int numSectors;

//Reset the state of the flash

flashReset(buffer_dest_addr);

//Calculate the number of sectors to be programmed (min = 1)

// numSectors = (buffer_length >> 16) + 1;

//Erase that number of sectors

// sectorErase(buffer_dest_addr,numSectors);

//program the flash with the selected data

programBlock(buffer_src_addr,buffer_dest_addr,buffer_length);

//verify that the flash was programmed correctly

verifyBlock(buffer_src_addr,buffer_dest_addr,buffer_length);

}

File: flashFunctions.c

///////////////////////////////////////////////////////////////////////////////////////

//NAME: flashFunctions.c (AMD Parallel Flash Programmer)

//DATE: 9/18/03

//PURPOSE: Program the Parallel Flash for the ADSP-21262 Ezkit

//

//USAGE: This file contains the subroutines called to program the PP Flash on the

// ADSP-21262 Ezkit lite.

//

////////////////////////////////////////////////////////////////////////////////////////

#include "ppflash.h"

//----------------------------------------

//RESET THE STATE OF THE FLASH SUBROUTINE

//Writes the reset command to the Flash

//Inputs - flash_addr - address to write to in external memory (pointer)

//Returns- none

//Address is only required to make sure that the flash is selected by the address decoder

void flashReset(int *flash_addr)

{

WriteByte((int*)FLASH_START, 0xF0);

}

//----------------------------------------

//SECTOR ERASE SUBROUTINE

//Erases the selected number of sectors in the flash, starting with the supplied address

//Inputs - flash_addr - address to write to in external memory (pointer)

// num_sectors - number of 32-bit words to write.

//Returns- none

void sectorErase(int *flash_addr, int num_sectors)

{

int wordToWrite[2] = {0x55aa0000, 0x3055aa80};

int i;

//Send the erase command once for each affected sector

for(i=0;i Check_Length))

{

Data_Bit = IR_Input;

Received_Bits = Received_Bits | Data_Bit;

Received_Bits = Received_Bits 600) && (Num_Received_Bits == 2))

if (TRF_Count > 5000)

{

trf_set();

TRF_Count = 0;

Sync=0;

Received_Bits = 0x03;

Num_Received_Bits = 2;

}

if (Num_Received_Bits == 43)

{

#asm("cli");

// printf("%X received\r", Received_Bits);

process_ir_signal(Received_Bits);

Sync=0;

Received_Bits = 0x03;

Num_Received_Bits = 2;

#asm("sei");

}

}

return 0;

}

/****************************************************************************************

*****************************TRF Functions***********************************************/

void trf_spi(unsigned char Data)

{

/* TRF needs a delay between consecutive data transfers. This function is here to make code

easier to read and modify. */

SPDR = Data;

delay_ms(15);

return;

}

void trf_time_delay()

{

/* TRF needs a delay between settings changes. This function is here to make code

easier to read and modify. */

delay_ms(30);

return;

}

/***************************************************************************/

void boot_shockburst()

{

int i;

CS = 1;

CE = 0;

delay_ms(25);

for(i=0;i> 4;

trf_spi(Feed_TRF);

Feed_TRF = Packet_ID & 0x00FF;

Feed_TRF = Feed_TRF ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download