Transcript
Tyler Cardon
[email protected] May 5, 2011 Dr. Don Cripps Electrical and Computer Engineering Department Utah State University Dear Dr. Cripps, This is the final report for my design project for your review and approval. I’ve written an SDHC (Secure Digital High Capacity) flash card driver and .flac (Free Lossless Audio Codec) codec on an 8-bit microcontroller. My final report outlines the course of my design from preliminary to finish. Complete assembly code is provided in Appendices A through K. Feel free to skip the assembly code. I wrote many parts of this report to gather what I have learned over the semester. I’ve summarized technical knowledge I’ve gained in section 4.2. Your Student, Tyler Cardon
i
Portable Audio Player Tyler Cardon USU Electrical and Computer Engineering Engineering Design Final Report Spring 2011
ii
Table of Contents 1. Introduction .............................................................................................................................................. 1 1.1 Subject and Purpose .................................................................................................................. 1 1.2 Problem Statement .................................................................................................................... 1 1.3 Design Objectives ....................................................................................................................... 2 1.4 Summary of Design Processes ................................................................................................... 2 2. Review of Conceptual and Preliminary Design ....................................................................................... 3 2.1 Problem Analysis ........................................................................................................................ 3 3. Basic Solution Description ....................................................................................................................... 6 3.1 System Schematic ...................................................................................................................... 6 3.2 Initial System Performance Estimate ........................................................................................ 8 4. Performance Optimization and Design of System Components ............................................................ 9 4.1 Description of Components and Component Level Specifications ............................................ 9 4.1.1 Summary of C8051F020 8-bit 8051 Family Microcontroller...................................... 9 4.1.2 Summary of SDHC Specifications .............................................................................. 9 4.1.3 Summary of Displaytech 128x64 Dot LCD Specifications ........................................ 10 4.2 Software Specifications ............................................................................................................ 11 4.2.1 Summary of FAT32 Specifications............................................................................ 11 4.2.2 Summary of .WAV File Format................................................................................. 14 4.2.3 Summary of .FLAC File Format ................................................................................ 15 4.2.3 Summary of Rice Encoding ..................................................................................... 17 4.2.4 Summary of Cyclic Redundancy Checks (CRC’s) ...................................................... 18 4.3 Methods of Code Optimization................................................................................................ 18 4.4 SDHC Card Transfer Speed Optimization ................................................................................ 20 4.5 Acquisition of Specifications ................................................................................................... 21 5. Project Implementation/Operation and Assessment ........................................................................... 22 5.1 Details of Implementation (Hardware) ................................................................................... 22 5.2 Details of Implementation (Software) ..................................................................................... 22 5.2.1 Playlist Manager ...................................................................................................... 22 5.2.2 Audio Player ............................................................................................................. 26
iii
5.2.3 Initialization ............................................................................................................. 28 5.2.4 Stage 1...................................................................................................................... 28 5.2.5 Stage 2 ..................................................................................................................... 28 5.2.6 Stage 3...................................................................................................................... 28 5.2.7 SDHC Driver.............................................................................................................. 29 5.2.8 .WAV Decoder.......................................................................................................... 31 5.2.9 .FLAC Driver.............................................................................................................. 32 5.2.10 Header Files ........................................................................................................... 32 5.3 Summary of the Final Results .................................................................................................. 33 5.4 Performance Verification ........................................................................................................ 34 5.5 Performance Evaluation .......................................................................................................... 35 6. Final Scope of Work Statement ............................................................................................................. 36 6.1 Summary of What Has Been Done........................................................................................... 36 6.2 Summary of What Still Needs to Be Done ............................................................................... 36 6.3 Lessons Learned and Suggestions for Future Activities ........................................................... 36 7. Other ....................................................................................................................................................... 38 7.1 Material and Component Suppliers ......................................................................................... 38 7.2 Impacts of my Solution in a Global, Economic, and Societal Context ..................................... 38 8. Cost Estimation....................................................................................................................................... 39 8.1 Estimate of System Costs ......................................................................................................... 39 8.2 Estimate of Development Costs............................................................................................... 40 9. Project Management Summary ............................................................................................................. 42 9.1 Time: GANTT Chart .................................................................................................................. 42 10. Conclusion ............................................................................................................................................ 43 Appendix A Playlist Manager ..................................................................................................................... 44 Appendix B new.asm.................................................................................................................................. 59 Appendix C GUI_r.h .................................................................................................................................... 62 Appendix D ISR_r.h..................................................................................................................................... 88 Appendix E MP3_r.h................................................................................................................................. 116 Appendix F SDHC_r.h ............................................................................................................................... 139 Appendix G Math_r.h ............................................................................................................................... 155 iii
Appendix H WAV_r.h ............................................................................................................................... 164 Appendix I FlAC_r.h .................................................................................................................................. 173 Appendix J LPC_r.h ................................................................................................................................... 205 Appendix K var_const.inc......................................................................................................................... 220 Appendix L Bibliography ............................................................................................................................ 43
List of Tables 1. Estimate of System Cost.......................................................................................................................... 39 2. Estimate of Development Cost ............................................................................................................... 40
List of Figures 1. Preliminary System Overview ................................................................................................................... 4 2. Post Design Review System Overview ...................................................................................................... 5 3. Modified C8051F020 Training Board Schematic....................................................................................... 6 4. C8051F020 Port Interfacinc Schematic ..................................................................................................... 7 5. Audio System Schematic ........................................................................................................................... 7 6. SD Family Card Pinout ............................................................................................................................. 10 7. S64128N Two Tone LCD .......................................................................................................................... 11 8. FAT/ FAT32 Hard Drive Organization ..................................................................................................... 12 9. Wav file Format and Data Chunks .......................................................................................................... 14 10. Wav file List Chunk ................................................................................................................................ 14 11. Rice Encoded Residuals ......................................................................................................................... 17 12. FAT32 File Index .................................................................................................................................... 24 13. Contents of all.dat................................................................................................................................. 24 14. Contents of all.pla ................................................................................................................................. 25 15. Contents of all_pl.plx ............................................................................................................................ 25 16. Baroque.pla ........................................................................................................................................... 26 17. SDHC Initialization State Diagram ......................................................................................................... 30 18. SDHC Data Transfer Mode .................................................................................................................... 31 19. GANTT Chart ......................................................................................................................................... 42
iv
Acknowledgements
I would like to acknowledge my course instructors, Dr. Donald Cripps and Laura Vernon.
Thanks also to Dr. Paul Wheeler for providing me with some guidance in my design reviw. I have a lot of appreciation for Josh Coalson, open source developer of FLAC who personally answered some of my questions about decoding. I would also like to thank Brian
Langenberger and Kay Gorontzi for their online publications of Audio Formats, and CRC, respectively. Lastly, thanks to all of the contributors at Wikipedia.org.
iv
1. Introduction 1.1 Subject and Purpose In the spirit of culminating all the material that Electrical and Computer Engineering
students learn at USU, each student is required to propose and design a capstone project. The project is to be of practical use in society and is also to fill a social need.
This document is a report on my capstone project. As a report, it encompasses all of
the details of my design, and design decisions.
1.2 Problem Statement I proposed, for my project, a handheld audio player. The challenge was to design a
handheld audio player that is unique from all of the other handheld audio players on the market. To meet this challenge, I have designed my project with some unique features.
User Convenience: My project operates on swappable rechargeable or disposable AA
batteries. It also supports SDHC (Secure Digital High Capacity) general purpose flash
memory cards which are used in several other devices, compatible for use with modern PC’s, and popular as a method of portable data storage. The device’s SDHC card can be used for general purpose storage, not just storage of audio files.
Lossless Audio Compression Support: As insufficient PC and portable memory disk
space is becoming less and less of an issue people are becoming more comfortable with using higher quality audio files at the expense of the file occupying more drive space.
Lossless audio compression is the compression of all of an audio file’s audio data, whereas lossy audio compression compresses audio files by first eliminating “unnecessary” audio data from the file. My audio player supports the lossless .flac (free lossless audio compression) audio file type, and uncompressed .wav files. 1
1. Introduction
1.3 Design Objectives As a portable audio player, my design meets the following objectives: • • • • • • • • •
It operates on portable batteries. It uses an LCD with a graphical user interface. It has an earphone jack for the user to listen to music through. It has user controls to navigate through songs and playlists. It has PC-based playlist management software. It supports the use of SDHC memory cards in the fastest mode of data transfer. It supports 44.1 kHz, 16 bit mono .wav file playback. It supports 12 kHz, 16 bit mono .flac file playback. It supports navigation through several songs and playlists.
1.4 Summary of Design Processes
The design was implemented with an 8-bit microprocessor training board. Hardware such as the SDHC card, audio amplifier, LCD, and power system, were interfaced to on through-hole perforated board. Drivers for the LCD and SDHC card, as well as audio file decoding and the graphical user interface were all programmed in 8-bit (8051) assembly and run on a c8051f020 microcontroller. The playlist management software for PC was written in 32-bit assembly (x86 with an FASM assembler) and runs on a windows PC.
2
2. Review of Conceptual and Preliminary Design 2.1Problem Analysis The original problem statement was that I needed to make an audio player with the following unique qualities: flexible software, “plug and play” adaptability, and long battery life. Since then, flexible software and long battery life have been eliminated from the goals of the project. The reason why flexible software is no longer a goal is because the 8-bit c8051f020 has reached its limits in decoding .flac files. The expandability of the product is limited and focus shifted towards making it functional. Long battery life is also a goal that seemed desirable at the beginning of the project but which later became impractical because of time constraints and the need to focus on functionality.
The original objectives for the product were stated as follows: •
It must have a PC – USB interface.
•
It must include Flash drive data management software for the PC.
•
It must give the user the control he/she expects when using an mp3 player: volume control, song navigation, playback modes.
•
It must provide a visual interface for the user.
•
It must provide quality audio playback via headphones.
•
It must have a custom SD-mode driver.
The PC-USB interface was decided to be unnecessary. Many modern PCs have SD card slots, and USB adapters for SD cards are common and inexpensive. Having the USB interface connected to the prototype also caused conflicts with the SD card’s in/out bus. The other objectives were all kept.
3
2. Review of Conceptual and Preliminary Design The original design concept was overly complicated and flawed. The plan was to handle all audio data externally to the microcontroller to reduce microcontroller operation speed (thus reducing power consumption) or also allow for the adding of video file support in the future (because the microcontroller would see little load from handling audio). This was to be done with a CPLD (complex programmable logic device) which was to retrieve audio data from the SDHC card and send it to an external DAC (digital to analog converter). A preliminary system overview is shown in figure 1. That aspect of the preliminary design was flawed because it didn’t account for the complexity of audio decoding, the inability of a CPLD to decode compressed audio, and the enormous load which decoding audio by itself places on an 8-bit microcontroller.
Figure 1 Preliminary System Overview
The system was simplified after the design review, as shown in figure 2. Simplifications included the removal of the CPLD data driver, the external DAC, and the buffer RAM. The 4
2. Review of Conceptual and Preliminary Design external DAC was originally to be interfaced with the data driver so that the microcontroller didn’t have to process audio data. The buffer RAM was to hold playlist information so that songs could be listened to while browsing through playlists. The external DAC was not necessary after I decided that audio data would be processed by the microprocessor as the c8051f020 has two internal DACs.
Figure 2 Post Design Review System Overview
The only change that has been made since the post design review system overview is that the product only handles mono (single channel) audio. .Flac files, as well as some other audio file types, have samples from different channels stored in separate frames, so that one channel’s frame must be accessed and processed (or at least stored in RAM) before another channel’s frame can be accessed. Decoding multiple channels is far too cumbersome for the c8051f020 when playing .flac file types. 5
3. Basic Solution Description 3.1 System Schematic I used a silicon labs c8051f020 training board. I removed the original power and
oscillator systems so I could replace them with the new ones shown in the schematic in figure 3.
Figure 3 Modified C8051f020 Training Board Schematic
Interfacing to the SDHC card, LCD, and pushbuttons was done with the general
purpose i/o ports of the c8051f020, as well as the external memory interface on ports 4 through 7. Peripherals were interfaced to with wire-wrapping based on the schematic shown in figure 4. 6
3. Basic Solution Description
Figure 4 C8051F020 Port Interfacing Schematic
Figure 5 Audio System Schematic
7
3. Basic Solution Description
3.2 Initial System Performance Estimates I initially estimated that the system would be capable of having fifty hours or more of battery life, and that the c8051f020 would be powerful enough for any audio file decoding and even video decoding. Since then I have realized that lossless audio decoding alone has proved too strenuous for the c8051f020, however a functional .flac player can be realized. More specifically, of the levels of .flac compression, fixed linear predictor compression can be decoded by the c8051f020, but LPC compression cannot be decoded by the c8051f020. For more information about .flac compression, see section 4.2.3.
8
4. Performance Optimization and Design of System Components 4.1 Description of Components and Component Level Specifications 4.1.1 Summary of C8051F020 8-bit 8051 Family Microcontroller Some of the used features of the c8051f020 include use of an external oscillator, 4kB internal XRAM (external RAM), 64kB programmable flash ROM, four 8 byte register banks, 16 bytes bit addressable general purpose RAM, 80 bytes general purpose RAM, four timers, a programmable counter array, built in external memory interface, two 12-bit DAC’s with internal reference, and 64 bits general purpose in/out port pins configurable as push-pull or open drain. The c8051f020 has a CIP-51 core, which is significantly slower (in instruction execution) than the C51, despite the c8051f020’s abundance of features in other areas.
4.1.2 Summary of SDHC Specifications SDHC cards have 9 pins, as shown in figure 6. Through those nine pins, 4-32 GB of memory must be accessed for read and write functions. This is done through a set of commands issued serially to the SD card on pin 2. Pin 2 is the CMD line in SD mode, or alternatively it is the MOSI line (master out slave in) when the SD card is interfaced to in SPI (serial peripheral interface) mode. SD mode is the faster mode of transfer, by which SDHC cards can transfer at a rate of 2 megabytes per second and higher. In SD mode, the SDHC card receives commands and issues responses serially on the CMD line, and receives and transmits data on the 1-4 bit wide DAT bus (pins 7, 8, 9, and 0). My design drives an SDHC card in 4-bit SD mode. The clock, pin 5, can be provided by a microcontroller. This gives the advantage of being able to pause and resume communication with the SDHC card at will.
9
4. Performance Optimization and Design of System Components
Figure 6 SD Family Card Pinout (from the SD simplified specifications)
4.1.3 Summary of Displaytech 128x64 Dot LCD Specifications The S64128N has a Sitronix ST7565R LCD Controller/Driver. It is designed for interfacing with Motorola or Intel family 8-bit microcontrollers via an external memory interface. The pin out of the LCD is shown in figure 7.
10
4. Performance Optimization and Design of System Components
Figure 7 S64128N Two Tone LCD
It has an 8-bit data bus, read and write enables, a chip select and a single address line. The address line is used to tell the LCD controller whether the data on the data bus is graphical data, or a command from the microcontroller. By default, graphical data is interpreted by the LCD controller as a high bit being an on pixel, and a low bit being an off pixel.
4.2 Software Specifications 4.2.1 Summary of FAT32 Specifications FAT32 (File Allocation Table 32) and FAT are the default format for SD family flash
cards. In the FAT and FAT32 format, a hard drive is divided into 512 byte to 32 kilobyte clusters. A new file may be allocated a cluster address and written at the beginning of a
cluster. The hard drive also utilizes another unit called the sector. A sector is usually 512 11
4. Performance Optimization and Design of System Components bytes. Figure 8 shows the five basic sections of a FAT hard drive. Sector 0 contains the
sector address of the boot sector. The most recently sector address written to is stored in
the boot sector. It also contains the cluster size (in sectors), and number of hidden sectors before the file allocation table (which can be used to calculate the file allocation table
index). The boot sector contains the number of copies of the file allocation table, and the
size of the file allocation table (both of which can be used to calculate the address of the first file index).
Figure 8 FAT/ FAT32 Hard Drive Organization
When a file is added to the root directory of the hard drive, its basic information is
added to the file index (name, extension, date of modification, cluster address relative to
the file index, file size, etc.). If the file’s name does not fit the 8-3 format (eight characters for the name and three for the extension), a long file name is stored preceding the file’s
entry in the file index. If a folder is created on the root directory of a drive, the folder is 12
4. Performance Optimization and Design of System Components allocated its own file index, and the address of that file index as well as the folder’s name
are stored on the root file index. If a file is deleted from the hard disk, its entry in the file
index is assigned a 0xE5 over the first character of the entry’s name, the index is preceded by a long file name which gives the original name of the file, and the file’s data on the hard drive remains intact until overwritten (it will be about the last place overwritten). New
data will not be written over a deleted file until all other free space of the hard drive has
been filled, the hard drive is reformatted and new data is written to the reformatted hard drive (reformatting the hard drive alone does not remove the physical data on the hard
drive, it only starts a fresh file allocation table and file indexes), or perhaps if the hard drive is defragmented and the contents of the hard drive are reorganized (unconfirmed) it may be overwritten in the process or afterwards.
Given this knowledge of a FAT32 hard drive, a driver for accessing the data on an
SDHC card can be written. The FAT32 driver on my c8051f020 locates the sector address of the first file index using the specifications outlined in the previous two paragraphs and locates critical files. The critical file located and accessed on resetting the system is “all_pl.plx”, an index of all of the audio player’s playlists, which also gives the sector
addresses of all the playlists. The index of playlist names is displayed on the LCD providing the user the interface to select a playlist.
Because Windows versions after Windows 95 do not give the user direct access to
hardware, a complete driver for reading the SDHC card and providing management was not finished for the PC. However, my PC based playlist manager uses information from the SDHC’s file index (provided to the program manually) to create playlists. 13
4. Performance Optimization and Design of System Components 4.2.2 Summary of .wav File Format The common .wav (Waveform Audio File Format) file is uncompressed and uses the
RIFF standard. Basic information such as sample size, sampling frequency, number of
channels, file size, number of samples, are included at the beginning of the .wav file in the
format chunk (seen in figure 9 after “fmt”). The number of audio samples and the samples themselves are given after the file details in the data chunk. Then file tags (information about the song i.e. title, album, artist, etc.) are included at the end of the file. Multiple
channel .wav files provide a single sample from each channel before giving proceeding
samples. .Wav files use the big-endian convention. Samples of sizes sixteen bits or more are stored as signed integers. Signed integers must have an offset added to them before
sent to the DAC to center them at half of the DAC’s reference voltage. Samples of sizes less than sixteen bits are stored as unsigned integers with centering offset added.
Figure 9 Wav file Format and Data Chunks (16-bit samples)
Figure 10 Wav file List Chunk (song tags)
14
4. Performance Optimization and Design of System Components 4.2.3 Summary of .flac File Format .Flac files compress an audio file without the loss of any of the original audio data.
This is done primarily through three compressing methods, two of which take advantage of Rice Encoding. UTF-8 is also used somewhat for the compression of multi-byte non-audio data.
A .flac file consists of metadata blocks and audio frames. The only mandatory
metadata block is the infostream metadata block which contains file specific information-
sample size, sampling frequency, number of samples, etc. Additional metadata blocks may follow which such as a seek table, vorbis format song tags (example “artist=Bach”,
“album=Nevermind”), album art, etc. The metadata blocks are proceeded by audio frames of variable or fixed length. The length of audio frames is flexible because most common encoding schemes in .flac will predict the entire frame with a multiple order difference equation (given in the subframe header) and encoded residuals (encoded in the audio frame in rice partitions- see section 4.2.4).
The simplest encoding scheme used in .flac encoding is a constant frame. A constant
frame is used when all of the samples of the frame have the same value. The number of
samples in the frame is given, and the constant value of those samples is given (usually “0” for silence).
The simpler predictor encoding scheme used in .flac encoding is fixed predictor
encoding. In fixed predictor encoding, the order of the difference equation is given as a number between zero to four. A number of warm-up samples are given equal to the
predictor order of the frame. For a zero order fixed frame, no warm-up samples are given
15
4. Performance Optimization and Design of System Components and the next sample equals the residual. For a first order fixed frame, the first sample
equals the warm-up sample and proceeding samples equals the previous sample plus the residual. For second to fourth order fixed frames, refer to the equations below. The
residual is a signed number giving the difference between the actual value of the next sample, and the value predicted by the difference equation. Fixed Predictor Order 0: f[n] = residual
Fixed Predictor Order 1: f[n] = f[n-1] + residual
Fixed Predictor Order 2: f[n] = 2*f[n-2] – f[n-1] + residual
Fixed Predictor Order 3: f[n] = 3*f[n-3] – 3*f[n-2] + f[n-1] + residual
Fixed Predictor Order 4: f[n] = 4*f[n-4] – 6*f[n-3] +4*f[n-2] –f[n-1] + residual A more complicated prediction method used by .flac is LPC (Linear Predictor
Coding). LPC follows the same format is fixed predictor encoding except that the
coefficients of the difference equation are not fixed. In fact, the precision of the signed coefficients (in numbers of bits) is not fixed either. After the result of the difference
equation is calculated it must be divided by a power of 2 (the power is provided in the frame header) and then the residual is added. .Flac encoding supports LPC predictor
orders from 1 to 32, and coefficient precision from 1 to 15 bits. In the worst case scenario,
the decoder must calculate the result of a 32nd order difference equation with 15 bit signed
coefficients, shift the result, decode the residual, then add it- a nightmare in 8-bit assembly, and impossible to implement at realistic sampling frequencies on an 8-bit microcontroller. I wrote some LPC codec for my c8051f020, but it was unable to perform it fast enough.
16
4. Performance Optimization and Design of System Components 4.2.4 Summary of Rice Encoding Frames have a frame header, and sub-frames for each independently encoded
channel. In a sub-frame are the sub-frame header and the rice partitions which contain residuals. A single sub-frame of 16 to 65,336 samples may be divided into 1 to 16 rice
partitions. A rice partition is preceded by a rice parameter between the values of 0 to 31.
Rice encoding is bit-wise method of encoding a signed integer. The least significant
bits of the residual are a number of un-encoded bits (the number of bits is determined by
the rice parameter). The most significant bits are a unary encoded number before the unencoded bits. The least significant bit is the sign. For a negative number, the value before
the sign must be incremented and negated. The unary encoded number is the number of 0 bits which precede a 1 bit. A visual example (provided by Brian Langerberger) using rice parameter 1 is provided below in figure 11.
Figure 11 Rice Encoded Residuals (provided by Brian Langerberger)
17
4. Performance Optimization and Design of System Components 4.2.5 Summary of Cyclic Redundancy Checks (CRC’s) CRC’s are a binary number usually appended to the end of a string of data. They can
be used to determine if the string of data is valid or if the data has been corrupted during a transmission.
My audio file player does not check the CRC’s provided to it from transmission from
the SD card, or those given in .flac files. Successful transmission of data is assumed, as
SDHC flash cards are not sensitive to movement like CD drives or hard drives are. However, my audio player must generate CRC’s to append to the commands it issues to the SDHC
card. All commands issued to the SDHC card, and responses supplied from it, have a CRC-7 and stop bit appended to them. A CRC is given by a polynomial which can be represented
by a binary number. A CRC-7 is calculated by a seventh order polynomial, and the result of the CRC-7 generator is a seven bit value. The CRC-7 used in SD family cards is x^7 + x^3 +
x^0, represented in binary as 10001001. CRC-8’s and CRC-16’s are provided in .flac files
and are ignored by my audio player.
An in-depth verbal description of CRC generation would be the clumsiest of the
features of my report and I am inclined to forego giving a verbal explanation. CRC
generation routines, are provided in my x86 and 8-bit assembly source code provided in Appendix A and Appendices B through K.
4.3 Methods of Code Optimization The majority of optimization is done in coding. I will discuss some of the techniques
I used for optimizing code for speed at the expense of size. The most common method I
used was the elimination of loops when speed was critical, and unnecessary routine calls. 18
5. Project Implementation/Operation and Assessment This resulted in a lot of redundancy in the code, but speed was critical as decoding was done between periods of the sampling frequency.
As an example of loop elimination, the microcontroller must compliment the clock
of the SDHC card 64 times after the transmission of every 512 bytes (referred to as a block
in the SDHC specifications). This is done to ignore the 8 bit CRC (transmitted in 16 cycles)
and 16 cycles of the DAT lines held high after CRC transmission (perhaps the purpose of the 16 cycle pause is to give the microcontroller time to verify the CRC7). 128 instruction
cycles are used to compliment the CLK line 64 times. Complimenting the clock in a loop
would increase the number of instruction cycles used to 640 cycles (djnz takes 3-4 cycles to
execute on the c8051f020’s CIP-51 core). Instead of complimenting the clock 64 times in a loop, it is done by calling a routine, clear_64, which uses 128 instruction cycles to
compliment th CLK line 64 times, with an extra 4 cycles for the call, and 5 cycles for the return, for a total of 73 instruction cycles. The extra nine cycles are sacrificed for the
convenience of not writing 64 instructions of “cpl SCLK” each time the SDHC card’s CRC7 must be ignored, and the solution is better for speed than the use of a loop.
A few more example of code optimization can be shown in .flac’s fixed predictor
decoding. The equations for decoding a 0 to 4th order fixed predictor frame of audio samples is given by the equations below:
Fixed Predictor Order 0: f[n] = residual
Fixed Predictor Order 1: f[n] = f[n-1] + residual
Fixed Predictor Order 2: f[n] = 2*f[n-2] – f[n-1] + residual
Fixed Predictor Order 3: f[n] = 3*f[n-3] – 3*f[n-2] + f[n-1] + residual
19
Fixed Predictor Order 4: f[n] = 4*f[n-4] – 6*f[n-3] +4*f[n-2] –f[n-1] + residual
5. Project Implementation/Operation and Assessment Though it would be easier to develop an algorithm or loop that handled all of the
five fixed predictor order cases, to optimize decoding for speed I used the following methods:
1. I handled each case separately in a switch, or case structure code. 2. I handled the more difficult (higher) predictor orders at the beginning of the switch, or case structure code. 3. I rearranged the terms for fewer multiplications, i.e. 4*{f[n-4] + f[n-2]} – 6*f[n-3] – f[n-1] + residual, instead of 4*f[n-4] – 6*f[n-3] +4*f[n-2] –f[n-1] + residual, so that the highest number of multiplications used in fixed predictor frame decoding per sampling period was 2.
4.4 SDHC Card Transmission Speed Optimization
My system reads a byte from the SDHC card (when it is in multiple block read mode)
in 32 instruction cycles with conditional instructions taking up to 81 additional cycles (for
the case of ignoring the CRC). In many cases in .flac decoding, the instructions are inserted into the code instead of calling the routine, reducing the time required for reading a byte from the SDHC card to 23 instruction cycles 99% of the time.
get_byte: {4 for call} cpl sclk (2) cpl sclk (2) mov a, sdhc (2) anl a, #0F0H (2) mov r4, a (1) cpl sclk (2) cpl sclk (2) mov a, sdhc (2) anl a, #0F0H (2) swap a (1) add a, r4 (1) djnz r3, fin_gb (4) djnz r2, fin_gb {4 conditional} mov r2, #2 {4 conditional} call clear_64 {73 conditional} fin_gb: ret {5 for return}
20
5. Project Implementation/Operation and Assessment 4.5 Acquisition of Specifications Specifications issued by the developer of the standard were referenced when
available and decipherable. This included the use of SD’s “SD Specifications Part 1 Physical Layer Simplified Specification Version 3.01”, Microsoft’s specifications for FAT32, and .flac
developer, Josh Coalson’s, FLAC Format Documentation. Other internet sources were used as required, and a lot of observations were made on my part by extensive use of a hex editor, and observations made during operation of my system.
21
5. Project Implementation/Operation and Assessment 5.1 Details of Implementation (Hardware) Power is supplied to the microcontroller and all subsystems from an adjustable
switch mode power supply IC. The power supply is not terribly efficient, but allowed me
the convenience of changing the voltage level delivered to the system on multiple occasions. The voltage drop of the power supply is also relatively low, which allows for operation of the system over a very large range of voltages provided by the AA batteries as they discharge. A schematic of the power supply is shown in figure 6.
The project prototype was implemented on a c8051f020 trainer board with the
power system and oscillator removed. A compatible voltage for the c8051f020 trainer
board was provided from the batteries through the adjustable power supply. The 22 MHz crystal oscillator was replaced with a 11 MHz crystal oscillator compatible with the audio sampling frequency of 44.1 kHz.
The remainder of the hardware consists of buttons and interfaces. Pull-up resistors
are included on the bi-directional CMD, and DAT lines of the SDHC. The bi-directional lines
of the SDHC, as well as the port lines connected to user buttons are configured as opendrain, and the rest of the port lines used by the c8051f020 are configured as push-pull.
5.2 Details of Implementation (Software) 5.2.1 Playlist Manager Software for playlist management on the PC is functional but is lacking in features.
It was written in x86 assembly, with the intent of taking advantage of direct access to the SDHC card, effectively being a SD driver, in some respects, for PC. Programming on 22
5. Project Implementation/Operation and Assessment Windows XP, however, I wasn’t allowed direct access to hardware. Source code for the playlist manager is in appendix A.
I can generate several playlists with the PC playlist manager. I will first explain how
a single playlist is generated. Generating a single playlist with the playlist manager works as follows (hex values are little-endian unless specified as big-endian):
1. I add or remove audio files to or from the SDHC card via PC. 2. I make a copy of the entire file index of the SDHC card using a hex editor. 3. I save a copy of the file index in a file named “all.dat” on the flash drive home directory (figure 13). 4. I insert a new line of 32 characters at the beginning of “all.dat” where I type in the cluster size of the SDHC’s FAT partitions in sectors (one byte hex - cluster size in bytes / 512 bytes, big-endian), and I also type in the physical address of the file index (4 bytes hex big-endian). The resulting file all.dat is shown in figure 14. 5. I run the program “inout_conversion.exe” located on the home directory of the flash drive. 6. “Inout_conversion.exe” makes a file all.pla, which contains the number of audio files, the playlist name “All”, physical sector addresses, CRC7’s (cyclical redundancy check) which can be appended to the end of commands to the SDHC by the microcontroller for single or multiple block reads, and song names for all audio files . The end of a playlist or song name is indicated by a single forward slash. The end of the .pla file is indicated by two forward slashes. A screenshot of all.pla is shown in figure 15. 7. I create a file, “all_pl.plx” on the home directory of the flash drive. 8. I type in the number of playlists which I want to be accessible by the audio file player, followed by the title “All Playlists”, to be displayed when I access the playlist navigation menu on the audio player. I type in a 32-bit sector address (found manually), a CRC7 for the read single block and read multiple block commands, followed by the name, terminated by a single forward slash for each playlist. The end of the file is indicated by two forward slashes. A screenshot of all_pl.plx is shown in figure 16.
23
5. Project Implementation/Operation and Assessment
Figure 12 FAT32 File Index
Figure 13 Contents of all.dat
24
5. Project Implementation/Operation and Assessment
Figure 14 Contents of all.pla
Figure 15 Contents of all_pl.plx
25
5. Project Implementation/Operation and Assessment Additional playlists can be added manually by copying and pasting the desired songs
into a new .pla file named after the playlist to be created. The format of the new .pla file must be the same as all.pla’s. The sector address of the new playlist is then manually retrieved, and all_pl.plx is manually updated as described in step 8 described in the
procedure for generating a single playlist. An example of a manually created playlist is shown in figure 16.
Figure 16 Baroque.pla (a manually created playlist)
5.2.2 Audio Player The main loop of the audio player follows a simple state diagram, easily followed by
a reader familiar with assembly coding.
26
5. Project Implementation/Operation and Assessment mairn: mov r0, #7FH clr_all: mov @r0, a djnz r0, clr_all
// clear RAM
call _8051_INITIALIZATION call _LCD_INITIALIZATION call _SDHC_INITIALIZATION call _SDHC_TRANSFER_READY call _XRAM_PLAYLIST_INITIALIZATION STAGE_1: call _INITIALIZE_STAGE_1 call _Display_Menu STAGE_1_loop: jnb push_flag_play,STAGE_1_loop call get_pl_addresses STAGE_2: call _INITIALIZE_STAGE_2 call _Display_Menu jmp stage_2_loop STAGE_2_loop: jnb push_flag_menu,cont_st_2_loop jmp stage_1 cont_st_2_loop: jnb push_flag_play,STAGE_2_loop STAGE_3: call _INITIALIZE_STAGE_3 call _PLAY_SONG STAGE_3_loop: jb push_flag_play, input_decoder_3 jb push_flag_menu, input_decoder_3 jb flag_finish_play, input_decoder_3 jb push_flag_left, input_decoder_3 jb push_flag_right, input_decoder_3 jb push_flag_stop, input_decoder_3 jb push_flag_mode, input_decoder_3 jmp stage_3_loop // END OF MAIN
5. Project Implementation/Operation and Assessment The remainder of assembly code for the audio player is optimized for speed, at the
huge expense of readability and space. The remainder of the source code is included in
appendices B through K. I will outline what happens in the microcontroller’s software.
5.2.3 Initialization In this step, the c8051f020 is initialized to function properly for the audio player.
The external memory interface, DAC, port pins, etc. are all configured for the audio player to operate. Next the LCD and SDHC card are driven on, and the SDHC is sent into transfer mode. The final step is retrieval of playlist names from the SDHC card.
5.2.4 Stage 1 In stage one, the playlists are displayed on the LCD and the user navigates through
the playlists. Navigation button reading and sprite movement are handled in a timer
interrupt to handle button de-bouncing and to preserve readability of the main loop. Stage one is only exited when the user selects a playlist.
5.2.5 Stage 2 In stage two, the songs in a playlist are displayed on the LCD and the user navigates
through the songs. Button reading and sprite movement are handled the same as in stage
one. Stage two can be exited when the user selects a song, or when the user returns to the playlist menu by pressing the menu button.
5.2.6 Stage 3 In stage three, the header (and footer in the case of .wav files) of the audio file is
decoded to retrieve song tags, song length, and all other parameters necessary for decoding of the audio file (sampling rate, sample size in bits, etc.). The song tags artist, title, and 28
5. Project Implementation/Operation and Assessment album are displayed on the LCD screen. A bar is displayed at the bottom of the screen as well as the current play position into the song in minutes and seconds.
When the song is ready to be decoded, the SDHC card resumes read multiple blocks
mode and it will transmit data to the microcontroller whenever the clock line is toggled (high to low) until a stop transmit command is issued to it. At the end of each sampling period a sample is decoded from the audio file and sent to the DAC in a timer interrupt.
Periodically, another interrupt will occur to update the song time position and sample the
buttons. In the main loop, only the button flags set inside the interrupt service routine are sampled.
5.2.7 SD Driver The state diagram shown in figure 17 is followed to initialize the SDHC. The
complete method for initializing an SDHC card can be found in the SDHC simplified
specifications. The state diagram in figure 18 is followed to place the SDHC card in data
transfer mode. Once in data transfer mode, the SDHC card can be issued a read single block command (command 17) to read 512 bytes. Alternatively it can be issued a read multiple
block command (command 18) to read data until a stop transmission command (command 12) is issued.
29
5. Project Implementation/Operation and Assessment
Figure 17 SDHC Initialization State Diagram (from the SD Simplified Specifications)
30
5. Project Implementation/Operation and Assessment
Figure 18 SDHC Data Transfer Mode
5.2.8 .WAV Decoder The wav decoder uses a CMD17 to read the first 512 bytes of the wav file to gather
the number of samples, and sampling frequency of the audio file to determine the length, in time, of the wav file. The size of the wav file is gathered so that the end of the wav file may next be read for the gathering of audio tags to display on the LCD. After the header and
footer of the wav file have been decoded, the first sample is read and sent to DAC0. Timer 2’s interrupt is used for reading the remaining samples at the sampling frequency and
31
5. Project Implementation/Operation and Assessment sending them to DAC0 one sample per sampling frequency period. DAC0 is updated at the overflow of timer 2.
The progress in time of the song is tracked by timer 0’s interrupt for updating of the
time on the LCD, and movement of the song progress bar. The end of the song is triggered by PCAO (programmable counter array 0) which counts the number of times that timer 0 overflows.
5.2.9 .FLAC Decoder Decoding, the time progress of the song, and the end of the song are handled by
the .flac decoder the same way they are in the .wav decoder. However, in decoding .flac, audio samples are divided into frames. Therefore there is some added overhead in
decoding each frame’s header. In decoding a frame’s header, some critical parameters
which must be observed are the frame type (i.e. fixed, constant, verbatim), predictor order, frame size, rice partition order, rice parameter, etc. After the decoding of a single rice partition, the rice parameter of the next rice partition (if there is more than one in the
subframe) must be read, and so on, until the end of the subframe has been reached. For a single channel audio file there is only one subframe per frame.
5.2.10 Header Files In an attempt to preserve my sanity, and for added ease of development, all the
assembly code for my c8051f020 was divided into header files. The header files have
names that are categories for the modules of my project so that the code for performing a certain function can be easily be found (by using control-f in the appropriate header file). While code was being developed, it was written in “new.asm”, where the main loop is 32
5. Project Implementation/Operation and Assessment located, for debugging purposes (the IDE doesn’t have debug features for header files).
Variable names and address names were stored in an include file, “var_const.inc”, while
“c8051f020.inc” was provided by silicon labs for using all of the c8051f020’s sfr’s (special function registers).
5.3 Summary of the Final Design Results The final design has been evaluated by listening to the quality of the music, and by
the use of test code. I have played 44.1 kHz sample rate, 16-bit uncompressed .wav files on my audio player, and I assert that if the .flac audio files could be played with the same
degree of audio quality I would continue developing this audio player for personal use. The .flac audio files I am using for demonstration have had their sampling rate
reduced to 12 kHz, and LPC encoding was disabled. I have concluded that 32nd order LPC
decoding for complete .flac codec can not be implemented on a CIP-51 core microcontroller in any way, shape, or form. 16-bit sample, 4th – 6th order LPC decoding may be possible
using higher clock frequencies, but higher order LPC decoding would most likely be too
strenuous for the CIP-51 core microcontroller under any circumstance, and .flac supports up to 32nd order LPC encoding.
Complete LPC decoding is not even the deciding factor of whether I think my
product is adequate for personal use, however. The important factor is audio quality, and there is no sense in using a lossless audio format if I must lose audio quality by reducing the sampling frequency.
I believe that a similar system to the one I have now could be implemented
successfully (and be good enough for personal use) on a C-51 core with an operating
frequency of at least 40 kHz. The C-51 has 50% or higher instruction execution speed than
33
5. Project Implementation/Operation and Assessment the CIP-51 for many instructions, and has some multiplication speed optimization. The c8051f020 has a maximum speed of 25 MHz. Combined with the slower instruction
execution times of its core CIP-51 core, I believe the c8051f020 was an inappropriate choice for the implementation of my design.
The best alternative solution for the successful implementation of my design would
be on a 32-bit microprocessor with a DSP instruction set for decreased multiplicate and
accumulate operation execution speeds. Complete .flac codec, as well as other complete audio codecs could be implemented on such a microprocessor.
5.4 Performance Verification
The system was verified to work correctly by writing transmitted SDHC data (in the
initial stages of development), and decoded audio frames to the c8051f020’s 4 kilobytes of external RAM. I also used a few bytes of RAM to keep track of the audio frame currently
being decoded so I could make reference to the data in the original .flac file, and compare data in the .flac frontend’s analysis output files for the .flac file being decoded. As a
consequence, it is possible that the system may not be optimized, as the overhead added by providing a testing, troubleshooting, and debugging interface to me, affected the speed of the system. Additionally, using “test code” devalidates the test results after the test code has been removed. I think this was a necessary process though, for validating correct
operation of the system, and, more importantly, for debugging the system. In the future I hope to employ more methodical methods of verifying and debugging my system if
necessary, and using less intrusive test code, or none at all. Debugging such a complex system on such numerous occasions, was an edifying experience nonetheless. 34
5. Project Implementation/Operation and Assessment 5.5 Performance Evaluation After I verified correct performance of my system to an adequate extent, I used
some more test code for the purpose of observing how often decoding was not successfully completed during a period of the sampling frequency. I observed that when the audio’s
sampling frequency was reduced to 12 kHz (far below the 44 kHz I hoped to implement), minimal overflow of instruction execution occurred. The frequency of occurrences of a
decoding operation taking longer than a sampling frequency period had been reduced to being negligible (roughly one occurrence per 7,000 samples- or one occurrence per 6
frames- due to the overhead of decoding frame headers). This was after reducing the
sampling frequency of the .flac files, and removing all other testing code. A good system, of course, should have no occurrences.
Unfortunately, the time constraints, and the complexity of encoding the audio files at
a higher sampling frequency, creating a new playlist, etc. prevented me from trying similar tests with higher quality audio (at a higher sampling frequency). However, if I had been more conscientious in my testing approach, or if I had been more direct in my design approach, I would have had time to optimize my system further.
35
6. Final Scope of Work Statement 6.1 Summary of What Has Been Done I’ve done extensive research and testing to observe and verify the properties of
SDHC flash drives in operation, the properties of FAT32 formatted hard drives, the format
of .wav files, and the format of .flac files. I wrote codec for .flac and .wav decoding, an SDHC card driver, and a user interface all on a CIP-51 core c8051f020 microcontroller. I also wrote some playlist management software for a windows based PC.
6.2 Summary of What Still Needs to Be Done I still need to develop a .flac audio player good enough for personal use. The CIP-51
was not capable of as much as I thought it was. My current plan is to develop .flac codec on a 32-bit DSC (digital signal controller) ARM Cortex M4 core Freescale Kwikstik K-40
development board. It has a built in SD (hopefully SDHC) card driver and LCD segment driver.
A more convenient and complete playlist management program needs to be
developed. My current plan is to develop the playlist management program on a less restricted Linux system.
6.3 Lessons Learned and Suggestions for Future Activities Initially I didn’t question the capacity of my 8-bit microcontroller. I didn’t research
audio decoding to estimate whether compressed audio decoding would be possible with an 8-bit microcontroller or not. Fortunately, more time was spent in becoming familiar with
specifications and standards, and in developing a design approach, than in writing code for the c8051f020. 36
6. Final Scope of Work Statement Another lesson learned was in testing and debugging. I feel that the methods I used
for testing and debugging my project were what allowed me to continually make progress
on my project. I’ve thought about improved methods I could use for testing and debugging, which I hope to explore in the future.
I feel like one of the most important lessons I learned was the complexity of writing
drivers, and the complexity of writing code to make something meet standards and
specifications. I feel like I need to take a step back in future design projects and focus on meeting the standards and specifications so that my design can be compatible as a
universal driver, codec, or whatever, instead of my design merely working for a few test
cases. Coding the SDHC driver and .flac codec was a big eye opener, and made me realize too much of implementing my design was focused on getting instant results, instead of creating a permanent solution by carefully observing the standard.
37
7. Other 7.1 Material and Component Suppliers Most of my components were available on-hand. I purchased some from the USU
ECE store, and from Newark. I have found replacement parts online from AVNet.
7.2 Impacts of my Solution in a Global, Economic, and Societal Context Flac provides quality audio with reasonable compression. My design provides
quality, flexibility and versatility to the user. A key focus of my design was user
convenience. The batteries are not custom-made. The memory card can be removed and
used for general purpose storage.
My product is primarily for personal use, and with the knowledge I have gained over
the course of my project, I can make a product fit for personal use. The societal impact of
my project is that I can publish the knowledge I’ve gained about .flac decoding, online and share my experiences with other developers.
More so than my project, I am a marketable product. I believe that any design
experience I gain while in school will have a global impact when I get a job as an engineer in industry.
38
8. Cost Estimation 8.1 Estimate of System Cost In table 1 is an estimate of the system cost of my project. Estimates were made for
industrial costs of PCB (printed circuit board) manufacturing, and commercial costs of components.
Part Number C8051f020 S64128N
34063
1N5819
Description Cost Microcontro 23.00 ller Push Button .85 Displaytech LCD 65K Resistors Power Supply IC Diode 100uF Capacitors 43k Resistor
20.22
240 uH Inductor .5 ohm Resistor 222 uF Capacitor Headphone Jack Audio Amp
1.20
.05 .23 .15 .05 .05
61k Resistor .05
BC140W04LF TDA 7052
39
330k Resistor 1.5k Resistor 60 pF Capacitor
.02 .05
1.00 2.25 .05 .05 .20
Quantity 1
Total 23.00
1
20.22
8 5 1 1 4 1 1 1 1 1 1 1 1 1 1
6.80 .25 .23 .15 .20 .05
Distributor AVNet USU ECE Store Mouser USU ECE Store AVNet AVNet AVNet
1.20
USU ECE Store USU ECE Store AVNet
.05
AVNet
.05 .02
1.00 2.25 .05 .05 .20
AVNet AVNet
USU ECE Store USU ECE Store USU ECE Store USU ECE Store
8. Cost Estimation 4xAA Battery Holder PCB Board Total
11.5892 MHz Osc.
4.15
1
4.15
3.50
1
3.50
.57
1
Newark
.57
Table 1 Estimate of System Cost
Newark
64.04
8.2 Estimate of Development Cost In table 2 is an estimate of the development cost of my project. Almost all
components for the prototype were on-hand, but I have included replacement part costs to give an idea for the replacement value of the prototype. Part Number
Description
C8051f020DK
Training Board Push Button
S64128N
34063
1N5819
Displaytech LCD 65K Resistors Power Supply IC Diode 100uF Capacitors 43k Resistor
Cost from Budget On-Hand On-Hand
40
.85
On- Hand 20.22 .25
.05
On-Hand On-Hand
.15 .05
On-Hand
.05
61k Resistor .05 240 uH Inductor .5 ohm Resistor 222 uF
Replace ment Cost 81.03
On-Hand On-Hand On-Hand
.23
.05 .05
1.20 .02 .05
Quantity
Total
Distributor
1
81.03
AVNet
1
20.22
8 5 1 1 4 1 1 1 1 1
6.80 .25 .23 .15 .20 .05
USU ECE Store Mouser USU ECE Store AVNet AVNet AVNet
1.20
USU ECE Store USU ECE Store AVNet
.05
AVNet
.05 .02
AVNet
8. Cost Estimation BC140W04LF TDA 7052
Total
41
Capacitor Headphone Jack Audio Amp
330k Resistor 1.5k Resistor 60 pF Capacitor Female Header Pins Wire Wrap Wire Wrap Sockets 10-pin Ribbon Cable 11.5892 MHz Oscillator Student Man Hours 4xAA Battery Holder
On-Hand
1.00
1
1.00
On-Hand
.05
1
.05
On-Hand On-Hand .20 .10 .80
1.25
On-Hand
2.25 .05 .20 .10 .10
1.25 2.20
1 1 1
56 8 3 5
2.25 .05 .20
5.60 .80
3.75
10.10
.57
.57
1
.57
On-Hand
.10
300
30
On-Hand 3.27
4.15
1
Table 2 Estimate of Development Cost
4.15 167.29
AVNet
USU ECE Store USU ECE Store USU ECE Store USU ECE Store USU ECE Store USU ECE Store USU ECE Store USU ECE Store Newark Tyler Cardon Newark
9. Project Management Summary 9.1 Time: GANTT Chart Figure 19 shows a GANTT chart showing the dates of completion of tasks for my project. All tasks were completed by me between December 2010 and May 2011.
Figure 19 GANTT Chart
42
10. Conclusion 10 Conclusion I have reviewed the history of my project, and I hope to continue developing it to meet higher standards. The conceptual design was something I thought I had spent enough time on, but the technical issues involved became more clear as I implemented my system, and my idea of an appropriate solution to the design problem changed with experience. I had some development ideas, and plans for expansion when I began this project such as developing an SD card data bus driver in hardware, and allowing my project room to expand it for handling video. These ideas faded away over the course of the project, and I had to modify my overall design to meet simpler criteria. My project is functional, but not a lot of room is left for expansion or improvement.
43
Appendix A Playlist Manager (x86 assembly) ;;;;;;;;;;;;;;;;;; format PE Console ;include 'win32a.inc' include 'macro/import32.inc' include 'win32ax.inc' ;include 'macro/masm.inc' ;include 'macro/proc32.inc' entry main section '.bss' readable writable fhandler dd ? fhandlew dd ? addr16 dd ? addr32 dd ? addr_offset dd ? current_line dd ? cluster_size dd ? garbage dd ? ;;;;;;;;;;;;;;;;;;;;;;;;;;;; crc7 variables: addr dd ? ret_crc7 dd ? arg_crc7 dd ? a_size dd ? ;;;;;;;;;;;;;;;;;;;;;;;;;;;; name retrieval variables is_lfn dd ? name_1 dd ? name_2 dd ? ext dd ? num_lines dd ? first_line dd ? att dd ? count dd ? flag_first dd ? section '.data' data readable writable fnamer db 'all.dat', 0 fnamew db 'temp.x',0 fnamew1 db 'all.pla',0 success_msg db 'file was opened successfully',0 p db "pause>nul",0 SEEK_SET dd 0 cmd17 dw 51h cmd18 dw 52h ext_wav dd 574156h ext_flac dd 464C41h section '.text' code readable executable ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44
Appendix A Playlist Manager (x86 assembly) proc get_address push ebp mov ebp, esp sub esp, 4 xor ebx, ebx invoke fgetc, [fhandler] add ebx, eax invoke fgetc, [fhandler] shl eax, 8 add ebx, eax mov [addr16], ebx mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc next_line push ebp mov ebp, esp sub esp, 16 ;;;;;;;;;;;;;;;; ;invoke putchar, 0x31 ;;;;;;;;;;;;;;;; mov eax, [current_line] shl eax, 5 invoke fseek,[fhandler], eax, [SEEK_SET] inc [current_line] mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc prev_line push ebp mov ebp, esp sub esp, 16 ;;;;;;;;;;;;;;;; ;invoke putchar, 0x30 ;;;;;;;;;;;;;;;; dec [current_line]
45
Appendix A Playlist Manager (x86 assembly) mov eax, [current_line] shl eax, 5 invoke fseek,[fhandler], eax, [SEEK_SET] mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc copy_file push ebp mov ebp, esp sub esp, 16 mov eax, [count] and eax, 0x0FF00 invoke fputc, eax, [fhandlew] mov eax, [count] and eax, 0x0FF invoke fputc, eax, [fhandlew] invoke fputc, 0x41, [fhandlew] invoke fputc, 0x6c, [fhandlew] invoke fputc, 0x6c, [fhandlew] invoke fputc, 0x2F, [fhandlew] mov [flag_first], 0 loopy_saeggi: invoke fgetc, [fhandler] cmp eax, '/' jne loopy_soon_saeggi mov ebx, [flag_first] cmp ebx, 1 je end_saeggi inc [flag_first] jmp loopy_soon_saeggi2 loopy_soon_saeggi: mov [flag_first], 0 loopy_soon_saeggi2: invoke fputc, eax, [fhandlew] jmp loopy_saeggi end_saeggi: invoke fputc, eax, [fhandlew] invoke fclose, [fhandlew] invoke fclose, [fhandler] fin_saeggi: mov esp, ebp pop ebp
46
Appendix A Playlist Manager (x86 assembly) ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; main: push ebp mov ebp,esp sub esp, 40
; save ebp ; store esp in ebp
mov [current_line], 1 mov [is_lfn], 0 ;; open readable file invoke fopen, fnamer, 'r' cmp eax, 0 je err_open mov [fhandler], eax invoke fopen, fnamew, 'w' cmp eax, 0 je err_open mov [fhandlew], eax mov dword [esp], success_msg call [printf] invoke fgetc, [fhandler] mov [cluster_size], eax call get_address mov eax, [addr16] mov [addr_offset], eax mov [num_lines], 0 mov [is_lfn], 0 mov [count], 0 line_loop: call next_line invoke fgetc, [fhandler] cmp eax, 0e5h je line_loop cmp eax, 0 je exit_line_loop ; check for mp3 extension invoke ungetc, eax, [fhandler] call check_ext cmp eax, 0 je not_mp3_ext
47
Appendix A Playlist Manager (x86 assembly) ;; call write_out inc [count] mov [num_lines], 0 mov [is_lfn], 0 jmp line_loop not_mp3_ext: ;check for lfn and [att], 0ffh cmp [att], 0fh jne not_lfn ; If an mp3 or non-mp3 lfn line was read: mov edx, [name_1] and edx, 0xf0000000 cmp edx, 0x40000000 jne line_loop ; (Nested) if an end lfn line was read mov [is_lfn], 1 mov edx, [name_1] shr edx, 24 and edx, 0fh mov [num_lines], edx jmp line_loop ; Else a non-mp3 8-3 name was read: not_lfn: mov [is_lfn], 0 mov [num_lines], 0 jmp line_loop exit_line_loop: invoke fputc, 0x2F, [fhandlew] ;; close file invoke fclose, [fhandler] invoke fclose, [fhandlew] invoke fopen, fnamew, 'r' cmp eax, 0 je err_open mov [fhandler], eax invoke fopen, fnamew1, 'w' cmp eax, 0 je err_open mov [fhandlew], eax
48
Appendix A Playlist Manager (x86 assembly) ;; copy file adding name and count call copy_file err_open: mov dword [esp],p ;pause call [system] mov esp,ebp pop ebp ;restore stack frame mov eax,0 ;return value 0 ret ;return from main ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc conv_hex_char push ebp mov ebp, esp sub esp, 32 mov edx, ebx mov ecx, edx and ecx, 0F0H shr ecx, 4 cmp ecx, 0x9 jg char_1 add ecx, 0x30 jmp cont_conv char_1: add ecx, 0x37 cont_conv: mov [garbage], edx invoke putchar, ecx mov edx, [garbage] and edx, 0FH cmp edx, 9 jg char_2 add edx, 0x00000030 jmp fin_conv char_2: add edx, 0x00000037 fin_conv: invoke putchar, edx mov esp, ebp pop ebp ret endp
49
Appendix A Playlist Manager (x86 assembly) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc crc7 push ebp mov ebp, esp mov [a_size], 40 mov eax, dword [addr] mov edx, [arg_crc7] mov edi, dword [a_size] crc_loop: mov ecx, edx shl edx, 1 mov ebx, eax and ebx, 0x80000000 cmp ebx, 0x80000000 jne bit_32_0 add edx, 1 bit_32_0: and ecx, 80h cmp ecx, 80h jne bit7_0 ; if bit 7 is 1 mov ecx, edx and edx, 0edh not ecx and ecx, 12h add edx, ecx ; else bit 7 is 0 bit7_0: shl eax, 1 dec edi cmp edi, 0 jne crc_loop shr edx, 1 and edx, 7fh shl edx, 1 add edx, 1 ; add stop bit mov dword [ret_crc7], edx mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50
Appendix A Playlist Manager (x86 assembly) proc write_out push ebp mov ebp, esp ;sub esp, 16 sub esp, 20 mov edi, 15 ;;;;;;;;;;;;;;; invoke putchar, 0x0D invoke putchar, 0x0A mov ebx, [current_line] shr ebx, 8 call conv_hex_char mov ebx, [current_line] call conv_hex_char invoke putchar, 0x20 mov ebx, [num_lines] call conv_hex_char invoke putchar, 0x20 ;;;;;;;;;;;;; ;;;;;;;;;;;;;;; find_ra: invoke fgetc, [fhandler] ;;;;;;;;;;;;; mov ebx, eax call conv_hex_char mov eax, ebx ;;;;;;;;;;;;; dec edi cmp edi, 0 je found_ra jmp find_ra found_ra: ;;;;;;;;;;;;; mov ebx, eax invoke putchar, 0x20 call conv_hex_char mov eax, ebx ;;;;;;;;;;;;; mov edi, eax invoke fgetc, [fhandler] ;;;;;;;;;;;;; mov ebx, eax call conv_hex_char mov eax, ebx
51
Appendix A Playlist Manager (x86 assembly) ;;;;;;;;;;;;; shl eax, 8 add eax, edi sub eax, 2 mov edx, [cluster_size] mul edx add eax, [addr_offset] mov edi, eax mov eax, edi shr eax, 24 and eax, 0ffh ;;;;;;;;;;;;; mov ebx, eax invoke putchar, 0x20 call conv_hex_char mov eax, ebx ;;;;;;;;;;;;; invoke fputc, eax, [fhandlew] mov eax, edi shr eax, 16 and eax, 0ffh ;;;;;;;;;;;;; mov ebx, eax call conv_hex_char mov eax, ebx ;;;;;;;;;;;;; invoke fputc, eax, [fhandlew] mov eax, edi shr eax, 8 and eax, 0ffh ;;;;;;;;;;;;; mov ebx, eax call conv_hex_char mov eax, ebx ;;;;;;;;;;;;; invoke fputc, eax, [fhandlew] mov eax, edi and eax, 0ffh ;;;;;;;;;;;;; mov ebx, eax call conv_hex_char
52
Appendix A Playlist Manager (x86 assembly) mov eax, ebx ;;;;;;;;;;;;; invoke fputc, eax, [fhandlew] mov edx, dword [cmd17] mov [arg_crc7], edx mov [addr], edi call crc7 ;; address still in addr ;; write ret_crc7 to write file mov edx, [ret_crc7] invoke fputc, edx, [fhandlew] mov edx, dword [cmd18] mov [arg_crc7], edx call crc7 mov edx, [ret_crc7] invoke fputc, edx, [fhandlew] ; write out filename cmp [is_lfn], 0 jne lfn_file ; if file is 8-3 mov edi, 5 _8_3_loop: dec edi cmp edi, 0 je begin_loop2 mov edx, [name_1] cmp edi, 1 je no_name_shift shr edx, 8 cmp edi, 2 je no_name_shift shr edx, 8 cmp edi, 3 je no_name_shift shr edx, 8 jmp no_name_shift_a no_name_shift: and edx, 0ffh cmp edx, 20h je fin_name push edx invoke isalpha, edx pop edx cmp eax, 0 je no_name_shift_a
53
Appendix A Playlist Manager (x86 assembly) add edx, 20h no_name_shift_a: invoke fputc, edx, [fhandlew] jmp _8_3_loop begin_loop2: mov edi, 5 loop2: dec edi cmp edi, 0 je fin_name mov edx, [name_2] cmp edi, 1 je no_name_shift2 shr edx, 8 cmp edi, 2 je no_name_shift2 shr edx, 8 cmp edi, 3 je no_name_shift2 shr edx, 8 no_name_shift2: and edx, 0ffh cmp edx, 20h je fin_name push edx invoke isalpha, edx pop edx cmp eax, 0 je no_name_shift_a2 add edx, 20h no_name_shift_a2: invoke fputc, edx, [fhandlew] jmp loop2 lfn_file: call get_lfn fin_name: invoke fputc, 2fh, [fhandlew] mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc write_lfn
54
Appendix A Playlist Manager (x86 assembly) push ebp mov ebp, esp mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc check_ext ;leaves stream at location 12 of line ;returns 1 in eax if extension is mp3 else returns 0 ;returns 8-3 filename, attribute = {name1,name2,ext,att} ;destroys eax,ebx,ecx,edx ;depends on file stream in [fhandler] ;requires include: fgetc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push ebp mov ebp, esp sub esp, 4 xor ebx, ebx xor ecx, ecx xor edx, edx invoke fgetc, [fhandler] shl eax, 24 mov [name_1], eax invoke fgetc, [fhandler] shl eax, 16 add [name_1], eax invoke fgetc, [fhandler] shl eax, 8 add [name_1], eax invoke fgetc, [fhandler] add [name_1], eax invoke fgetc, [fhandler] shl eax, 24 mov [name_2], eax invoke fgetc, [fhandler] shl eax, 16 add [name_2], eax invoke fgetc, [fhandler] shl eax, 8 add [name_2], eax invoke fgetc, [fhandler] add [name_2], eax invoke fgetc, [fhandler] shl eax, 16
55
Appendix A Playlist Manager (x86 assembly) mov [ext], eax invoke fgetc, [fhandler] shl eax, 8 or [ext], eax invoke fgetc, [fhandler] or [ext], eax invoke fgetc, [fhandler] mov [att], eax xor eax, eax mov edi, [ext] cmp edi, [ext_wav] jne cmp_next mov eax, 1 jmp fin_ext cmp_next: cmp edi, [ext_flac] jne fin_ext mov eax, 1 fin_ext: mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; proc get_lfn push ebp mov ebp, esp sub esp, 12 call prev_line mov edi, 0 lfn_loop: inc edi call prev_line invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler]
56
Appendix A Playlist Manager (x86 assembly) cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] invoke fgetc, [fhandler] invoke fgetc, [fhandler] invoke fgetc, [fhandler] ;invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn
57
Appendix A Playlist Manager (x86 assembly) invoke fputc, eax, [fhandlew] invoke fgetc, [fhandler] invoke fgetc, [fhandler] cmp eax, 2eh je fin_lfn invoke fputc, eax, [fhandlew] cmp edi, [num_lines] jl lfn_loop fin_lfn: add edi, 1 forward_loop: cmp edi, 0 je fin_call call next_line dec edi jmp forward_loop fin_call: mov esp, ebp pop ebp ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; section '.idata' import data readable library msvcrt,'msvcrt.dll' import msvcrt,\ fread,'fread',\ fopen,'fopen',\ fclose,'fclose',\ printf,'printf',\ gets,'gets',\ fgetc,'fgetc',\ system,'system',\ putchar,'putchar',\ ferror,'ferror',\ fseek,'fseek',\ fputc,'fputc',\ isgraph,'isgraph',\ ungetc,'ungetc',\ fputs,'fputs',\ isalpha,'isalpha',\ isint,'isint',\ exit,'exit'
58
Appendix B new.asm (8051 8-bit assembly) $include (c8051f020.inc) $include (var_const.inc)
ORG 0 reset: anl p4, #11111011B jmp mairn ORG 0BH jb write_indef, fasty_saeggi clr tr0 jmp normal_t0 fasty_saeggi: jmp new_isr0 ORG 1BH jb write_indef, fasty_saeggi_luger jmp T1_ISR fin_ISV1: reti fasty_saeggi_luger: jmp new_ISR1 ORG 2BH jmp isr2 ORG 4BH clr tr0 jb write_indef, fasty_luger call PCA0_ISR reti fasty_luger: jmp new_PCA0_ISR ORG 0B3H mairn: mov r0, #7FH clr_all: mov @r0, a djnz r0, clr_all call _8051_INITIALIZATION call _LCD_INITIALIZATION call _SDHC_INITIALIZATION call _SDHC_TRANSFER_READY call _XRAM_PLAYLIST_INITIALIZATION STAGE_1:
59
Appendix B new.asm (8051 8-bit assembly) call _INITIALIZE_STAGE_1 call _Display_Menu STAGE_1_loop: jnb push_flag_play,STAGE_1_loop call get_pl_addresses STAGE_2: call _INITIALIZE_STAGE_2 call _Display_Menu jmp stage_2_loop STAGE_2_loop: jnb push_flag_menu,cont_st_2_loop jmp stage_1 cont_st_2_loop: jnb push_flag_play,STAGE_2_loop STAGE_3: call _INITIALIZE_STAGE_3 call _PLAY_SONG jnb push_flag_stop, stage_3_loop clr tr2 clr tr0 STAGE_3_loop: jb push_flag_play, input_decoder_3 jb push_flag_menu, input_decoder_3 jb flag_finish_play, input_decoder_3 jb push_flag_left, input_decoder_3 jb push_flag_right, input_decoder_3 jb push_flag_stop, input_decoder_3 jb push_flag_mode, input_decoder_3 jmp stage_3_loop input_decoder_3: clr tr2 clr tr0 jmp input_decode_3 main_pm: mov r0, #current_pl_32 mov r1, #addr_1 mov r2, #4 loopy_money: mov a, @r0 mov @r1, a inc r1
60
Appendix B new.asm (8051 8-bit assembly) inc r0 djnz r2, loopy_money jmp stage_2 // END OF MAIN change_mode: sjmp stage_3_loop //////////////////////////////////////////////// ////////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// $include (isr_r.h) $include (SDHC_r.h) $include (MP3_r.h) $include (luts.h) $include (LCD_r.h) $include (GUI_r.h) $include (math_r.h) $include (wav_r.h) $include (flac_r.h) $include (lpc_r.h) end
61
Appendix C GUI_r.h /////////////////////////////// Last Modified May 4 ////////////////////// /////////////////////////////// March 26 size: 499 bytes /////////////////////// #ifndef GUI_r #define GUI_r ORG 11000H ///////////////////////////// display flac tags display_flac_tags: mov addr_1, current_song_32 mov addr_2, current_song_2 mov addr_3, current_song_3 mov addr_4, current_song_LSB mov 30H, #52H call CRC7 mov t0_mode, #find_seq_18 call send_cmd18 clr tr0 mov 30H, #'r' mov 31H, #'e' mov 32H, #'f' mov 33H, #'e' mov 1CH, #4 setb tr0 jnb flag_sequence_found, $ clr tr0 clr flag_sequence_found clr f0 setb tr0 jnb f0, $ clr tr0 clr f0 mov 30H, #0FFH mov 31H, #0F8H mov 1CH, #2 setb tr0 jnb f0, $ clr f0 jnb f0, $ clr tr0 mov a, sequence_addr_16_LSB add a, #40 mov r0, a mov a, sequence_addr_16
62
Appendix C GUI_r.h addc a, #0 cjne a, #10H, fun mov a, #0 fun: mov emi0cn, a furm: inc r0 call check_emi0cn movx a, @r0 cjne a, #'B', fuz1 jmp z1 fuz1: cjne a, #'b', furm z1: inc r0 call check_emi0cn movx a, @r0 cjne a, #'U', fuz2 jmp z2 fuz2: cjne a, #'u', furm z2: inc r0 call check_emi0cn movx a, @r0 cjne a, #'M', fuz3 jmp z3 fuz3: cjne a, #'m', furm z3: inc r0 call check_emi0cn movx a, @r0 cjne a, #'=', furm inc r0 call check_emi0cn mov temp3, #album_tag call display_tag fury: inc r0 call check_emi0cn movx a, @r0 cjne a, #'I', fuz4 jmp z4 fuz4: cjne a, #'i', fury
63
Appendix C GUI_r.h z4: inc r0 call check_emi0cn movx a, @r0 cjne a, #'S', fuz5 jmp z5 fuz5: cjne a, #'s', fury z5: inc r0 call check_emi0cn movx a, @r0 cjne a, #'T', fuz6 jmp z6 fuz6: cjne a, #'t', fury z6: inc r0 call check_emi0cn movx a, @r0 cjne a, #'=', fury inc r0 call check_emi0cn mov temp3, #artist_tag call display_tag furz: inc r0 call check_emi0cn movx a, @r0 cjne a, #'T', fuza jmp z7 fuza: cjne a, #'t', furz z7: inc r0 call check_emi0cn movx a, @r0 cjne a, #'L', fuzb jmp z8 fuzb: cjne a, #'l', furz z8: inc r0 call check_emi0cn movx a, @r0 cjne a, #'E', fuzc jmp z9
64
Appendix C GUI_r.h fuzc: cjne a, #'e', furz z9: inc r0 call check_emi0cn movx a, @r0 cjne a, #'=', furz inc r0 call check_emi0cn mov temp3, #name_tag call display_tag ret ///////////////////////////////// clear body ///////////////////////////// clear_body: mov r7, #0B5H pagey_saeggi: mov a, r7 call wcom_a mov a, #0 call wcom_a mov a, #10H call wcom_a mov r2, #128 clear_saeggi: call wdat_0 djnz r2, clear_saeggi dec r7 cjne r7, #0AFH, pagey_saeggi ret //////////////////////////////// clear header ///////////////////////// clear_header: mov a, #0B7H call wcom_a mov a, #0 call wcom_a mov a, #10H call wcom_a mov r2, #128 mov r3, #0 mov r4, #2 loop_clear_header: mov a, r3
65
Appendix C GUI_r.h call wdat_a djnz r2, loop_clear_header mov a, #0B6H call wcom_a mov a, #0 call wcom_a mov a, #10H call wcom_a mov r2, #128 mov r3, #2 djnz r4, loop_clear_header ret ////////////////////////////////////// display body text ////////////////// _LCD_DISPLAY_BODY_TEXT: /* // start at page 2, column 14 // retrieve ascii letter, cmp against '/' // calculate location in LUT // load location in DPTR call clear_body mov r7, #0B5H inc r7 mov temp1, #0 mov r0, #-1 mov count2, #6 string_loop_body: inc r0 mov emi0cn, temp1 movx a, @r0 cjne a, #'/', cont_body1 clr c mov a, #5 subb a, count2 ret cont_body1: mov a, r0 add a, #LOCATION_next_string mov r0, a dec r0 page_loop_body: dec r7 cjne r7, #0AFH, cont1_body ret cont1_body: mov a, r7
66
Appendix C GUI_r.h call wcom_a mov a, #0EH call wcom_a mov a, #10H call wcom_a mov r3, #16 char_loop_body: inc r0 call check_emi0cn mov emi0cn, temp1 movx a, @r0 cjne a, #'/', cont_body jmp string_loop_body cont_body: clr c subb a, #32 mov dptr, #font5x8 mov b, #5 mul ab add a, dpl xch a, b addc a, dph mov dph, a mov dpl, b mov r2, #5 byte_loop_body: call wdat_c inc dptr djnz r2, byte_loop_body clr a call wdat_a djnz r3, char_loop_body loop_saeggi: inc r0 cjne r0, #0, no_incy_saeggi inc temp1 no_incy_saeggi: mov emi0cn, temp1 movx a, @r0 cjne a, #'/', loop_saeggi djnz count2, string_loop_body mov a, #5*/ ret
//////////////////////////////// display header /////////////////////////// _LCD_DISPLAY_HEADER:
67
Appendix C GUI_r.h ;mov dptr, #HEADER_all_playlists_single ;call refresh_header ret /////////////////////////////////// display sprite ////////////////////// _LCD_DISPLAY_SPRITE: /* clr c mov r3, _sprite_pos mov r4, #0B5H page_loop_sprite: cjne r4, #0AFH, cont_sprite ret cont_sprite: mov a, r4 call wcom_a mov a, #0 call wcom_a mov a, #10H call wcom_a mov r2, #3 cjne r3, #0, byte_loop_clear mov dptr, #SPRITE_pointer byte_loop_sprite: call wdat_c inc dptr djnz r2, byte_loop_sprite fin_loop_sprite: dec r3 dec r4 jmp page_loop_sprite byte_loop_clear: clr a call wdat_a djnz r2, byte_loop_clear jmp fin_loop_sprite */ ret ///////////////////////// MENU NAVIGATION _MENU_NAVIGATION: _ALL_PLAYLIST: /* mov push_flags, #0 mov _playlist_pos, #0
68
Appendix C GUI_r.h mov _sprite_pos, #0 mov _sprite_pos_max, #1 call _LCD_DISPLAY_HEADER call _LCD_DISPLAY_BODY_TEXT call _LCD_DISPLAY_SPRITE mov _shift_B1, B1 mov _shift_B2, B2 orl ie, #00001000B setb tr1 jnb push_flag_play, $ clr tr1 // Display playlist mov push_flags, #0 mov _playlist_pos, #0 call _LCD_PLAYLIST_HEADER call _LCD_BODY_TEXT_GET mov _sprite_pos, #0 mov _sprite_pos_max, a call _LCD_DISPLAY_SPRITE mov _shift_B1, B1 mov _shift_B2, B2 orl ie, #00001000B setb tr1 jnb push_flag_play, $ clr tr1 */ ret /////////////////////////// Playlist Header ///////////////////////// _LCD_PLAYLIST_HEADER: sjmp $ /////////////////////////////// refresh header ///////////////////////// refresh_header: ; mov dptr,#0 mov r2,#0B7H page_loop_head: mov a,r2 call wcom_a mov a,#0 call wcom_a mov a,#10H call wcom_a mov r3,#128
69
; start of 1k block of memory ; command to set page number to 0 ; set page number n, n = 0, 1, 2...7 ; set column number to 4. If LCD is not ; inverted, you will want to set column ; number to 0. ; copy 128 bytes
Appendix C GUI_r.h byte_loop_head: ;clr a ;movc a, @a+dptr ;call reorder_lookup call wdat_c ; and write it to the LCD inc dptr djnz r3,byte_loop_head dec r2 ; advance to next page, but bail if it is 8 (B8) cjne r2,#0B5H,page_loop_head ret ///////////////////////////// Initialize stage 2 //////////// _Initialize_STAGE_2: mov r0, #current_pl_32 mov r1, #addr_1 mov r2, #4 loopy_thingy: mov a, @r1 mov @r0, a inc r1 inc r0 djnz r2, loopy_thingy // get # songs //mov 30H, #51H mov 30H, #52H call CRC7 //mov t0_mode, #read_block_17 //call send_cmd17 mov t0_mode, #find_seq_18 call send_cmd18 clr tr0 mov 1CH, #2 mov 30H, #'/' mov 31H, #'/' setb tr0 jnb flag_sequence_found, $ clr tr0 call send_cmd12 mov emi0cn, #ixram mov r0, #0 ;movx a, @r0 ;mov sprite_pos_max_16, a inc r0 movx a, @r0 ;clr c ;subb a, #1 mov county_saeggy, a
70
Appendix C GUI_r.h ;mov a, sprite_pos_max_16 ;subb a, #0 ;mov sprite_pos_max_16, a call display_header mov sprite_pos_16, #0 mov sprite_pos_LSB, #0 ret ///////////////////////////////////////////////
//////////////////////////// initialize display for new song /////// display_new_song: call clear_body call clear_header mov a, #0B4H call wcom_a mov a, #10H call wcom_a mov a, #0H call wcom_a mov dptr, #body_artist loop_artist: clr a movc a,@a+dptr cjne a, #0FFH, con_line_artist jmp next_line_new con_line_artist: call reorder_lookup call wdat_a inc dptr jmp loop_artist next_line_new: mov a, #10H call wcom_a mov a, #0H call wcom_a mov a, #0B3H call wcom_a mov dptr, #body_album loop_album: clr a movc a,@a+dptr cjne a, #0FFH, con_line_album jmp next2_line_new
71
Appendix C GUI_r.h con_line_album: call reorder_lookup call wdat_a inc dptr jmp loop_album next2_line_new: mov a, #0B0H call wcom_a mov a, #0 call wcom_a mov a, #10H call wcom_a mov r2, #128 mov dptr, #body_slider_line loop_slider_line: call wdat_c inc dptr djnz r2, loop_slider_line ret
/////////////////////////// Display Riff Tags ///////////////////// display_riff_tags: mov 30H, #52H call CRC7 mov t0_mode, #find_seq_18 call send_cmd18 clr tr0 clr cr mov 30H, #'L' mov 31H, #'I' mov 32H, #'S' mov 33H, #'T' mov 1CH, #4 setb cr setb tr0 sharmu: jb flag_dat_fail, display_riff_tags jnb flag_sequence_found, sharmu clr tr0 mov t0_mode, #read_block_17
72
Appendix C GUI_r.h mov PCA0CPH0, #HIGH(One_Block) mov PCA0CPL0, #LOW(One_Block) mov PCA0CPM0, #49H mov PCA0H, #0 mov PCA0L, #0 mov pca0cn, #40H setb cr setb tr0 jnb flag_dat_received, $ call send_cmd12 clr tr0 clr cr mov a, sequence_addr_16_LSB add a, #4 mov r0, a mov a, sequence_addr_16 addc a, #0 mov emi0cn, a mov r1, #chunk_size_LSB mov r2, #4 loopy_looker: movx a, @r0 mov @r1, a inc r0 mov a, r0 jnz not_zes mov a, emi0cn cjne a, #10H, not_tensys mov emi0cn, #0 jmp not_zes not_tensys: inc emi0cn not_zes: dec r1 dec chunk_size_LSB djnz r2, loopy_looker // r0 pointing at first tag mov a, r0 add a, #4 mov r0, a mov a, emi0cn addc a, #0 mov emi0cn, a mov a, chunk_size_LSB clr c subb a, #4
73
Appendix C GUI_r.h mov chunk_size_LSB, a tag_loop: mov temp0, r0 mov temp2, emi0cn movx a, @r0 cjne a, #'I', next_tag inc r0 call check_emi0cn movx a, @r0 cjne a, #'A', not_artist inc r0 call check_emi0cn movx a, @r0 cjne a, #'R', next_tag inc r0 call check_emi0cn movx a, @r0 cjne a, #'T', next_tag inc r0 call check_emi0cn mov temp3, #artist_tag call display_tag jmp next_tag not_artist: cjne a, #'N', not_name inc r0 call check_emi0cn movx a, @r0 cjne a, #'A', not_name inc r0 call check_emi0cn movx a, @r0 cjne a, #'M', not_name inc r0 call check_emi0cn mov temp3, #name_tag call display_tag jmp next_tag not_name: cjne a, #'P', next_tag inc r0 call check_emi0cn movx a, @r0 cjne a, #'R', next_tag inc r0 call check_emi0cn movx a, @r0 cjne a, #'D', next_tag inc r0 call check_emi0cn
74
Appendix C GUI_r.h mov temp3, #album_tag call display_tag jmp next_tag //jmp next_tag next_tag: mov a, chunk_size_LSB clr c subb a, #8 jc fin_tag clr c subb a, temp2 mov chunk_size_LSB, a jc fin_tag jnz con_riff_tags fin_tag: ret con_riff_tags: mov a, temp0 add a, temp4 add a, #8 mov r0, a mov a, temp2 addc a, #0 mov emi0cn, a jmp tag_loop not_riff_tag: sjmp $ ret
////////////////////////////// display riff tag /////////////////// display_riff_tag: mov emi0cn, temp1 jmp nextys char_loop_body_riff_tag: inc r0 mov emi0cn, temp1 call check_emi0cn nextys: movx a, @r0 cont_body_riff_tag: clr c subb a, #32 jnc nextersys
75
Appendix C GUI_r.h ret nextersys: mov dptr, #font5x8 mov b, #5 mul ab add a, dpl xch a, b addc a, dph mov dph, a mov dpl, b mov r2, #5 byte_loop_body_riff_tag: call wdat_c inc dptr djnz r2, byte_loop_body_riff_tag ;;;;;;;;;;;; ;clr a ;call wdat_a ;;;;;;;;;;;; djnz r3, char_loop_body_riff_tag ret /////////////////////////// Playlist Header ///////////////////////// display_header: call clear_header mov column_l, #0EH mov a, column_l call wcom_a mov column_h, #10H mov a, column_h call wcom_a mov a, #0B7H call wcom_a mov temp1_16, #HIGH(font8_h) mov temp2_16, #LOW(font8_h) mov temp3_16, #HIGH(font8_offset_16) mov temp4_16, #LOW(font8_offset_16) mov count2, #2 mov temp3, #MAX_char_header mov r0, #2 //call get_pl_addresses mov backup2, #ixram loop_font8: mov emi0cn, backup2 movx a, @r0 cjne a, #'/', cont_di_playlist ret
76
Appendix C GUI_r.h cont_di_playlist: clr c ;mov a, temp1 subb a, #20H clr c rlc a add a, temp4_16 mov dpl, a clr a addc a, temp3_16 mov dph, a clr a movc a, @a+dptr mov offset_h, a mov a, #1 movc a, @a+dptr mov offset_l,a mov a, #2 movc a, @a+dptr mov r3, a mov a, #3 movc a, @a+dptr mov r3, a // add {temp2_16,temp1_16} + {offset_h,offset_l} mov a, offset_l add a, temp2_16 mov dpl, a mov a, offset_h addc a, temp1_16 mov dph, a // subtract {r3} - {offset_l} clr c mov a, r3 subb a, offset_l mov r2, a mov backup1, r2 char_loop_offset: call wdat_c inc dptr djnz r2, char_loop_offset mov temp1_16, #HIGH(font8_l) mov temp2_16, #LOW(font8_l) mov a, column_l call wcom_a mov a, column_h call wcom_a mov a, #0B6H
77
Appendix C GUI_r.h call wcom_a djnz count2, loop_font8 mov count2, #2 inc r0 cjne r0, #0, notsy_zeesy inc emi0cn notsy_zeesy: mov temp1_16, #HIGH(font8_h) mov temp2_16, #LOW(font8_h) mov a, column_l add a, backup1 mov b, a anl a, #0FH mov column_l, a call wcom_a mov a, b swap a anl a, #0FH add a, column_h mov column_h, a call wcom_a mov a, #0B7H call wcom_a djnz temp3, go_loop_font8 ret go_loop_font8: jmp loop_font8 //////////////////////////// Get audio tags ///////////////// get_audio_tags: mov a, audio_file_type cjne a, #riff, not_riff_tags call display_riff_tags ret not_riff_tags: cjne a, #flac, not_flac_tags call display_flac_tags ret not_flac_tags: sjmp $ sjmp $
////////////////////////////// Display Riff Name //////////////////// // temp4 holds number of characters
78
Appendix C GUI_r.h display_riff_name: mov a, temp4 mov temp3, #MAX_char_header+2 cjne a, #MAX_char_header+2, cherck_argain jmp nexters cherck_argain: jnc nexters mov temp3, a nexters: mov backup2, emi0cn mov column_l, #0H mov a, column_l call wcom_a mov column_h, #10H mov a, column_h call wcom_a mov a, #0B7H call wcom_a mov temp1_16, #HIGH(font8_h) mov temp2_16, #LOW(font8_h) mov temp3_16, #HIGH(font8_offset_16) mov temp4_16, #LOW(font8_offset_16) mov count2, #2 loop_font8_name: mov emi0cn, backup2 movx a, @r0 jb acc.7, bye_bye cont_di_name: clr c ;mov a, temp1 subb a, #20H jnc cont_namer bye_bye: ret cont_namer: clr c rlc a add a, temp4_16 mov dpl, a clr a addc a, temp3_16 mov dph, a clr a movc a, @a+dptr mov offset_h, a mov a, #1 movc a, @a+dptr
79
Appendix C GUI_r.h mov offset_l,a mov a, #2 movc a, @a+dptr mov r3, a mov a, #3 movc a, @a+dptr mov r3, a // add {temp2_16,temp1_16} + {offset_h,offset_l} mov a, offset_l add a, temp2_16 mov dpl, a mov a, offset_h addc a, temp1_16 mov dph, a // subtract {r3} - {offset_l} clr c mov a, r3 subb a, offset_l mov r2, a mov backup1, r2 char_loop_offset_name: call wdat_c inc dptr djnz r2, char_loop_offset_name mov temp1_16, #HIGH(font8_l) mov temp2_16, #LOW(font8_l) mov a, column_l call wcom_a mov a, column_h call wcom_a mov a, #0B6H call wcom_a djnz count2, loop_font8_name mov count2, #2 inc r0 cjne r0, #0, notsy_zeesy_name mov a, backup2 inc backup2 cjne a, #0FH, notsy_zeesy_name mov backup2, #0 notsy_zeesy_name: mov temp1_16, #HIGH(font8_h) mov temp2_16, #LOW(font8_h) mov a, column_l add a, backup1 mov b, a anl a, #0FH mov column_l, a
80
Appendix C GUI_r.h call wcom_a mov a, b swap a anl a, #0FH add a, column_h mov column_h, a call wcom_a mov a, #0B7H call wcom_a djnz temp3, go_loop_font8_name ret go_loop_font8_name: jmp loop_font8_name //////////////////////////// Display Tag //////////////////////// // temp4 holds number of characters display_tag: mov a, audio_file_type cjne a, #riff, not_riff_display mov r3, #16 movx a, @r0 mov temp4, a cjne a, #16, compare_agairn jmp begin_riff_tag_display compare_agairn: jnc begin_riff_tag_display mov r3, a dec r3 begin_riff_tag_display: inc r0 call check_emi0cn inc r0 call check_emi0cn inc r0 call check_emi0cn inc r0 call check_emi0cn furn: mov temp1, emi0cn mov a, temp3 cjne a, #artist_tag, not_riff_artist mov a, #0B4H call wcom_a mov a, #12H call wcom_a mov a, #8 call wcom_a
81
Appendix C GUI_r.h call display_riff_tag ret not_riff_artist: cjne a, #name_tag, not_riff_name call display_riff_name ret not_riff_name: cjne a, #album_tag, not_riff_album mov a, #0B3H call wcom_a mov a, #12H call wcom_a mov a, #8 call wcom_a call display_riff_tag ret not_riff_album: sjmp $ not_riff_display: cjne a, #flac, not_flac_display jmp furn not_flac_album: not_flac_display: sjmp $ ret
////////////////////////////////////// display body text ////////////////// DISPLAY_BODY_TEXT: // start at page 2, column 14 // retrieve ascii letter, cmp against '/' // calculate location in LUT // load location in DPTR call clear_body ///////////////////////////////////////// // // call when initially displaying menu // call when scrolling through menu // ////////////////////////////////////////
82
Appendix C GUI_r.h /////////////////////////////////// // // if sprite_pos < 8, show first 7 // /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// // // if sprite_pos >= 8 & if sprite_pos < sprite_min, show [sprite_pos, sprite_pos+7] // else sprite_pos >= 8 & if sprite_pos > sprite_pos_max, show [sprite_pos-7, sprite_pos] // //////////////////////////////////////////////////////////////////////////////////// setb f0 mov a, sprite_pos_max_LSB cjne a, sprite_pos_LSB, nes nes: jnc snes // sprite_pos_max < sprite_pos ;sjmp $ mov sprite_pos_max_LSB, sprite_pos_LSB mov a, sprite_pos_LSB subb a, #4 mov sprite_pos_min_LSB, a jmp sega // sprite_pos_max >= sprite_pos snes: mov a, sprite_pos_min_LSB cjne a, sprite_pos_LSB, genesis jmp sega genesis: jc sega clr f0 mov sprite_pos_min_LSB, sprite_pos_LSB sjmp $ sega: mov temp1, #0 ;mov r0, #1 mov emi0cn, temp1 ;movx a, @r0 ;mov county_saeggy, a ;mov r4, a mov r4, county_saeggy mov count2, #6 // r4 holds number of songs // county_saeggy holds number of songs // get number of /'s to ignore mov a, #5
83
Appendix C GUI_r.h clr c mov r7, #0 subb a, sprite_pos_LSB jnc ignore_first_a cpl a inc a mov r7, a // r7 holds number of /'s to ignore -1 mov a, r4 add a, #5 clr c subb a, r7 jnc ignore_first_a mov a, r4 subb a, #4 mov r7, a // correct r7 if displaying the last scrollable group of songs ignore_first_a: inc r7 mov r0, #0 mov emi0cn, temp1 // ignore r7+1 number of '/'s ignore_first: movx a, @r0 inc r0 call check_emi0cn mov temp1, emi0cn cjne a, #'/', ignore_first djnz r7, ignore_first mov r7, #0B5H inc r7 dec r0 cjne r0, #0FFH, string_loop_body dec temp1 // read and display count2 = 6 number of songs string_loop_body: inc r0 mov emi0cn, temp1 call check_emi0cn mov temp1, emi0cn movx a, @r0 cjne a, #'/', cont_body1 clr c mov a, #5 subb a, count2 ret cont_body1: mov a, r0
84
Appendix C GUI_r.h add a, #LOCATION_next_string mov r0, a mov a, emi0cn addc a, #0 mov emi0cn, a mov temp1, emi0cn dec r0 cjne r0, #0FFH, wtfs dec temp1 wtfs: page_loop_body: dec r7 cjne r7, #0AFH, cont1_body ret cont1_body: mov a, r7 call wcom_a mov a, #0EH call wcom_a mov a, #10H call wcom_a mov r3, #16 char_loop_body: inc r0 mov emi0cn, temp1 call check_emi0cn mov temp1, emi0cn movx a, @r0 cjne a, #'/', cont_body jmp string_loop_body cont_body: clr c subb a, #32 mov dptr, #font5x8 mov b, #5 mul ab add a, dpl xch a, b addc a, dph mov dph, a mov dpl, b mov r2, #5 byte_loop_body: call wdat_c inc dptr djnz r2, byte_loop_body clr a call wdat_a djnz r3, char_loop_body
85
Appendix C GUI_r.h loop_saeggi: inc r0 cjne r0, #0, no_incy_saeggi inc temp1 no_incy_saeggi: mov emi0cn, temp1 movx a, @r0 cjne a, #'/', loop_saeggi djnz count2, string_loop_body mov a, #5 ret ////////////////////////////////////////////// Display Sprite DISPLAY_SPRITE: clr c mov a, sprite_pos_LSB subb a, sprite_pos_min_LSB mov r3, a mov r4, #0B5H page_loop_sprite: cjne r4, #0AFH, cont_sprite ret cont_sprite: mov a, r4 call wcom_a mov a, #0 call wcom_a mov a, #10H call wcom_a mov r2, #3 cjne r3, #0, byte_loop_clear mov dptr, #SPRITE_pointer byte_loop_sprite: call wdat_c inc dptr djnz r2, byte_loop_sprite fin_loop_sprite: dec r3 dec r4 jmp page_loop_sprite byte_loop_clear: clr a call wdat_a djnz r2, byte_loop_clear jmp fin_loop_sprite ret
86
Appendix C GUI_r.h //////////////////////////////// _Display_Menu _Display_Menu: mov push_flags, #0 mov sprite_pos_min_LSB, #0 mov sprite_pos_max_LSB, #5 mov a, county_saeggy dec a clr c subb a, #5 jnc fuxx add a, #5 mov sprite_pos_max_LSB, a fuxx: call display_body_text ;mov sprite_pos_max_LSB, county_saeggy ;dec sprite_pos_max_LSB call display_sprite setb tr1 ret #endif
87
Appendix D ISR_r.h //////////////////////// Last Modified March 30 ////////////////// //////////////////////// March 26 size: 271 bytes ////////////////////// #ifndef isr_r #define isr_r ORG 3000H
normal_t0: cpl sclk djnz toggle, fin_ISV0 mov toggle, #2 jmp T0_ISR fin_ISV0: setb tr0 reti ///////////////////////////////////// T1 ISR ///////////////////////// T1_ISR: jb menu, _not_menu jnb _shift_menu, _not_menu setb push_flag_menu jmp fin_isr1 _not_menu: jb DOWN, _not_down jnb _shift_down, _not_down mov a, sprite_pos_LSB inc a cjne a, county_saeggy, _yes_down jmp _not_down _yes_down: inc sprite_pos_LSB mov a, sprite_pos_lsb cjne a, sprite_pos_max_lsb, noob jmp noobish noob: jc noobish call _display_menu noobish: call DISPLAY_SPRITE jmp fin_isr1 _not_down: jb UP, _not_up jnb _shift_up, _not_up mov a, sprite_pos_LSB
88
Appendix D ISR_r.h jz _not_up yes_up: dec sprite_pos_LSB mov a, sprite_pos_LSB cjne a, sprite_pos_min_lsb, farg jmp farsh farg: jnc farsh call _display_menu farsh: call DISPLAY_SPRITE jmp fin_ISR1 _not_up: jb PLAY, fin_isr1 jnb _shift_play, fin_isr1 setb push_flag_play fin_isr1: mov _shift_B1, B1 mov _shift_B2, B2 jmp fin_ISV1 ////////////////////////// T0 ISR //////////////////////// // // // T0_ISR: push psw push acc push b orl psw, #00011000B jb flag_DAT_valid, rd_data setb flag_DAT_valid mov a, SDHC anl a, #0F0H cjne a, #0F0H, first_read clr flag_DAT_valid jmp fin_t0_isr first_read: mov r6, T0_MODE cjne r6, #read_next_block_17, next_mode_isr0 jmp ixread ;cjne r6, #read_block_18_after_sequence, common_mode ;sjmp $
89
Appendix D ISR_r.h ;;;;; same as common mode next_mode_isr0: cjne r6, #find_count, common_mode jmp common_mode common_mode: mov emi0cn, #ixram mov emi0cn_min, #ixram mov emi0cn_max, #ixram_max ;jnb write_x, ixread ;mov emi0cn, #exram ;mov emi0cn_min, #exram ;mov emi0cn_max, #exram_max ixread: mov PCA0CPH0, #HIGH(One_Block) mov PCA0CPL0, #LOW(One_Block) mov PCA0CPM0, #49H mov PCA0H, #0 mov PCA0L, #0 mov pca0cn, #40H mov r1, #30H jmp fin_t0_isr // use r4 for number of values to check // use r1 to point at values to check // r6 holds mode rd_data: mov a, SDHC anl a, #0F0H rd_data_a: djnz r3, fin_t0_isr mov r3, #2 swap a add a, r7 jnb sequence_rec, con_t0_isr0 jb flag_sequence_found, con_t0_isr mov r5, a mov b, @r1 cjne a, b, fail_sequence inc r1 mov a, r4 add a, #30H cjne a, 19H, fin_sequence setb flag_sequence_found clr c mov a, r0 inc a subb a, r4 mov r1, #sequence_addr_16_LSB mov @r1, a
90
Appendix D ISR_r.h dec r1 mov a, emi0cn mov b, #0 subb a, b cjne a, #0FFH, not_ff_sequence mov a, #10H not_ff_sequence: mov @r1, a jmp fin_sequence fail_sequence: mov r1, #30H fin_sequence: mov a, r5 jmp con_t0_isr ;; 30H has character to count ;; {31H, 32H} holds number to count con_t0_isr0: jnb find_count, con_t0_isr cjne a, 30H, con_t0_isr mov r7, 32H cjne r7, #1, qwerty_isr0 mov r7, 31H cjne r7, #2, qwerty_isr0 mov a, r0 add a, #1 mov sequence_addr_16_LSB, a mov a, emi0cn addc a, #0 mov sequence_addr_16, a qwerty_isr0: djnz 32H, con_t0_isr djnz 31H, con_t0_isr setb flag_sequence_found con_t0_isr: movx @r0, a inc r0 cjne r0, #0, fin_t0_isr inc emi0cn mov a, emi0cn cjne a, emi0cn_max, fin_t0_isr mov emi0cn, emi0cn_min jmp fin_t0_isr fin_t0_isr: mov r7, a pop b pop acc
91
Appendix D ISR_r.h pop psw jmp fin_isv0 //////////////////////////////////// PCA0 ISR PCA0_ISR: push acc mov a, T0_mode jb flag_DAT_valid, next_PCA0 setb flag_DAT_fail jmp fin_read next_PCA0: jnb write_18, next1_PCA0 saeggi_spaghetti: jnb flag_sequence_found, PCA0_no_sequence setb flag_dat_received jmp fin_read PCA0_no_sequence: mov PCA0H, #0 mov PCA0L, #0 mov a, #64 loop_crc_clear: cpl sclk djnz acc, loop_crc_clear setb tr0 ;;;;;;;;;;;;;;; ;mov a, tl4 ;add a, #1 ;mov tl4, a ;mov a, th4 ;addc a, #0 ;mov th4, a ;;;;;;;;;;;;;;; setb f0 jmp fin_pca0_isr next1_PCA0: ;;;;;;;;;;; same as write_18 jb find_count, saeggi_spaghetti cjne a, #find_seq_17, next2_PCA0 setb flag_dat_received fin_read: clr tr0 clr cr clr tf0 jmp fin_pca0_isr
92
Appendix D ISR_r.h next2_PCA0: cjne a, #read_block_17, next3_PCA0 there: setb flag_dat_received jmp fin_read next3_PCA0: cjne a, #read_next_block_17, next4_PCA0 jmp there next4_PCA0: sjmp $ fin_pca0_isr: clr ccf0 clr cf pop acc ret
/////////////////////// ISR T2 ////////////////////////// isr2: push psw push acc push emi0cn push garbage clr tf2 mov a, audio_file_type cjne a, #mp3, next_type_isr2 sjmp $ next_type_isr2: cjne a, #flac, next_type2_isr2 consty: mov a, frame_type0 anl a, #11111000B cjne a, #8, not_fixed jmp not_constant_2 not_fixed: mov a, frame_type0 cjne a, #subframe_constant, $ djnz r7, fin_isr2_flac djnz r6, fin_isr2_flac fin_isr2_h: mov r0, #0 mov r1, #2 mov emi0cn, #0
93
Appendix D ISR_r.h call decode_flac_frame_header_serial mov track_pos, predictor_order dec track_pos fin_isr2_flac: rks: pop garbage pop emi0cn pop acc pop psw reti next_type2_isr2: jmp next_type2_isr22 ;;;;;;;;;;;;;;;;; fixed subframe not_constant_2: mov emi0cn, emi_backup mov a, predictor_order cjne a, #4, fpo0 jmp fpo_4 fpo0: cjne a, #0, fpo1 call get_res ;movx @r1, a ;inc r1 ;call check_emi0cn_r1 ;mov emi_backup, emi0cn mov dac0l, a mov a, b ;movx @r1, a ;inc r1 add a, #80H mov dac0h, a jmp fin_fixed fpo1: cjne a, #1, fpo_2a jmp sing fpo_2a: jmp fpo_2 sing: mov a, temp1 call get_res
94
Appendix D ISR_r.h ;movx @r1, a ;inc r1 ;cjne r1, #0, furker ;inc emi_backup ;furker: orl psw, #00011000B mov r2, b mov r3, a mov a, dac0l add a, r3 ;movx @r1, a ;inc r1 mov dac0l, a mov a, dac0h ;cpl acc.7 addc a, r2 ;movx @r1, a ;inc r1 ;cjne r1, #0, furk ;inc emi_backup ;furk: ;add a, #80H mov dac0h, a anl psw, #11100111B jmp fin_fixed fin_fixed: djnz r7, fin_isr2_flac djnz r6, fin_isr2_flac djnz partition_count, fin_f_p shick: mov a, test3 cjne a, #13H, shuz nop shuz: call get_byte shuzy: cjne a, #0FFH, shuz1 jmp not_shuz shuz1: shuz12: call get_byte
95
Appendix D ISR_r.h cjne a, #0FFH, shuz2 jmp not_shuz shuz2: call get_byte cjne a, #0FFH, shuz3 jmp not_shuz shuz3: ;sjmp $ mov emi0cn, #0 mov r0, #0 push 5 push 4 mov r5, #0 call test_sdhc pop 4 pop 5 sjmp $ sjmp $ not_shuz: mov test, a call get_byte cjne a, #0F8H, shuzy notzs: mov temp4, a call get_byte mov r_4, a mov r_0, #2 //mov a, test3 //cjne a, #85H, shuzz //nop //shuzz: jmp fin_isr2_h fin_f_p: mov r7, partition_size_LSB mov r6, partition_size_16 mov r1, #0 mov emi_backup, #0 call get_par jmp fin_isr2_flac fpo_3z: jmp fpo_3 fpo_2: cjne a, #2, fpo_3z mov emi0cn, #0EH jnb flag_first_time, nf_2 /////////////////////////////
96
Appendix D ISR_r.h ;mov r0, #0 ;movx a, @r0 ;mov 18H, a ;inc r0 ;movx a, @r0 ;mov 19H, a ;inc r0 ;movx a, @r0 ;mov 1AH, a ;mov dac0l, a ;inc r0 ;movx a, @r0 ;mov 1BH, a ;add a, #80H ;mov dac0h, a ;inc r0 ///////////////////////////// mov dac0l, 1AH mov a, 1BH add a, #80H mov dac0h, a mov track_pos, #2 clr flag_first_time jmp fin_isr2_flac nf_2: mov a, test3 cjne a, #4eH, shoot_me nop shoot_me: orl psw, #00011000B djnz track_pos, nf_sell mov track_pos, #2 mov a, r0 clr c rlc a mov r4, a mov a, r1 rlc a mov r5, a mov a, r4 clr c subb a, r2 mov r2, a mov a, r5 subb a, r3 mov r3, a anl psw, #11100111B call get_res orl psw, #00011000B add a, r2 mov r2, a
97
Appendix D ISR_r.h xch a, b addc a, r3 mov r3, a anl psw, #11100111B jmp fin_fpo2 nf_sell: mov a, r2 clr c rlc a mov r4, a mov a, r3 rlc a mov r5, a mov a, r4 clr c subb a, r0 mov r0, a mov a, r5 subb a, r1 mov r1, a anl psw, #11100111B call get_res orl psw, #00011000B add a, r0 mov r0, a xch a, b addc a, r1 mov r1, a anl psw, #11100111B fin_fpo2: xch a, b ;mov emi0cn, emi_backup ;movx @r1, a mov dac0l, a ;inc r1 xch a, b ;movx @r1, a add a, #80H mov dac0h, a ;inc r1 ;cjne r1, #0, hfmf ;inc emi_backup ;hfmf:
98
Appendix D ISR_r.h djnz r7, fin_hfmf djnz r6, fin_hfmf djnz partition_count, fin_hfmf1 jmp shick fin_hfmf1: mov r7, partition_size_LSB mov r6, partition_size_16 clr a ;mov emi_backup, a ;mov r1, a call get_par fin_hfmf: jmp fin_isr2_flac fpo_3: cjne a, #3, $ jmp your_momma fpo_4a: jmp fpo_4 your_momma: ;mov emi0cn, #0EH jnb flag_first_time, nf_3 ///////////////////////////// ;mov r0, #0 ;movx a, @r0 ;mov 18H, a ;inc r0 ;movx a, @r0 ;mov 19H, a ;inc r0 ///////////////////////////// djnz track_pos, f_1 ///////////////////////////// ;movx a, @r0 ;mov 1AH, a ;inc r0 ;movx a, @r0 ;mov 1BH, a ;inc r0 ;movx a, @r0 ;mov 1CH, a ///////////////////////////// ;mov dac0l, a ;inc r0 ;movx a, @r0 ;mov 1DH, a ;add a, #80H ;mov dac0h, a ///////////////////////////// mov dac0l, 1CH
99
Appendix D ISR_r.h mov a, #80H add a, 1DH mov dac0h, a mov track_pos, #3 clr flag_first_time jmp fin_isr2_flac f_1: ///////////////////////////// ;movx a, @r0 ;mov 1AH, a ;mov dac0l, a ;inc r0 ;movx a, @r0 ;mov 1BH, a ;add a, #80H ;mov dac0h, a ;inc r0 ;movx a, @r0 ;mov 1CH, a ;inc r0 ;movx a, @r0 ;mov 1DH, a ;inc r0 ;jmp fin_isr2_flac ///////////////////////////// mov dac0l, 1AH mov a, #80H add a, 1BH mov dac0h, a jmp fin_isr2_flac sjmp $ nf_3: ////////////////////////////////////////////////// // // 3f(t-1) - 3f(t-2) + f(t-3) + r // ////////////////////////////////////////////////// orl psw, #00011000B mov a, track_pos djnz acc, nf_sell_1 mov track_pos, #3 mov a, r2 clr c subb a, r0 mov r6, a mov a, r3 subb a, r1 mov r7, a
100
Appendix D ISR_r.h mov a, r6 mov b, #3 mul ab mov r6, a mov r_0, b mov a, r7 mov b, #3 mul ab add a, r_0 mov r7, a mov a, r6 add a, r4 mov r4, a mov a, r7 addc a, r5 mov r5, a anl psw, #11100111B call get_res orl psw, #00011000B add a, r4 mov r4, a xch a, b addc a, r5 mov r5, a anl psw, #11100111B jmp fin_fpo3 nf_sell_1: mov track_pos, a cjne a, #1, nf_sell_2 mov a, r0 clr c subb a, r4 mov r6, a mov a, r1 subb a, r5 mov r7, a mov a, r6 mov b, #3 mul ab mov r6, a mov r_0, b mov a, r7 mov b, #3 mul ab add a, r_0 mov r7, a mov a, r6 add a, r2 mov r2, a mov a, r7 addc a, r3 mov r3, a
101
Appendix D ISR_r.h anl psw, #11100111B call get_res orl psw, #00011000B add a, r2 mov r2, a xch a, b addc a, r3 mov r3, a anl psw, #11100111B jmp fin_fpo3 nf_sell_2: clr c mov a, r4 subb a, r2 mov r6, a mov a, r5 subb a, r3 mov r7, a mov a, r6 mov b, #3 mul ab mov r6, a mov r_0, b mov a, r7 mov b, #3 mul ab add a, r_0 mov r7, a mov a, r6 add a, r0 mov r0, a mov a, r7 addc a, r1 mov r1, a anl psw, #11100111B call get_res orl psw, #00011000B add a, r0 mov r0, a mov dac0l, a xch a, b addc a, r1 mov r1, a add a, #80h mov dac0h, a anl psw, #11100111B jmp fin_fpo3 fin_fpo3: djnz r7, fin_hfmf2 djnz r6, fin_hfmf2 djnz partition_count, fin_hfmf3
102
Appendix D ISR_r.h jmp shick fin_hfmf3: mov r7, partition_size_LSB mov r6, partition_size_16 clr a mov emi_backup, a mov r1, a call get_par fin_hfmf2: jmp fin_isr2_flac fux_your_couch: jmp fpo1 ////////////////////////////////////////////////// fpo_4: cjne a, #4, fux_your_couch ///////////////////////////// ;mov emi0cn, #0EH ///////////////////////////// orl psw, #00011000B jnb flag_first_time, nf_4 mov a, track_pos djnz acc, f4_c mov track_pos, a mov dac0l, r6 mov a, r7 add a, #80H mov dac0h, a clr flag_first_time mov track_pos, #4 anl psw, #11100111B jmp fin_isr2_flac f4_c: mov track_pos, a cjne a, #1, f4_c2 mov dac0l, r4 mov a, r5 add a, #80H mov dac0h, a anl psw, #11100111B jmp fin_isr2_flac f4_c2: ///////////////////////////// ;mov r0, #0 ;movx a, @r0 ;mov r_0, a
103
Appendix D ISR_r.h ;inc r0 ;movx a, @r0 ;mov r1, a ;inc r0 ;movx a, @r0 ;mov r2, a ;mov dac0l, a ;inc r0 ;movx a, @r0 ;mov r3, a ;add a, #80H ;mov dac0h, a ;inc r0 ;movx a, @r0 ;mov r4, a ;inc r0 ;movx a, @r0 ;mov r5, a ;inc r0 ;movx a, @r0 ;mov r6, a ;inc r0 ;movx a, @r0 ;mov r7, a ;mov r0, r_0 ///////////////////////////// mov dac0l, r2 mov a, r3 add a, #80H mov dac0h, a anl psw, #11100111B jmp fin_isr2_flac nf_4: orl psw, #00011000B djnz track_pos, nf_fn1 mov track_pos, #4 mov a, r4 add a, r0 mov r_0, a mov a, r5 addc a, r1 mov r_1, a clr a mov acc.2, c mov r_2, a mov a, r_0 mov b, #4 mul ab
104
Appendix D ISR_r.h mov r_0, a mov r_4, b mov a, r_1 mov b, #4 mul ab add a, r_4 mov r_1, a mov a, r_2 addc a, b mov r_2, a mov a, r2 mov b, #6 mul ab mov r_4, b clr c xch a, r_0 subb a, r_0 mov r_0, a mov f0, c mov a, r3 mov b, #6 mul ab add a, r_4 xch a, b addc a, #0 mov r_4, a xch a, b xch a, r_1 mov c, f0 subb a, r_1 mov r_1, a mov a, r_2 subb a, b mov r_2, a clr c mov a, r_0 subb a, r6 mov r6, a mov a, r_1 subb a, r7 mov r7, a mov a, r_2 subb a, #0 anl psw, #11100111B call get_res orl psw, #00011000B add a, r6 mov r6, a xch a, b addc a, r7
105
Appendix D ISR_r.h mov r7, a jmp fin_fpo4 nf_fn1: mov a, track_pos cjne a, #1, nf_fn2 mov a, r2 add a, r6 mov r_0, a mov a, r3 addc a, r7 mov r_1, a clr a mov acc.2, c mov r_2, a mov a, r_0 mov b, #4 mul ab mov r_0, a mov r_4, b mov a, r_1 mov b, #4 mul ab add a, r_4 mov r_1, a mov a, r_2 addc a, b mov r_2, a mov a, r0 mov b, #6 mul ab mov r_4, b clr c xch a, r_0 subb a, r_0 mov r_0, a mov f0, c mov a, r1 mov b, #6 mul ab add a, r_4 xch a, b addc a, #0 mov r_4, a xch a, b xch a, r_1 mov c, f0 subb a, r_1 mov r_1, a mov a, r_2 subb a, b
106
Appendix D ISR_r.h mov r_2, a clr c mov a, r_0 subb a, r4 mov r4, a mov a, r_1 subb a, r5 mov r5, a mov a, r_2 subb a, #0 anl psw, #11100111B call get_res orl psw, #00011000B add a, r4 mov r4, a xch a, b addc a, r5 mov r5, a jmp fin_fpo4 nf_fn2: cjne a, #2, nf_fn3 mov a, r0 add a, r4 mov r_0, a mov a, r1 addc a, r5 mov r_1, a clr a mov acc.2, c mov r_2, a mov a, r_0 mov b, #4 mul ab mov r_0, a mov r_4, b mov a, r_1 mov b, #4 mul ab add a, r_4 mov r_1, a mov a, r_2 addc a, b mov r_2, a mov a, r6 mov b, #6 mul ab mov r_4, b clr c xch a, r_0 subb a, r_0
107
Appendix D ISR_r.h mov r_0, a mov f0, c mov a, r7 mov b, #6 mul ab add a, r_4 xch a, b addc a, #0 mov r_4, a xch a, b xch a, r_1 mov c, f0 subb a, r_1 mov r_1, a mov a, r_2 subb a, b mov r_2, a clr c mov a, r_0 subb a, r2 mov r2, a mov a, r_1 subb a, r3 mov r3, a mov a, r_2 subb a, #0 //jnz $ anl psw, #11100111B call get_res orl psw, #00011000B add a, r2 mov r2, a xch a, b addc a, r3 mov r3, a jmp fin_fpo4 nf_fn3: mov a, r6 add a, r2 mov r_0, a mov a, r7 addc a, r3 mov r_1, a clr a mov acc.2, c mov r_2, a mov a, r_0 mov b, #4 mul ab mov r_0, a
108
Appendix D ISR_r.h mov r_4, b mov a, r_1 mov b, #4 mul ab add a, r_4 mov r_1, a mov a, r_2 addc a, b mov r_2, a mov a, r4 mov b, #6 mul ab mov r_4, b clr c xch a, r_0 subb a, r_0 mov r_0, a mov f0, c mov a, r5 mov b, #6 mul ab add a, r_4 xch a, b addc a, #0 mov r_4, a xch a, b xch a, r_1 mov c, f0 subb a, r_1 mov r_1, a mov a, r_2 subb a, b mov r_2, a clr c mov a, r_0 subb a, r0 mov r0, a mov a, r_1 subb a, r1 mov r1, a mov a, r_2 subb a, #0 //jnz $ anl psw, #11100111B call get_res orl psw, #00011000B add a, r0 mov r0, a xch a, b addc a, r1
109
Appendix D ISR_r.h mov r1, a jmp fin_fpo4 fin_fpo4: anl psw, #11100111B xch a, b mov emi0cn, emi_backup ;movx @r1, a mov dac0l, a ;inc r1 xch a, b ;movx @r1, a add a, #80H mov dac0h, a ;inc r1 ;cjne r1, #0, hfmf4 ;inc emi_backup ;hfmf4: djnz r7, fin_hfmfz djnz r6, fin_hfmfz djnz partition_count, fin_hfmfz2 jmp shick fin_hfmfz2: mov r7, partition_size_LSB mov r6, partition_size_16 clr a mov emi_backup, a mov r1, a call get_par fin_hfmfz: jmp fin_isr2_flac fpo_un: sjmp $ unknown_fixed: sjmp $ not_fixed_isr2: sjmp $ reti
110
Appendix D ISR_r.h not_constant_21: sjmp $ // assume wav type at this point: next_type2_isr22: cpl sclk call decode_riff pop acc pop psw reti ;;;;;;;;;;;;;;;;;;; constant subframe 1 subframe_type_1: cjne a, #subframe_constant, decf_not_constant1 ;; place sample in a register jmp constant_sample1 ;;;;;;;;;;;;;;;;;;; fixed subframe 1 decf_not_constant1: cjne a, #subframe_fixed_1, decf_not_fixed1 sjmp $ jmp fin_subframe decf_not_fixed1: sjmp $ fin_subframe: ret ////////////////////////// New ISR0 ///////////////////////////// ///////////////////////////////////////////////////////////////// new_ISR0: mov th0, #high(hz_200) mov tl0, #low(hz_200) djnz toggle, fin_new0 mov toggle, #2 djnz toggle2, cont_0isr_jmp mov a, current_time_BCD1 add a, #1 da a cjne a, #60H, display_bcd2 mov a, current_time_BCD2 add a, #1 mov current_time_BCD2, a da a mov a, #0B0H call wcom_a mov a, #9 call wcom_a mov a, #15H
111
Appendix D ISR_r.h call wcom_a mov a, current_time_bcd2 anl a, #0F0H swap a mov b, #5 mul ab add a, #low(f5x8_0) mov dpl, a mov a, #high(f5x8_0) addc a, #0 mov dph, a mov toggle2, #5 jmp display_bcd4_loop cont_0isr_jmp: jmp cont_0isr display_bcd4_loop: call wdat_c inc dptr djnz toggle2, display_bcd4_loop jmp saeggi_spaghetter fin_new0: jmp fin_newisr0 saeggi_spaghetter: mov a, current_time_bcd2 anl a, #0FH mov b, #5 mul ab add a, #low(f5x8_0) mov dpl, a mov a, #high(f5x8_0) addc a, #0 mov dph, a mov toggle2, #5 display_bcd3_loop: call wdat_c inc dptr djnz toggle2, display_bcd3_loop mov a, #0 display_bcd2: mov current_time_BCD1, a mov a, #0B0H call wcom_a mov a, #8 call wcom_a
112
Appendix D ISR_r.h mov a, #16H call wcom_a mov a, current_time_bcd1 anl a, #0F0H swap a mov b, #5 mul ab add a, #low(f5x8_0) mov dpl, a mov a, #high(f5x8_0) addc a, #0 mov dph, a mov toggle2, #5 display_bcd2_loop: call wdat_c inc dptr djnz toggle2, display_bcd2_loop mov a, current_time_bcd1 anl a, #0FH mov b, #5 mul ab add a, #low(f5x8_0) mov dpl, a mov a, #high(f5x8_0) addc a, #0 mov dph, a mov toggle2, #5 display_bcd1_loop: call wdat_c inc dptr djnz toggle2, display_bcd1_loop mov toggle2, #10 cont_0isr: djnz 31H, fin_new0 mov 31H, temp1 dec 30H mov a, 30H cjne a, #0FFH, fin_new0 mov 30H, temp2 mov a, column_l call wcom_a mov a, column_h call wcom_a mov a, #18H call wdat_a mov a, column_l
113
Appendix D ISR_r.h cjne a, #0FH, saeggi_meanie mov column_l, #0 inc column_h jmp fin_new0 saeggi_meanie: inc column_l jmp fin_new0 fin_newisr0: jb menu, _not_menu0 jnb _shift_menu, _not_menu0 setb push_flag_menu jmp fin_isrn0 _not_menu0: jb PLAY, not_play0 jnb _shift_play, not_play0 setb push_flag_play jmp fin_isrn0 not_play0: jb stop, not_stop0 jnb _shift_stop, not_stop0 setb push_flag_stop jmp fin_isrn0 not_stop0: jb left, not_left0 jnb _shift_left, not_left0 setb push_flag_left jmp fin_isrn0 not_left0: jb right, not_right0 jnb _shift_right, not_right0 setb push_flag_right jmp fin_isrn0 not_right0: jb mode, fin_isrn0 jnb _shift_mode, fin_isrn0 setb push_flag_mode fin_isrn0: mov _shift_B1, B1 mov _shift_B2, B2 reti
new_PCA0_ISR:
114
Appendix D ISR_r.h clr tr2 clr tr0 clr cr clr ccf0 setb flag_finish_play reti new_isr1: reti
#endif
115
Appendix E MP3_r.h ////////////////////////// Last Modified March 30 //////////////////// ///////////////////////// March 26 size: 708 bytes /////////////////////// #ifndef MP3_r #define MP3_r ORG 7000H /////////////////////// Initialization Routine // // _8051_Initialization: mov wdtcn,#0DEh ; disable watchdog mov wdtcn,#0ADh mov xbr2,#40h ; enable port output mov p2mdout, #00000000B mov p3mdout, #00000010B mov count_it, #value mov oscicn, #00010111B // Run at 16 MHz mov emi0cf, #00111000B mov ckcon, #28H ;mov ckcon #20H for t2 /12 mov t2con, #0 mov xbr1, #00000010B mov pca0md, #00000101B mov ie, #10101000B mov eie1, #08H mov ip, #20H mov emi0cf, #00111000B mov emi0tc, #xram_timing mov p74out, #0FFH mov ref0cn, #3 mov dac0cn, #9FH mov dac1cn, #9FH clr a mov r0, a mov r1, #ixram mov a, #AA clr_allx_a: mov emi0cn, r1 clr_allx: movx @r0, a djnz r0, clr_allx inc r1 cjne r1, #ixram_max, clr_allx_a ret
116
Appendix E MP3_r.h ///////////////////////////////////////// clear exram ////////////////// _XRAM_INITIALIZATION: mov emi0cn, #exram mov r0, #0 mov a, #0 loop_xram: mov a, #0CDH movx @r0, a inc r0 cjne r0, #0, loop_xram inc emi0cn mov a, emi0cn cjne a, #exram_max, loop_xram ret //////////////////////////////////// get body text //////////// _LCD_BODY_TEXT_GET: mov t0_mode, #find_seq_18 mov cmd_stat, #0 call send_cmd18 clr tr0 mov 30H, #'/' mov 31H, #'/' mov 1CH, #2 setb tr0 loop_get: jnb flag_dat_received, loop2_get sjmp cont_get loop2_get: jnb flag_sequence_found, loop_get call send_cmd12 cont_get: clr tr0 ret ////////////////////////////////////// read boot sector read_boot_sector:
// read sector 0, CMD17 clr a mov T0_STAT, a mov T0_MODE, #find_seq_17
117
Appendix E MP3_r.h mov addr_1, a mov addr_2, a mov addr_3, a mov addr_4, a mov CRC, #55H call send_CMD17 clr tr0 mov 30H, #sector0_1 mov 31H, #sector0_2 mov 32H, #sector0_3 mov 33H, #sector0_4 mov 1CH, #4 setb tr0 here2_playlist: jnb flag_DAT_fail, next2_playlist next2_playlist: jnb flag_DAT_received, here2_playlist jnb flag_sequence_found, $ mov r0, #sequence_addr_16 mov emi0cn, @r0 inc r0 mov a, @r0 add a, #7 jnc notc_playlist mov r2, emi0cn cjne r2, #10H, not_10_playlist mov emi0cn, #-1 not_10_playlist: inc emi0cn notc_playlist: // get boot sector 32-bit address mov r0, a movx a, @r0 ;add a, #1 mov addr_4, a inc r0 cjne r0, #0, not_01_pl inc emi0cn not_01_pl: movx a, @r0 mov addr_3, a inc r0 cjne r0, #0, not_02_pl inc emi0cn not_02_pl: movx a, @r0 mov addr_2, a inc r0 cjne r0, #0, not_03_pl
118
// FATAL ERROR
Appendix E MP3_r.h inc emi0cn not_03_pl: movx a, @r0 mov addr_1, a // calculate 32-bit address CRC for CMD17 mov 30H, #51H call crc7 // read boot sector, CMD17 mov t0_mode, #find_seq_17 call send_cmd17 clr tr0 mov 30H, #boot1 mov 31H, #boot2 mov 32H, #boot3 mov 1CH, #3 setb tr0 jnb flag_DAT_received, $ jnb flag_sequence_found, $ ret
//FATAL ERROR
///////////////////////////////////// Calculate FIA ///////////////// /////////////////////////// Initialize Stage 3 //////////////////// _initialize_stage_3: clr flag_main_decode clr tr1 anl tmod, #11111110B orl tmod, #00000010B ;;;;;;;;;;;;;;;;;;;;;;;;;; djnz count_it, go_for_it mov r0, #7FH mov emi0cn, #0 zeg: mov a, @r0 movx @r0, a djnz r0, zeg // reset the SDHC call _SDHC_INITIALIZATION call _SDHC_TRANSFER_READY mov r0, #7fh zag: mov emi0cn, #0 movx a, @r0 mov @r0, a
119
Appendix E MP3_r.h djnz r0, zag mov count_it, #value go_for_it: ;;;;;;;;;;;;;;;;;;;;;;;;;; mov push_flags, #0 mov play_mode_flags, #0 call display_new_song mov audio_file_type, #0 mov r0, #current_pl_32 mov r1, #addr_1 mov r2, #4 loopy_looky: mov a, @r1 mov @r0, a inc r0 inc r1 djnz r2, loopy_looky mov 30H, #52H call crc7 mov r7, #0 mov r6, #0 ;sharmys_i_cant_believe_i_already_made_a_label_named_sharmys: ;djnz r6, $ ;djnz r7,sharmys_i_cant_believe_i_already_made_a_label_named_sharmys ; mov t0_mode, #find_count_18 mov t0_mode, #find_count_18 call send_cmd18 clr tr0 ; mov 30H, #'/' ; mov 31H, #'/' ; mov 1cH, #2 ;;;;;;;;;;;;;;;;;;;;; mov 30H, #'/' mov a, sprite_pos_LSB add a, #3 mov 32H, a mov a, #1 addc a, sprite_pos_16 mov 31H, a ;;;;;;;;;;;;;;;;;;;;; setb tr0 jnb flag_dat_valid, $ jnb flag_sequence_found, $
120
Appendix E MP3_r.h call send_cmd12 call get_pl_addresses mov r0, #current_song_32 mov r1, #addr_1 mov r2, #4 loopy_looper: mov a, @r1 mov @r0, a inc r0 inc r1 djnz r2, loopy_looper mov 30H, #51H call crc7 mov t0_mode, #read_block_17 call send_cmd17 jnb flag_dat_received, $ call get_audio_type call get_audio_specs call get_audio_tags ret next_type: sjmp $ ret ///////////////////////////////////////// calculate_FIA: // get sectors per cluster 8-bits mov emi0cn, sequence_addr_16 mov a, sequence_addr_16_LSB add a, #LOCATION_cluster_size mov r0, a jnc no_c_cluster inc emi0cn no_c_cluster: movx a, @r0 mov cluster_size, a // get reserved sectors 16-bit mov emi0cn, sequence_addr_16 mov a, sequence_addr_16_LSB add a, #LOCATION_reserved_sectors mov r0, a jnc no_c_reserved
121
Appendix E MP3_r.h inc emi0cn no_c_reserved: mov r1, #reserved_sectors_16 inc r0 cjne r0, #0, not_0_r1 inc emi0cn not_0_r1: movx a, @r0 mov @r1, a dec r0 cjne r0, #0FFH, not_ff_r1 dec emi0cn not_ff_r1: inc r1 movx a, @r0 mov @r1, a // get sectors per FAT 32-bit mov emi0cn, sequence_addr_16 mov a, sequence_addr_16_LSB add a, #LOCATION_fat_size add a, #3 jnc no_c_fat inc emi0cn no_c_fat: mov r0, a mov r1, #fat_sectors_32 mov r2, #4 loop_fat_size: movx a, @r0 mov @r1, a inc r1 dec r0 cjne r0, #0FFH, not_ff_size dec emi0cn not_ff_size: djnz r2, loop_fat_size // Calculate 32-bit File Index Address = // boot sector address (32 bit)+ // reserved sectors (16 bit) + // 2*sectors per FAT (32 bit) //2*sectors per FAT mov a, #fat_sectors_32 add a, #3 mov r0, a mov r1, #temp3_32 clr c mov r2, #4 loop_address_shift: mov a, @r0
122
Appendix E MP3_r.h rlc a mov @r1, a dec r0 dec r1 djnz r2, loop_address_shift // +reserved sectors (16 bit) mov r1, #reserved_sectors_LSB mov r0, #temp3_32 mov r2, #2 clr c loop_playlist_calc1: mov a, @r0 addc a, @r1 mov @r0, a dec r0 dec r1 djnz r2, loop_playlist_calc1 jnc not_c_calc1 dec r0 inc @r0 not_c_calc1: // +boot sector address (32 bit) mov r1, #addr_4 mov r0, #temp3_32 mov r2, #4 clr c loop_playlist_calc2: mov a, @r0 addc a, @r1 mov @r1, a dec r0 dec r1 djnz r2, loop_playlist_calc2 // FIA stored in addr1-4 ret /////////////////////////// get audio type //////////////////// get_audio_type: mov emi0cn, #ixram mov r0, #0 movx a, @r0 cjne a, #'R', not_riff inc r0 call check_emi0cn movx a, @r0 cjne a, #'I', not_recognized
123
Appendix E MP3_r.h inc r0 call check_emi0cn movx a, @r0 cjne a, #'F', not_recognized inc r0 call check_emi0cn movx a, @r0 cjne a, #'F', not_recognized mov audio_file_type, #riff ret not_riff: cjne a, #'f', not_flac inc r0 call check_emi0cn movx a, @r0 cjne a, #'L', not_recognized inc r0 call check_emi0cn movx a, @r0 cjne a, #'a', not_recognized inc r0 call check_emi0cn movx a, @r0 cjne a, #'C', not_recognized mov audio_file_type, #flac mov test0, #-1 mov test1, #-1 mov test2, #-1 mov test3, #-1 ret sjmp $ not_flac: sjmp $ not_recognized: sjmp $ ret ///////////////////////////// audio specs ///////////////// get_audio_specs: mov a, audio_file_type cjne a, #riff, next_type_specs ;jmp riff_specs
124
Appendix E MP3_r.h ;next_type_spec: ;jmp next_type_specs call riff_specs ret next_type_specs: cjne a, #flac, next2_type_specs call flac_specs ret next2_type_specs: sjmp $ ret
////////////////////////// Check emi0cn ////////////////////////// check_emi0cn: push acc mov a, r0 jmp nexterzy check_emi0cn_r1: push acc mov a, r1 nexterzy: jnz fin_check mov a, emi0cn cjne a, #0fH, not_tensaluger mov emi0cn, #0 ;; mov a, tl4 add a, #1 mov tl4, a mov a, th4 addc a, #0 mov th4, a ;; jmp fin_check not_tensaluger: inc emi0cn fin_check: pop acc ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
125
Appendix E MP3_r.h
///////////////////////////// Initialize Play ////////////////////// initialize_play: mov a, audio_file_type cjne a, #riff, next_type_play call wav_play_initialization ret next_type_play: cjne a, #flac, next2_type_play call flac_play_initialization ret next2_type_play: sjmp $ ret ////////////////////////////////////////////////// PLAYLIST INIT _XRAM_PLAYLIST_INITIALIZATION: ///////////////// ALGORITHM + CODE /////////////////// /* // load file index address (FIA) and CRC7 for CMD18 from flash mov psctl, #4 mov r0, #FIA_NAME_24 dec r0 mov dptr, #0 clr f0 flash_FIA: inc r0 clr a movc a, @a+dptr mov @r0, a inc dptr cjne r0, #FIA_32_LSB, flash_FIA mov psctl, #0 // read address with CMD17 mov r0, #FIA_CRC17 mov CRC, @r0 inc r0 inc r0 mov addr_1,@r0 inc r0 mov addr_2,@r0
126
Appendix E MP3_r.h inc r0 mov addr_3,@r0 inc r0 mov addr_4,@r0 mov T0_STAT, #0 mov T0_MODE,#find_seq_17 call send_CMD17 clr tr0 mov r0, #30H mov r1, #FIA_NAME_24 mov r2, #3 mov 1CH, r2 loop_FIA_name: mov a, @r1 mov @r0, a inc r0 inc r1 djnz r2, loop_FIA_name setb tr0 here_playlist: jnb flag_DAT_fail, next_playlist jmp if1_playlist next_playlist: jnb flag_DAT_received, here_playlist jnb flag_sequence_found, if1_playlist jmp contin1_playlist */ //********** IF file index address in flash is incorrect: if1_playlist: setb f0 call read_boot_sector call calculate_FIA mov r0, #addr_1 mov r1, #FIA_32 mov r2, #4 store_FIA: mov a, @r0 mov @r1, a inc r0 inc r1 djnz r2, store_FIA mov 30H, #51H call crc7 mov FIA_CRC17, CRC
127
Appendix E MP3_r.h mov T0_MODE, #read_block_17 call send_cmd17 jnb flag_dat_valid, $ jnb flag_dat_received, $ mov r0, #0 mov emi0cn, #0 mov r2, #3 mov r1, #FIA_name_24 loop_fia_name2: movx a, @r0 mov @r1, a inc r0 inc r1 djnz r2, loop_fia_name2 // calculate file index address CRC7 for CMD18 mov 30H, #52H call crc7 mov FIA_CRC18, CRC //********** CONTINUE // verify presence of all_pl.plx contin1_playlist: mov T0_MODE, #find_seq_18 call send_cmd18 clr tr0 mov 30H, #pl_index_name1 mov 31H, #pl_index_name2 mov 32H, #pl_index_name3 mov 33H, #pl_index_name4 mov 34H, #pl_index_name5 mov 35H, #pl_index_name6 mov 36H, #pl_index_name7 mov 37H, #pl_index_name8 mov 38H, #pl_index_name9 mov 39H, #pl_index_name10 mov 3AH, #pl_index_name11 mov 1CH, #11 setb tr0 // read file index with CMD18 jnb flag_sequence_found, $ jnb flag_dat_received, $ call send_cmd12
128
// FATAL ERROR
Appendix E MP3_r.h //**************************************** // get cluster address for all_pl.plx mov emi0cn, sequence_addr_16 mov a, sequence_addr_16_LSB add a, #LOCATION_cluster_addr mov r0, a movx a, @r0 /////////////////////////// clr c subb a, #2 ////////////////////////// mov temp4_32, a inc r0 movx a, @r0 mov b, #0 subb a, b mov temp3_32, a mov temp2_32, #0 ////////////////////////// mov temp1_32, #0 ////////////////////////// // Calculate sector address for all_pl.plx // file index address + (cluster +1) // calculate CRC7 for CMD18 mov b, cluster_size loop_calc_all_pl_a: mov r0, #temp4_32 mov r2, #4 clr c mov a, b rrc a mov b, a jz fin_calc_loop loop_calc_all_pl: mov a, @r0 rlc a mov @r0, a dec r0 djnz r2, loop_calc_all_pl jmp loop_calc_all_pl_a fin_calc_loop: mov r0, #temp4_32 mov r1, #FIA_32_LSB mov r2, #4 clr c loop_calc2_all_pl: mov a, @r0 addc a, @r1 mov @r0, a
129
Appendix E MP3_r.h dec r0 dec r1 djnz r2, loop_calc2_all_pl mov r0, #temp4_32 mov r1, #all_pl_addr_32_LSB mov addr_4, @r0 mov @r1, addr_4 dec r1 dec r0 mov addr_3, @r0 mov @r1, addr_3 dec r1 dec r0 mov addr_2, @r0 mov @r1, addr_2 dec r1 dec r0 mov addr_1, @r0 mov @r1, addr_1 mov 30H, #52H call crc7 mov all_pl_crc18, crc call_18: ;call send_cmd13 mov r2, #0 djnz r2,$ mov a, SDHC anl a, #0F0H xrl a, #0F0H jnz call_18 mov t0_mode, #find_seq_18 //x loopys: ;setb check_rsp call send_cmd18 clr tr0 ;call send_cmd13 ;jmp loopys mov a, #'/' mov 30H, a mov 31H, a mov 1CH, #2 ;mov 30H, #'W' ;mov 31H, #'a' ;mov 32H, #'v' ;mov 1CH, #3 setb tr0
130
Appendix E MP3_r.h loopy: jnb flag_dat_fail,next_loopy sjmp $ ERROR X10 next_loopy: jnb flag_sequence_found, loopy
// FATAL
call send_cmd12 jnb f0, contin2_playlist //********** IF file index was incorrect: /****************************************** Step 1. Disable interrupts. Step 2. Set FLWE (FLSCL.0) to enable FLASH writes/erases via user software. Step 3. Set PSEE (PSCTL.1) to enable FLASH erases. Step 4. Set PSWE (PSCTL.0) to redirect MOVX commands to write to FLASH. Step 5. Use the MOVX command to write a data byte to any location within the 512-byte page to be erased. Step 6. Clear PSEE to disable FLASH erases Step 7. Use the MOVX command to write a data byte to the desired byte location within the erased 512-byte page. Repeat this step until all desired bytes are written (within the target page). Step 8. Clear the PSWE bit to redirect MOVX commands to the XRAM data space. Step 9. Re-enable interrupts. ******************************************/ // store file index address, CRC7 for CMD18, // and volume name in flash ROM contin2_playlist: // store important values // store playlist information in xram fin_playlist: ret ///////////////////////////////////////////////// _INITIALIZE_STAGE_1: mov r0, #addr_1 mov r1, #all_pl_addr_32 mov r2, #4 loopy_ini: mov a, @r1 mov @r0, a inc r1 inc r0 djnz r2, loopy_ini mov r0, #current_pl_32 mov r1, #all_pl_addr_32
131
Appendix E MP3_r.h mov r2, #4 loopy_init: mov a, @r1 mov @r0, a inc r1 inc r0 djnz r2, loopy_init // get # songs mov 30H, #51H call CRC7 mov t0_mode, #read_block_17 call send_cmd17 jnb flag_dat_received, $ mov emi0cn, #ixram mov r0, #0 //movx a, @r0 //mov sprite_pos_max_16, a inc r0 movx a, @r0 //clr c //subb a, #1 //mov sprite_pos_max_LSB, a //mov a, sprite_pos_max_16 //subb a, #0 //mov sprite_pos_max_16, a mov county_saeggy, a call display_header mov sprite_pos_16, #0 mov sprite_pos_LSB, #0 ret
///////////////////////////////// _Play_song ////////////////////// ////////////////////////////// stage_3 input decoding //////////////// input_decode_3: jbc push_flag_play, push_play_3 jbc push_flag_menu, push_menu_3 jbc flag_finish_play, finish_play_3 jbc push_flag_left, prev_3 jbc push_flag_right, next_3 jb push_flag_stop, push_stop_3 jbc push_flag_mode, push_mode_3 sjmp $
132
Appendix E MP3_r.h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push_mode_3: ;call change_mode setb tr0 jmp stage_3_loop push_stop_3: setb tr0 jmp stage_3_loop jmp stage_2 push_play_3: setb tr0 jmp stage_3_loop jbc flag_pause, resume_play jbc push_flag_stop, resume_play setb flag_pause jmp stage_3_loop resume_play: setb tr0 jmp stage_3_loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push_menu_3: setb tr0 jmp stage_3_loop jmp main_pm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; finish_play_3: mov a, sprite_pos_16 cjne a, sprite_pos_max_16, yar mov a, sprite_pos_LSB cjne a, sprite_pos_max_LSB, yar jmp stage_2 yar: call next_song jmp stage_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; prev_3: mov a, sprite_pos_16 jnz prevs3 mov a, sprite_pos_LSB jnz prevs3 jmp stage_3 prevs3: call prev_song
133
Appendix E MP3_r.h jmp stage_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; next_3: mov a, sprite_pos_16 cjne a, sprite_pos_max_16, nexts3 mov a, sprite_pos_LSB cjne a, sprite_pos_max_LSB, nexts3 setb tr0 jmp stage_3_loop nexts3: call next_song jmp stage_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ////////////////// Play Song ///////////////////
////////////////////////// gets song/playlist address
get_pl_addresses_count: mov r0, sequence_addr_16_LSB mov emi0cn, sequence_addr_16 inc r0 jmp qwerty_pl get_pl_addresses: mov emi0cn, #ixram mov r0, #0 skip_first: //mov emi0cn, temp1 movx a, @r0 inc r0 cjne a, #'/', skip_first mov r3, sprite_pos_16 mov r4, sprite_pos_LSB inc r4 seek_next_string: djnz r4, cont_next_string dec r3
134
Appendix E MP3_r.h cjne r3, #0FFH, cont_next_string qwerty_pl: mov r1, #addr_1 mov r2, #4 loop_movey_exy: movx a, @r0 mov @r1, a inc r0 call check_emi0cn inc r1 djnz r2, loop_movey_exy inc r0 call check_emi0cn movx a, @r0 mov CRC, a inc r0 call check_emi0cn ret cont_next_string: mov a, r0 add a, #LOCATION_next_string mov r0, a clr a addc a, emi0cn mov emi0cn, a loop_char_check: movx a, @r0 inc r0 call check_emi0cn cjne a, #'/', loop_char_check jmp seek_next_string ////////////////////////////////// Next Song next_song: anl tmod, #11111110B orl tmod, #00000010B call send_cmd12 mov r2, #0 mov r3, #0 herezy: djnz r2, herezy djnz r3, herezy mov a, sprite_pos_LSB
135
Appendix E MP3_r.h ;cjne a, max_sprite_pos_LSB, good_saeggi_luger ;mov a, sprite_pos_16 ;cjne a, max_sprite_pos_16, good_saeggi_luger ;jmp burn ;good_saeggi_luger: add a, #1 mov sprite_pos_LSB, a mov a, sprite_pos_16 addc a, #0 mov sprite_pos_16, a ;burn: mov r1, #current_pl_32 mov r0, #addr_1 mov r2, #4 lucky_charms: mov a, @r1 mov @r0, a inc r0 inc r1 djnz r2, lucky_charms jmp stage_3 ///////////////////////////////////////// Prev song prev_song: anl tmod, #11111110B orl tmod, #00000010B call send_cmd12 mov r2, #0 mov r3, #0 herezy2: djnz r2, herezy2 djnz r3, herezy2 mov a, sprite_pos_LSB clr c subb a, #1 mov sprite_pos_LSB, a mov a, sprite_pos_16 subb a, #0 ;jnc good saeggi ;mov sprite_pos_LSB, #0 ;mov a, #0 ;good_saeggi: mov sprite_pos_16, a mov r1, #current_pl_32 mov r0, #addr_1
136
Appendix E MP3_r.h mov r2, #4 lucky_charms_2: mov a, @r1 mov @r0, a inc r0 inc r1 djnz r2, lucky_charms_2 jmp stage_3 //////////////////////////////////// _PLAY_SONG _Play_song: ///////////////////////////// Assumes: // // {R3,R2} = begin of audio data corresponding to {emi0cn, r0} // {song_length_16,song_length_LSB} = song length in .1 ms // ////////////////////////////// ////////////////////////////// Results: // // call initialize_play push 02 clr tr2 mov th0, #HIGH(hz_200) mov tl0, #LOW(hz_200) mov r0, #30H mov @r0, song_length_LSB inc r0 mov @r0, song_length_16 mov r2, #2 div_4: clr c mov a, @r0 rrc a mov @r0, a dec r0 mov a, @r0 rrc a mov @r0, a inc r0 djnz r2, div_4
137
Appendix E MP3_r.h mov 32H, #21 orl psw, #00011000B call d16by8 anl psw, #11100111B mov temp1, 33H mov temp2, 34H mov 30H, temp2 mov 31H, temp1 ;;;;;;;;;;;;;;;;; number of .1s to increment time slider ;;;;;;;;;;;;;;;;; in {temp2, temp1} = {30H, 31H} mov a, song_length_LSB clr c rlc a mov PCA0CPL0, a mov a, song_length_16 rlc a mov PCA0CPH0, a mov PCA0CPM0, #49H mov PCA0H, #0 mov PCA0L, #0 mov pca0cn, #40H mov toggle, #2 mov toggle2, #10 ;;;;;;;;;;;;;;;;; Song ends at PCAC0 inter ;;;;;;;;;;;;;;;;; toggle counts 2 t0 isrs. 20 HZ/2 = 10 Hz ;;;;;;;;;;;;;;;;; toggle2 counts 10 t0 isrs. 10 HZ/10 = 1 Hz mov column_l, #0 mov column_h, #10H mov current_time_BCD1, #0 mov current_time_BCD2, #0 anl tmod, #11111101B orl tmod, #00000001B ; make t0 mode 1 anl ckcon, #11110111B ; make t0 /12 setb write_indef clr tf0 pop 02 setb tr0 setb cr setb tr2 ret #endif
138
Appendix F SDHC_r.h //////////////////////// Last modified March 26 //////////////////////////// //////////////////////// March 26 size: 817 bytes ////////////////////////////// #ifndef SDHC_r #define SDHC_r ORG 5000H
reset_sdhcz: sjmp $ /////////////////////// MAIN ROUTINE ////////////////// // // SDHC INITIALIZATION VIA C8051F020 // For use with SD Mode // // _SDHC_INITIALIZATION: anl p4, #11111011B mov r0, #0 mov r1, #0 mov r2, #10 shimmy: djnz r0, $ djnz r1, shimmy djnz r2, shimmy orl p4, #00000100B mov tmod, #12H mov th0, #Tim0 anl ie, #11111101B mov r2, #0 setb tr0 bleck: jnb tf0, $ cpl SCLK clr tf0 //clr ccf0 djnz r2, bleck clr tr0 setb SCLK call send_cmd0 cmd8: call send_cmd8
139
Appendix F SDHC_r.h jnb flag_CMD_fail, cmd55 clr flag_CMD_fail jmp cmd8 cmd55: mov r5, #0 mov r4, #0 not_initialized: djnz r5, not_timed_out djnz r4, not_timed_out jmp timed_out not_timed_out: mov rca_H, #0 mov rca_l, #0 mov crc, #65H call send_cmd55 check_status: // check for status: 00 00 01 20 mov a, 31H cjne a, #0, init_status_fail mov a, 32H cjne a, #0, init_status_fail mov a, 33H cjne a, #1, init_status_fail mov a, 34H cjne a, #20H, init_status_fail jmp acmd41 init_status_fail: jmp not_initialized acmd41: call send_acmd41 mov a, 31H jnb acc.7, not_initialized jmp cmd2 timed_out: sjmp $ cmd2: call send_cmd2 call send_cmd3 mov a, 33H cjne a, #05H, ident_status_fail mov a, 34H cjne a, #20H, ident_status_fail jmp ident_status_pass ident_status_fail: jmp _SDHC_INITIALIZATION ident_status_pass:
140
Appendix F SDHC_r.h mov RCA_H, 31H mov RCA_L, 32H ret ///////////////////// INITIALIZATION Routine //////////////////////// // // _SDHC_Transfer_ready _SDHC_TRANSFER_READY: mov r0, #RCA_H cjne @r0, #default_RCA_H, not_default_RCA inc r0 cjne @r0, #default_RCA_L, not_default_RCA jmp default_RCA not_default_RCA: sjmp $ default_RCA: call send_cmd9 mov a, 30H cjne a, #3FH, default_RCA call send_cmd7 acmd6: call send_acmd6 mov a, 32H cjne a, #0, acmd6 call send_cmd13 mov a, 33H cjne a, #09H, not_transmit_ready jmp transmit_ready not_transmit_ready: call reset_SDHCz transmit_ready: ret
////////////////// Sub Routine get_RSP //////////////////////// // // // Reads the CMD line on positive level of SCLK for R2/2 # of cycles // // get_RSP: ;;;;;;;;;;;;;;
141
Appendix F SDHC_r.h ;setb short_rsp ;;;;;;;;;;;;;; mov th0, #TIM0 anl ie, #11111101B setb tr0 mov r0, #30H mov r1, #8 mov r2, #CMD_FAIL_COUNT clr c clr a qwerty: mov r3, #2 mov c, CMD jnc a666 qwerty2: jnb tf0, $ clr tf0 cpl SCLK djnz r3, qwerty2 djnz r2, qwerty setb flag_CMD_fail clr short_rsp ret a666: rlc a jnb short_rsp, a789 mov r2, #6 jmp a789 a456: mov r1, #8 a123: mov r3, #2 mov c, CMD rlc a a789: jnb tf0, $ clr tf0 cpl SCLK djnz r3, a789 djnz r1, a123 mov @r0, a inc r0 djnz r2, a456 clr tr0 clr tf0 clr short_rsp
142
Appendix F SDHC_r.h ;;;;;;;;;;;;;; ;mov r0, #64 ;f_: ;cpl sclk ;djnz r0, f_ ;;;;;;;;;;;;;; ret ///////////////////// Sub Routine SEND_CMD ///////////////// // // // Assumes 6 byte CMD in 30-35H // // Sends data serially on CMD on positive level of SCLK // // SEND_CMD: orl psw, #00011000B mov r0, #2FH mov r3, #6 mov th0, #TIM0 anl ie, #11111101B setb tr0 ghi: inc r0 mov r2, #8 clr c mov a, @r0 def: mov r1, #2 rlc a mov CMD, c abc: jnb tf0, $ clr tf0 cpl SCLK djnz r1, abc djnz r2, def djnz r3, ghi clr tr0 clr tf0 anl psw, #11100111B ret
143
Appendix F SDHC_r.h ////////////////////
CMD0
send_cmd0: CMD0_5 EQU 040H CMD0_4 EQU 0 CMD0_3 EQU 0 CMD0_2 EQU 0 CMD0_1 EQU 0 CMD0_0 EQU 095H mov r0, #30H mov @r0, #CMD0_5 inc r0 mov @r0, #CMD0_4 inc r0 mov @r0, #CMD0_3 inc r0 mov @r0, #CMD0_2 inc r0 mov @r0, #CMD0_1 inc r0 mov @r0, #CMD0_0 call send_CMD ret ////////////////////// send_cmd2: CMD2_5 EQU 042H CMD2_4 EQU 0 CMD2_3 EQU 0 CMD2_2 EQU 0 CMD2_1 EQU 0 CMD2_0 EQU 04DH mov r0, #30H mov @r0, #CMD2_5 inc r0 mov @r0, #CMD2_4 inc r0 mov @r0, #CMD2_3 inc r0 mov @r0, #CMD2_2 inc r0 mov @r0, #CMD2_1 inc r0 mov @r0, #CMD2_0 call send_CMD
144
CMD2
Appendix F SDHC_r.h call get_RSP ret ////////////////////////////
CMD3
send_cmd3: CMD3_5 EQU 043H CMD3_4 EQU 0 CMD3_3 EQU 0 CMD3_2 EQU 0 CMD3_1 EQU 0 CMD3_0 EQU 021H mov r0, #30H mov @r0, #CMD3_5 inc r0 mov @r0, #CMD3_4 inc r0 mov @r0, #CMD3_3 inc r0 mov @r0, #CMD3_2 inc r0 mov @r0, #CMD3_1 inc r0 mov @r0, #CMD3_0 call send_CMD call get_RSP ret /////////////////////////// send_cmd7: CMD7_5 EQU 047H CMD7_4 EQU 0E6H CMD7_3 EQU 024H CMD7_2 EQU 0 CMD7_1 EQU 0 CMD7_0 EQU 0FFH mov r0, #30H mov @r0, #CMD7_5 inc r0 mov @r0, #CMD7_4 inc r0 mov @r0, #CMD7_3 inc r0 mov @r0, #CMD7_2 inc r0 mov @r0, #CMD7_1
145
CMD7
Appendix F SDHC_r.h inc r0 mov @r0, #CMD7_0 call send_CMD call get_RSP ret ///////////////////////
CMD8
send_cmd8: CMD8_5 EQU 048H CMD8_4 EQU 0 CMD8_3 EQU 0 CMD8_2 EQU 1 CMD8_1 EQU 0CDH CMD8_0 EQU 055H clr flag_CMD_fail mov r0, #30H mov @r0, #CMD8_5 inc r0 mov @r0, #CMD8_4 inc r0 mov @r0, #CMD8_3 inc r0 mov @r0, #CMD8_2 inc r0 mov @r0, #CMD8_1 inc r0 mov @r0, #CMD8_0 call send_CMD call get_RSP ret ////////////////////// send_cmd9: CMD9_5 EQU 049H CMD9_4 EQU 0E6H CMD9_3 EQU 024H CMD9_2 EQU 0 CMD9_1 EQU 0 CMD9_0 EQU 0D3H mov r0, #30H mov @r0, #CMD9_5 inc r0 mov @r0, #CMD9_4
146
CMD9
Appendix F SDHC_r.h inc r0 mov @r0, #CMD9_3 inc r0 mov @r0, #CMD9_2 inc r0 mov @r0, #CMD9_1 inc r0 mov @r0, #CMD9_0 call send_CMD call get_RSP ret //////////////////////////// send_cmd13: CMD13_5 EQU 04DH CMD13_4 EQU 0E6H CMD13_3 EQU 024H CMD13_2 EQU 0 CMD13_1 EQU 0 CMD13_0 EQU 071H mov r0, #30H mov @r0, #CMD13_5 inc r0 mov @r0, #CMD13_4 inc r0 mov @r0, #CMD13_3 inc r0 mov @r0, #CMD13_2 inc r0 mov @r0, #CMD13_1 inc r0 mov @r0, #CMD13_0 call send_CMD call get_RSP ret //////////////////////// CMD 12 send_CMD12: CMD12_5 EQU 4CH CMD12_4 EQU 0 CMD12_3 EQU 0 CMD12_2 EQU 0 CMD12_1 EQU 0 CMD12_0 EQU 61H clr CR
147
CMD 13
Appendix F SDHC_r.h mov r0, #30H mov @r0, #CMD12_5 inc r0 mov @r0, #CMD12_4 inc r0 mov @r0, #CMD12_3 inc r0 mov @r0, #CMD12_2 inc r0 mov @r0, #CMD12_1 inc r0 mov @r0, #CMD12_0 retry_12: setb short_rsp call send_CMD call get_RSP mov temp1, #0 mov temp2, #10H shurz: cpl sclk djnz temp1, shurz djnz temp2, shurz ret //////////////////////////// send_cmd17: CMD17_5 EQU 051H mov r0, #30H mov @r0, #CMD17_5 inc r0 mov @r0, addr_1 inc r0 mov @r0, addr_2 inc r0 mov @r0, addr_3 inc r0 mov @r0, addr_4 inc r0 mov @r0, CRC call send_CMD ;call get_rsp orl ie, #00000010B orl eie1, #00001000B mov th0, #tim_read mov tl0, #tim_read mov t0_stat, #0 mov PCA0CPH0, #HIGH(DATA_FAIL_COUNT)
148
CMD 17
Appendix F SDHC_r.h mov PCA0CPL0, #LOW(DATA_FAIL_COUNT) mov PCA0CPM0, #49H mov 18H, #0 mov 1AH, #0 mov 1BH, #2 mov toggle, #2 mov pca0cn, #40H setb tr0 ret ///////////////////// CMD18 send_cmd18: cmd18_5 equ 52H mov T0_STAT, #0 mov r0, #30H mov @r0, #CMD18_5 inc r0 mov @r0, addr_1 inc r0 mov @r0, addr_2 inc r0 mov @r0, addr_3 inc r0 mov @r0, addr_4 inc r0 mov @r0, CRC call send_CMD jnb check_rsp, next_18 call get_rsp next_18: clr check_rsp orl ie, #00000010B mov th0, #tim_read mov tl0, #tim_read mov PCA0CPH0, #HIGH(DATA_FAIL_COUNT) mov PCA0CPL0, #LOW(DATA_FAIL_COUNT) mov PCA0CPM0, #49H mov 18H, #0 mov 1AH, #0 mov 1BH, #2 mov toggle, #2 mov emi0cn, #0 mov t0_stat, #0 setb CR setb tr0 ret
149
Appendix F SDHC_r.h ///////////////////// send_cmd55:
CMD 55
CMD55_5 EQU 77H CMD55_2 EQU 0 CMD55_1 EQU 0 mov r0, #30H mov @r0, #CMD55_5 inc r0 mov @r0, RCA_H inc r0 mov @r0, RCA_L inc r0 mov @r0, #CMD55_2 inc r0 mov @r0, #CMD55_1 inc r0 mov @r0, CRC call send_CMD call get_RSP ret /////////////////////////////// ACMD6 send_acmd6: ACMD6_5 EQU 046H ACMD6_4 EQU 0 ACMD6_3 EQU 0 ACMD6_2 EQU 0 ACMD6_1 EQU 02H ACMD6_0 EQU 0CBH retry_cmd55: mov CRC, #19H call send_cmd55 mov a, 30H cjne a, #37H, retry_cmd55 mov r0, #30H mov @r0, #ACMD6_5 inc r0 mov @r0, #ACMD6_4 inc r0 mov @r0, #ACMD6_3 inc r0 mov @r0, #ACMD6_2 inc r0 mov @r0, #ACMD6_1 inc r0 mov @r0, #ACMD6_0
150
Appendix F SDHC_r.h call send_CMD call get_RSP ret
/////////////////
ACMD41
ACMD41_5 EQU 69H ACMD41_4 EQU 40H ACMD41_3 EQU 0FFH ACMD41_2 EQU 80H ACMD41_1 EQU 0 ACMD41_0 EQU 17H send_acmd41: mov r0, #30H mov @r0, #ACMD41_5 inc r0 mov @r0, #ACMD41_4 inc r0 mov @r0, #ACMD41_3 inc r0 mov @r0, #ACMD41_2 inc r0 mov @r0, #ACMD41_1 inc r0 mov @r0, #ACMD41_0 call send_CMD call get_RSP ret //////////////////////// CRC7 (plus stop bit) /////////////////// CRC7: // polynomial 10001001B + stop bit mov temp1, #40 mov temp2, #4 mov a, 30H mov r0, #31H mov @r0, addr_1 inc r0 mov @r0, addr_2 inc r0 mov @r0, addr_3 inc r0 mov @r0, addr_4
151
Appendix F SDHC_r.h clr c loop_CRC7: xch a, @r0 rlc a xch a, @r0 dec r0 djnz temp2, loop_CRC7 mov r0, #34H mov temp2, #4 next_CRC7: rlc a jnc not_c_crc7 cpl acc.4 cpl acc.1 not_c_crc7: clr c djnz temp1, loop_CRC7 clr c rrc a anl a, #7FH clr c rlc a inc a mov CRC, a ret /////////////////////////////// clear_64 // // 64 cpl sclks // clear_64: cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk
152
Appendix F SDHC_r.h cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk cpl sclk ret //////////////////////////// get_byte get_byte: cpl sclk cpl sclk
153
Appendix F SDHC_r.h mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 djnz r3, fin_gb djnz r2, fin_gb mov r2, #2 call clear_64 fin_gb: ret ////////////////////////////// tets_sdhc test_sdhc: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 movx @r0, a inc r0 call check_emi0cn djnz r5, test_sdhc ret #endif
154
Appendix G Math_r.h #ifndef math_r #define math_r ORG 2E000H ;26 Oct 00 added code to zero remainder when dividend is zero ;19 Dec 99 corrected comments, removed unnecessary instruction ;16 May 99 8051 source code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ;DIV32U is called to divide (unsigned) a 32-bit dividend using a ; 16-bit divisor. ; ;DIV32U solves for quotient and remainder the equation: ; ; dividend = divisor*quotient + remainder ; ;Call: ; r7,r6,r5,r4 = dividend ; r1,r0 = divisor ; lcall DIV32U ; ;Return: ; r5,r4 = quotient ; r7,r6 = remainder ; c flag set to 1 if overflow occured ; All registers, acc, b and two caller-assigned direct memory bytes ; (q0 and q1)have been changed. ; Data pointer has not been disturbed ; ;Note: ; (1)Overflow is a divide by zero or any value that will cause ; the quotient to be greater than 16 bits. ; (2)Most significant (ms) register always listed first when comma separates ; two in a comment. Example: r3,r2 (r3 contains the ms bits) ; (3) The algorithm used in this code borrows heavily from work posted ; by John C. Wren who said he got it from a C complier. ; ;Original author: John Veazey, Ridgecrest, CA, 18 APR 99 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DIV32_16U: ; ;Clear the working quotient ; clr a mov q1,a mov q0,a ; ;Clear the msb's of a 32-bit working divisor (r3,r2,r1,r0) ; mov r3,a
155
Appendix G Math_r.h mov r2,a ; ;b counts the number of places+1 the divisor was initially ; shifted left to align its ms bit set with the ms bit set ; in the dividend ; mov b,#1 ; ;Make an error return if trying to divide by zero ; mov a,r1 orl a,r0 jnz du100 ljmp du920 ;Make the error return ; ;Just return with quotient and remainder zero if dividend is zero ; du100: mov a,r7 orl a,r6 orl a,r5 orl a,r4 jnz du200 mov r7,a mov r6,a jmp du910 ;Make a normal return ; ;Align the msb set in the demoninator with the msb set in the ; numerator. Increment the shift count in b each time a shift left ; is performed. ; du200: mov a,r3 ;Stop if msb set clr c rlc a jc du600 subb a,r7 ;Compare r3 & r7, (c clear) jz du210 ; jump if r3=r7 jnc du600 ; jump if r3>r7 sjmp du240 ; r3
r6 jnz du240 ; jump if r2r5 jnz du240 ; jump if r1r4 du240:
156
Appendix G Math_r.h clr c ;Now shift the denominator mov a,r0 ; left 1 bit position rlc a mov r0,a mov a,r1 rlc a mov r1,a mov a,r2 rlc a mov r2,a mov a,r3 rlc a mov r3,a inc b ;Increment b counter and sjmp du200 ; continue
; ;Compare the shifted divisor with the remainder (what's ; left of the dividend) ; du600: mov a,r7 clr c subb a,r3 jc du720 ;jump if r3>r7 jnz du700 ;jump if r3r6 jnz du700 ;jump if r2r5 jnz du700 ;jump if r1r4 ; ;Divisor is equal or smaller, so subtract it off and ; get a 1 for the quotient ; du700: mov a,r4 clr c subb a,r0 mov r4,a mov a,r5 subb a,r1 mov r5,a mov a,r6 subb a,r2 mov r6,a mov a,r7 subb a,r3
157
Appendix G Math_r.h mov r7,a clr c cpl c ;Get a 1 for the quotient sjmp du730
; ;Divisor is greater, get a 0 for the quotient ; du720: clr c ; ;Shift 0 or 1 into quotient ; du730: mov a,q0 rlc a mov q0,a mov a,q1 rlc a mov q1,a jc du920 ;overflow - make the error return ; ;Now shift the denominator right 1, decrement the counter ; in b until b = 0 ; du740: clr c mov a,r3 rrc a mov r3,a mov a,r2 rrc a mov r2,a mov a,r1 rrc a mov r1,a mov a,r0 rrc a mov r0,a djnz b,du600 ; ;Move quotient and remainder ; mov a,r5 mov r7,a mov a,r4 mov r6,a mov a,q1 mov r5,a mov a,q0 mov r4,a ; ;Make the normal return ;
158
Appendix G Math_r.h du910: clr c ret ; ;Make the error return ; du920: clr c cpl c ret ;End of DIV32U ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;{r7,r6,r5,r4} = {r7,r6}*r0 mul16_8u: mov a, r6 mov b, r0 mul ab mov r4, a mov temp2, b mov a, r7 mov b, r0 mul ab add a, temp2 mov r5, a clr a add a, b mov r6, a mov r7, #0 ret
;***************************************************************************; ; ; ; D16BY8 ; ; CALCULATES QUOTIENT = DIVIDEND/DIVISOR ; ; REMAINDER = DIVIDEND - QUOTIENT * DIVISOR ; ; Inputs to this routine are a 16-bit dividend and an 8-bit divisor. ; Outputs are a 16-bit quotient and an 8-bit remainder. Inputs and ; outputs are unsigned integers. Accuracy of the calculation has been ; verified with all possible values of dividend and divisor. Running ; time varies from 145 to 276 usecs at 12MHz, the average being 232 usecs. ; ;
159
Appendix G Math_r.h ; INPUTS: DIVIDEND 2 bytes in externally defined DATA ; (low byte at DIVIDEND, high byte at DIVIDEND+1) ; ; DIVISOR 1 byte in externally defined DATA ; ; ; OUTPUTS: QUOTIENT 2 bytes in externally defined DATA ; ; REMAINDER 1 byte in externally defined DATA ; ; ; VARIABLES AND REGISTERS MODIFIED: ; ; QUOTIENT, REMAINDER ; ACC, B, PSW, R4, R5, R6, R7 ; ; ERROR EXIT: Exit with OV = 1 indicates DIVISOR = 0. ; ; ;***************************************************************************; Dividend data 30H Divisor data 32H Quotient data 33H Remainder data 35H D16BY8: CLR CJNE
A A,DIVISOR,OK
DIVIDE_BY_ZERO: SETB OV RET OK:
MOV MOV MOV MOV MOV
QUOTIENT,A R4,#8 R5,DIVIDEND R6,DIVIDEND+1 R7,A
MOV MOV DIV MOV MOV
A,R6 B,DIVISOR AB QUOTIENT+1,A R6,B
TIMES_TWO: MOV RLC MOV MOV RLC MOV MOV RLC
160
A,R5 A R5,A A,R6 A R6,A A,R7 A
Appendix G Math_r.h MOV COMPARE: CJNE MOV CJNE CJNE DONE: CPL
R7,A A,#0,DONE A,R6 A,DIVISOR,DONE R5,#0,DONE C
BUILD_QUOTIENT: MOV A,QUOTIENT RLC A MOV QUOTIENT,A JNB ACC.0,LOOP SUBTRACT: MOV SUBB MOV MOV SUBB MOV
A,R6 A,DIVISOR R6,A A,R7 A,#0 R7,A
LOOP:
DJNZ
R4,TIMES_TWO
MOV MOV MUL MOV MOV SUBB MOV CLR RET
A,DIVISOR B,QUOTIENT AB B,A A,DIVIDEND A,B REMAINDER,A OV
///////////////////////////// get song length get_song_length: orl psw, #00011000B mov r4, num_samples_LSB mov r5, num_samples_1 mov r6, num_samples_2 mov r7, num_samples_32 mov r1, sample_rate_16 mov r0, sample_rate_LSB call DIV32_16U mov temp3, r5 mov temp4, r4 mov r0, #10
161
Appendix G Math_r.h call MUL16_8U mov r1, sample_rate_16 mov r0, sample_rate_LSB call DIV32_16U mov song_length_16, r5 mov song_length_LSB, r4 mov r7, temp3 mov r6, temp4 mov r0, #10 call MUL16_8U mov a, r4 add a, song_length_LSB mov song_length_LSB, a mov a, r5 addc a, song_length_16 mov song_length_16, a anl psw, #11100111B ret // 16-bit signed x Z-bit signed // case 1: + times + // case 2: + times // case 3: - times + // case 4: - times // sample: // (sign) number // b'1 b'15 // times coefficient // (sign) number // b'1 b'(Z-1) // Algorithm: // 1. use lookup table to get masking factor for coefficient // 2. remove signs and xor signs for result sign // 3. take absolute value of both // 4. multiply absolute values // 5. convert to 32-bit signed // Assumes: {r2, r3} = abs 16-bit // {r6,r7} = abs 12-bit // predictor_order = Z // {r6,r7} = result // // r0 points to coefficient // r1 points to saving spot MU16_12:
162
Appendix G Math_r.h sjmp $ ret #endif
163
Appendix H WAV_r.h #ifndef wav_r #define wav_r ORG 0B000H ///////////////////////// wav play initialization ///////////////////// wav_play_initialization: clr a ;mov addr_1, a ;mov addr_2, a ;mov addr_3, a ;mov addr_4, a ;mov addr_1, a ;mov addr_2, #16H ;mov addr_3, #0D7H ;mov addr_4, #48H mov r0, #current_song_32 mov addr_1, @r0 inc r0 mov addr_2, @r0 inc r0 mov addr_3, @r0 inc r0 mov addr_4, @r0 mov 30H, #52H call crc7 call send_cmd18 clr tr0 mov t0_mode, #find_seq_18 ;;;;;;;;;;; ;mov 30H, #0 ;mov 1CH, #1 ;;;;;;;;;;; mov 30H, #'d' mov 31H, #'a' mov 32H, #'t' mov 33H, #'a' mov 1CH, #4 setb tr0 sharmys: mov a, 18H cjne a, #23H, sharmys jnb flag_sequence_found, $ mov r2, #16 mov th0, #0 clr cr
164
Appendix H WAV_r.h shaz: mov tl0, #0 setb tf0 nop nop nop nop clr tf0 inc pca0l djnz r2, shaz clr tr0 clr cr mov t0_mode, #read_blocks_18 mov tl2, #LOW(fs_44100) mov th2, #HIGH(fs_44100) mov rcap2l, #LOW(fs_44100) mov rcap2h, #HIGH(fs_44100) mov r2, #2 mov a, pca0h mov b, pca0l mov a, pca0h mov b, pca0l shum_charms: clr c rrc a xch a, b rrc a xch a, b djnz r2, shum_charms mov r2, a mov r3, b mov b, #high(200H) mov a, #low(200H) clr c subb a, r3 mov r3, a mov a, b subb a, r2 mov r2, a inc r2 clr a mov dac0l, a mov dac1l, a mov a, #80H mov dac0h, a mov dac0l, a
165
Appendix H WAV_r.h mov r0, 18H mov emi0cn, #0 setb tr2 ret ////////////////////////////////// riff_specs ////////////////// riff_specs: mov emi0cn, #ixram mov r0, #4 mov r1, #song_fin_4 mov r2, #4 loopy_singy_riff: movx a, @r0 mov @r1, a inc r0 dec r1 djnz r2, loopy_singy_riff mov r0, #12 mov temp1, r0 movx a, @r0 cjne a, #'f', riff_error inc r0 movx a, @r0 cjne a, #'m', riff_error inc r0 movx a, @r0 cjne a, #'t', riff_error inc r0 inc r0 call get_riff_chunk_size mov temp1, r0 movx a, @r0 cjne a, #1, riff_error inc r0 inc r0 movx a, @r0 mov channels, a inc r0 inc r0 movx a, @r0 mov sample_rate_LSB, a inc r0 movx a, @r0 mov sample_rate_16, a mov a, r0 add a, #9 mov r0, a movx a, @r0 mov sample_size, a
166
Appendix H WAV_r.h jmp cont_riff riff_error: jmp riff_error_T not_fact_block: cjne a, #'d', not_fact_block;#'f', riff_error inc r0 movx a, @r0 cjne a, #'a', riff_error;#'a', riff_error inc r0 movx a, @r0 cjne a, #'t', riff_error;#'c', riff_error inc r0 movx a, @r0 cjne a, #'a', riff_error;#'t', riff_error inc r0 mov temp1, r0 mov r1, #num_samples_LSB mov r2, #4 // get number of samples loopy_againy2: movx a, @r0 mov @r1, a inc r0 dec r1 djnz r2, loopy_againy2 // num_samples * byte size * channels ;; divide by channels (1 or 2) mov r2, channels mov r3, #4 nc_l: djnz r2, nc_lc jmp nc_c nc_lc: clr c mov r1, #num_samples_32 nc_ll: mov a, @r1 rrc a mov @r1, a inc r1 djnz r3, nc_ll jmp nc_l ;; divide by byte size (1 or 2) nc_c: mov r2, #4
167
Appendix H WAV_r.h mov a, sample_size bs_l: clr c rrc a djnz r2, bs_l inc a mov r2, a mov r3, #4 nc_l2: djnz r2, nc_lc2 jmp nc_c2 nc_lc2: clr c mov r1, #num_samples_32 nc_ll2: mov a, @r1 rrc a mov @r1, a inc r1 djnz r3, nc_ll2 jmp nc_l2 nc_c2: jmp saeggi_gotty cont_riff: mov a, temp1 add a, chunk_size_LSB mov r0, a movx a, @r0 cjne a, #'f', not_fact_block;#'f', riff_error inc r0 movx a, @r0 cjne a, #'a', riff_error;#'a', riff_error inc r0 movx a, @r0 cjne a, #'c', riff_error;#'c', riff_error inc r0 movx a, @r0 cjne a, #'t', riff_error;#'t', riff_error inc r0 call get_riff_chunk_size mov temp1, r0 mov r1, #num_samples_LSB mov r2, #4 // get number of samples loopy_againy: movx a, @r0 mov @r1, a
168
Appendix H WAV_r.h inc r0 dec r1 djnz r2, loopy_againy // calculate length of song // divide #samples/ fs saeggi_gotty: call get_song_length orl psw, #00011000B // calculate end sector of song // song_addr + (song size/ 512) mov r7, song_fin_1 mov r6, song_fin_2 mov r5, song_fin_3 mov r4, song_fin_4 mov r1, #HIGH 512 mov r0, #LOW 512 call DIV32_16U mov r1, #current_song_LSB mov a, @r1 add a, r4 mov song_fin_4, a dec r1 mov a, @r1 addc a, r5 mov song_fin_3, a dec r1 clr a addc a, @r1 mov song_fin_2, a dec r1 clr a addc a, @r1 mov song_fin_1, a clr c mov a, song_fin_4 subb a, #10H mov song_fin_4, a mov a, song_fin_3 subb a, #0 mov song_fin_3, a mov a, song_fin_2 subb a, #0 mov song_fin_2, a mov a, song_fin_1 subb a, #0 mov song_fin_1, a
169
Appendix H WAV_r.h anl psw, #11100111B ret riff_error_T: sjmp $ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ///////////////////////// Assumes r0 points at chunksize LSB get_riff_chunk_size: mov r1, #chunk_size_LSB mov r2, #4 loopy_sizey: movx a, @r0 mov @r1, a inc r0 dec r1 djnz r2, loopy_sizey ret ////////////////////// Decode riff // // big endian 16-bit pcm samples // //////////////////////////////////
decode_riff: cpl sclk mov a, sdhc anl a, #0F0H mov r7, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a rl a add a, r7 mov f0, c mov dac0l, a ;;;;; ;movx @r0, a ;inc r0 ;call check_emi0cn ;;;;; djnz r3, shurmys
170
Appendix H WAV_r.h djnz r2, shurmys ;anl dac0cn, #7FH mov r2, #2 mov r3, #64 shurmys_no: cpl sclk djnz r3, shurmys_no ;orl dac0cn, #80H shurmys: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r7, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a mov c, f0 addc a, r7 ;;;;; ;movx @r0, a ;;;;; ;clr c add a, #80H mov dac0h, a ;;;;; ;inc r0 ;call check_emi0cn ;;;;; djnz r3, shurmys2 djnz r2, shurmys2 ;anl dac0cn, #7FH mov r2, #2 mov r3, #64 shurmys_no2: cpl sclk djnz r3, shurmys_no2 ;orl dac0cn, #80H shurmys2: mov a, channels cjne a, #2, one_channel sjmp $ one_channel: mov dac1h, dac0h mov dac1l, dac0l ret
171
Appendix H WAV_r.h
#endif
172
Appendix I FLAC_r.h #ifndef flac_r #define flac_r ORG 0D000H
//////////////////////////////////// decode_flac_frame_header // // supports single channel, 16-bit flac format // serially extracts header data // // Arguments: ;;// r5 = current bit shift position // {r2,r3} = count+100H until CRC7 received from SDHC // r_0 = current offset (0,1, or 2) // test = current byte from SDHC (shifted) // temp1 = next byte from SDHC (shifted) // r_4 = next byte from SDHC (unshifted) // // Returns: // {r6,r7} = block size // {r4,temp4} = most current 2 bytes // channel_assign = channel assignment // frame_type0 = frame type // sample_16 = current sample // {emi, r0} = external memory decode storage address // {emi_backup, r1} = current sample to send to DAC0 // // Uses: // garbage = number of bit shifts to use // garbage2 in get_residual // temp1 in get_next_byte //////////////////////////////////////////////////////////////////// decode_flac_frame_header_serial:
setb flag_first_time ////////////////////////////////// ;mov r0, #test3 ;mov a, @r0 ;add a, #1 ;mov @r0, a ;dec r0 ;mov a, @r0 ;addc a, #0 ;mov @r0, a ;dec r0 ;mov a, @r0 ;addc a, #0
173
Appendix I FLAC_r.h ;mov @r0, a ;dec r0 ;mov a, @r0 ;addc a, #0 ;mov @r0, a ;mov r4, test ;mov a, test3 ;cjne a, #0a3H, splooz ;mov a, test2 ;cjne a, #1, splooz ;nop ;mov emi0cn, #0 ;mov r0, #0 ;push 5 ;push 4 ;mov r5, #0 ;call test_sdhc ;pop 4 ;pop 5 ;sjmp $ splooz: ///////////////////////////////// mov r4, test mov a, r_0 cjne a, #0, n0 jmp y0 n0: cjne a, #1, n1 jmp dfs1_f n1: cjne a, #2, n2 mov r5, temp4 cjne r4, #0FFH, err_dfs cjne r5, #0F8H, err_dfs mov r4, r_4 jmp dfs2 n2: sjmp $ y0: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a
174
Appendix I FLAC_r.h cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 mov temp4, a djnz r3, dfs1 djnz r2, dfs1 mov r2, #2 call clear_64 dfs1: dfs1_f: mov r5, temp4 cjne r4, #0FFH, err_dfs cjne r5, #0F8H, err_dfs jmp ok_dfs err_dfs: sjmp $ ok_dfs: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov r4, a djnz r3, dfs2 djnz r2, dfs2 mov r2, #2 call clear_64 dfs2: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5
175
Appendix I FLAC_r.h mov r5, a djnz r3, dfs3 djnz r2, dfs3 mov r2, #2 call clear_64 dfs3: dfs3_f: // get sample rate clr f0 mov a, r4 anl a, #00001100B cjne a, #00001100B, go_seller setb f0 // get frame size go_seller: mov a, r4 anl a, #80H cjne a, #80H, wtf jmp wtf? wtf: mov a, r4 anl a, #0F0H swap a clr c subb a, #2 mov b, a orl psw, #00011000B mov r2, #HIGH(576) mov a, #LOW(576) dfs4_l2: clr c rlc a xch a, r2 rlc a xch a, r2 djnz b, dfs4_l2 mov b, r2 anl psw, #11100111B mov r6, b mov r7, a inc r6 jmp wtfr wtf?: mov a, r4 anl a, #0F0H swap a
176
Appendix I FLAC_r.h clr c subb a, #8 mov b, a inc b setb c clr a dfs4_l: rlc a djnz b, dfs4_l mov r7, #0 mov r6, a inc r6 wtfr: mov a, r5 anl a, #0F0H swap a mov channel_assign, a // skip frame number cpl sclk cpl sclk mov a, sdhc anl a, #0f0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0f0H swap a add a, r4 djnz r3, dfs5 djnz r2, dfs5 mov r2, #2 call clear_64 dfs5: anl a, #0C0H cjne a, #0C0H, not_punk punk: cpl sclk cpl sclk mov a, sdhc anl a, #0f0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0f0H swap a
177
Appendix I FLAC_r.h add a, r4 djnz r3, dfs5z djnz r2, dfs5z mov r2, #2 call clear_64 dfs5z: // skip crc8 not_punk: cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dfs6 djnz r2, dfs6 mov r2, #2 call clear_64 dfs6: ;;;;;;;;;;;; // skip sampling rate jnb f0, your_moms call get_byte your_moms: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov r_0, a djnz r3, dfs7 djnz r2, dfs7 mov r2, #2 call clear_64 dfs7: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk
178
Appendix I FLAC_r.h cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 mov r_1, a ;mov garbage, temp1 djnz r3, dfs8 djnz r2, dfs8 mov r2, #2 call clear_64 dfs8: ;;;;;;;;;;;;;;;;;;; cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov r_2, a djnz r3, dfs9 djnz r2, dfs9 mov r2, #2 call clear_64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; STOP at r_2 dfs9: dfs10: dfs10_f: mov a, r_0 anl a, #01111110B rr a mov frame_type0, a cjne a, #subframe_constant, sf_v jmp fart sf_v: cjne a, #subframe_verbatim, sf_f sjmp $ sf_f: anl a, #11111000B
179
Appendix I FLAC_r.h cjne a, #8, $ mov a, frame_type0 anl a, #00000111B mov predictor_order, a jmp saeggi_shiggy ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lpc frame type sf_l: call sf_lj
//////////////////////////////// flac play initialization flac_play_initialization: mov emi0cn, temp1 setb tr0 jnb flag_sequence_found, $ clr tr0 call get_song_length mov r2, #2 mov a, pca0h mov b, pca0l mov a, pca0h mov b, pca0l shum_charms2: clr c rrc a xch a, b rrc a xch a, b djnz r2, shum_charms2 mov r2, a mov r3, b mov b, #high(200H) mov a, #low(200H) clr c subb a, r3 mov r3, a mov a, b subb a, r2 mov r2, a inc r2 mov r_0, #1 mov r5, #8 mov test, #0FFH mov temp4, #0F8H
180
Appendix I FLAC_r.h call decode_flac_frame_header_serial mov track_pos, predictor_order dec track_pos mov tl2, #LOW(fs_44100) mov th2, #HIGH(fs_44100) mov rcap2l, #LOW(fs_44100) mov rcap2h, #HIGH(fs_44100) clr a mov r0, a mov r1, a mov emi0cn, a mov emi_backup, a mov emi, a mov emi0cn_max, #0C0H mov emi0cn_max2, #60H ret
saeggi_shiggy: jnz blark mov r4, r_2 ;;;;;;;;;;;;;;;;;;; ;mov backup1, r_3 mov r_3, r_1 ;;;;;;;;;;;;;;;;;;; jmp shiz_f blark: mov a, predictor_order cjne a, #4, suz //////////////////////////// ;mov emi0cn, #0EH ;mov r1, #0 ;mov a, r_2 ;movx @r1, a ;mov dac0l, a ;mov a, r_1 ;inc r1 ;movx @r1, a ;inc r1 ;add a, #80H ;mov dac0h, a //////////////////////////// mov r1, #18H mov @r1, r_2 mov dac0l, @r1 inc r1 mov @r1, r_1 mov a, #80h
181
Appendix I FLAC_r.h add a, @r1 mov dac0h, a inc r1 //////////////////////////// ;call get_byte ;mov r5, a ;call get_byte ;movx @r1, a ;inc r1 ;mov a, r5 ;movx @r1, a ;inc r1 //////////////////////////// call get_byte inc r1 mov @r1, a dec r1 call get_byte mov @r1, a inc r1 inc r1 inc r1 ////////////////////////////// ;call get_byte ;mov r5, a ;call get_byte ////////////////////////////// ;movx @r1, a ;inc r1 ////////////////////////////// ;mov a, r5 ////////////////////////////// ;movx @r1, a ;inc r1 ////////////////////////////// call get_byte mov @r1, a dec r1 call get_byte mov @r1, a inc r1 inc r1 ///////////////////////////// ;call get_byte ;mov r5, a ;call get_byte ;movx @r1, a ;inc r1 ;mov a, r5 ;movx @r1, a
182
Appendix I FLAC_r.h ;inc r1 ///////////////////////////// call get_byte mov @r1, a call get_byte dec r1 mov @r1, a call get_byte mov r_3, a jmp shiz_f suz: ////////////////////////// mov a, test3 cjne a, #13H, splooze nop splooze: ////////////////////////// mov garbage, predictor_order ///////////////////////////// ;mov emi0cn, #0EH ;mov r1, #0 ;mov a, r_2 ;movx @r1, a ;mov dac0l, a ;mov a, r_1 ;inc r1 ;movx @r1, a ;add a, #80H ;mov dac0h, a ///////////////////////////// mov r1, #18H mov @r1, r_2 mov dac0l, @r1 inc r1 mov @r1, r_1 mov a, #80h add a, @r1 mov dac0h, a djnz garbage, shiznit call get_byte mov r_3, a jmp shiz_f shiznit: ;mov a, r_3 ;inc r1 ;movx @r1, a
183
Appendix I FLAC_r.h cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov test4, a djnz r3, s1 djnz r2, s1 mov r2, #2 call clear_64 s1: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 inc r1 ///////////////////////////// ;movx @r1, a ///////////////////////////// mov @r1, a ///////////////////////////// mov r_4, a mov a, test4 ///////////////////////////// inc r1 ///////////////////////////// ;movx @r1, a ///////////////////////////// mov @r1, test4 djnz r3, s4 djnz r2, s4 mov r2, #2 call clear_64 s4:
184
Appendix I FLAC_r.h /////////////////////////////////////// fpies ;sjmp $ djnz garbage, s1_c jmp s1_f ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; s1_c: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov test4, a djnz r3, s2 djnz r2, s2 mov r2, #2 call clear_64 s2: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 inc r1 ///////////////////////////// ;movx @r1, a ///////////////////////////// mov @r1, a inc r1 ///////////////////////////// ;mov a, test4 ;movx @r1, a ///////////////////////////// mov @r1, test4 djnz r3, s3
185
Appendix I FLAC_r.h djnz r2, s3 mov r2, #2 call clear_64 s3: jmp s1 s1_f: mov a, predictor_order cjne a, #3, bloop mov r_3, r_4 jmp s5 bloop: cjne a, #4, bloopy sjmp $ bloopy: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov r_3, a djnz r3, s5 djnz r2, s5 mov r2, #2 call clear_64 s5: shiz_f: mov a, r_0 anl a, #1 cjne a, #1, sell_me ;;;;;;;;;;;;;;;;;;; clr c mov a, r_3 rlc a ///////////////////////////// ;jnc $ ///////////////////////////// mov a, r_3 anl a, #01100000B rl a
186
Appendix I FLAC_r.h rl a rl a mov rice_encoding, a mov a, r_3 anl a, #00011110B rr a mov partition_order, a mov a, predictor_order ///////////////////////////// ;jnz $ ///////////////////////////// mov a, rice_encoding ///////////////////////////// ;jnz $ ///////////////////////////// mov a, r_3 anl a, #00000001B rl a rl a rl a mov b, a mov a, r4 anl a, #11100000B rl a rl a rl a add a, b mov rice_parameter, a call get_partition_info mov a, r4 mov r5, #3 shizzy82: rl a djnz r5, shizzy82 mov r4, a mov r5, #5 mov a, predictor_order cjne a, #0, fin_mer call get_res mov dac0l, a mov a, b add a, #80H mov dac0h, a mov a, r7 clr c subb a, #1 mov r7, a jnz fr
187
Appendix I FLAC_r.h dec r6 fin_mer: jmp fin_me sell_me: mov a, r_3 anl a, #11000000B rl a rl a mov rice_encoding, a mov a, r_3 anl a, #00111110B rr a mov partition_order, a mov a, r_3 anl a, #00111100B rr a rr a mov partition_order, a cx: mov a, predictor_order jnz cxx jmp cx1 cxx: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov r4, a djnz r3, cx1 djnz r2, cx1 mov r2, #2 call clear_64 cx1: ;mov a, /////////////////////// continue fixing here: mov a, rice_encoding jnz code_2 mov a, r_3 anl a, #00000011B rl a rl a
188
Appendix I FLAC_r.h mov b, a mov a, r4 anl a, #11000000B rl a rl a add a, b mov rice_parameter, a call get_partition_info mov a, r4 mov r5, #2 shizzy2: rl a djnz r5, shizzy2 mov r4, a mov r5, #6 mov a, predictor_order cjne a, #0, fin_me call get_res mov dac0l, a mov a, b add a, #80H mov dac0h, a mov a, r7 clr c subb a, #1 mov r7, a jnz fr dec r6 fr: fin_me: clr a mov emi_backup, a mov r1, a ret code_2: mov a, r_3 anl a, #00000011B rl a rl a rl a mov b, a mov a, r4 anl a, #11100000B rl a rl a rl a add a, b mov rice_parameter, a call get_partition_info mov a, r4 mov r5, #3
189
Appendix I FLAC_r.h shizzy: rl a djnz r5, shizzy mov r4, a mov r5, #5 mov a, predictor_order cjne a, #0, fin_me2 call get_res fin_me2: ret ////////////////////////////// // // calculate partition length mov r4, a clr a mov r0, a mov r1_backup, a mov r1, a mov a, predictor_order jnz shizniz call get_res shizniz: call get_partition_info sjmp $ ret fart: mov a, r_1 add a, #80H mov dac0h, a mov dac0l, r_2 cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dfsa2 djnz r2, dfsa2 mov r2, #2 call clear_64 dfsa2: cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dfsa1
190
Appendix I FLAC_r.h djnz r2, dfsa1 mov r2, #2 call clear_64 dfsa1: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;; cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 mov r4, a djnz r3, d0 djnz r2, d0 mov r2, #2 call clear_64 d0: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 mov r5, a djnz r3, d1 djnz r2, d1 mov r2, #2 call clear_64 d1: ;;;;;;;;;;;;;;;;;;; cpl sclk cpl sclk mov a, sdhc anl a, #0F0H
191
Appendix I FLAC_r.h mov r_4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r_4 mov r_4, a mov r_0, a djnz r3, d2 djnz r2, d2 mov r2, #2 call clear_64 d2: d3_f: mov test, r4 mov temp4, r5 mov r_0, #2 mov a, #8 clr c dec temp1 subb a, temp1 mov r5, a ret /////////////////////////////// get_res get_res: spooge: clr c mov a, #8 mov b, #0 subb a, rice_parameter jnc fool nop fool: mov res, #0 ;mov garbage2, #0 cont_get_res: djnz r5, contin_f23 call get_next_byte contin_f23: mov a, r4 rlc a mov r4, a jc fin_res inc res jmp cont_get_res
192
Appendix I FLAC_r.h fin_res: mov garbage, rice_parameter inc garbage fin_res_l: djnz garbage, fin_r_c jmp fin_r_f fin_r_c: djnz r5, contin_f24 call get_next_byte contin_f24: mov a, r4 rlc a mov r4, a mov a, res rlc a mov res, a mov a, b rlc a mov b, a ;mov a, res ;clr c ;rlc a ;mov res, a jmp fin_res_l fin_r_f: ;mov a, res ;add a, garbage2 ;mov b, #0 mov a, res clr c xch a, b rrc a xch a, b rrc a jnc not_c_fin add a, #1 xch a, b addc a, #0 xch a, b cpl a add a, #1 xch a, b cpl a addc a, #0 xch a, b ;mov b, #0FFH not_c_fin:
193
Appendix I FLAC_r.h ret ///////////////////////// flac specs flac_specs: inc r0 inc r0 mov r1, #block_size_24 mov r2, #3 shim: movx a, @r0 mov @r1, a inc r0 inc r1 djnz r2, shim mov a, r0 add a, #10 mov r0, a movx a, @r0 anl a, #0FH swap a mov b, a inc r0 movx a, @r0 mov r2, a swap a anl a, #0FH add a, b mov sample_rate_16, a mov a, r2 anl a, #0FH swap a mov b, a inc r0 movx a, @r0 mov r2, a swap a anl a, #0FH add a, b mov sample_rate_LSB, a mov a, r2 anl a, #0FH mov channels, a inc r0 inc r0 mov sample_size, #16 mov r1, #num_samples_32 mov r2, #4
194
Appendix I FLAC_r.h fum: movx a, @r0 mov @r1, a inc r0 inc r1 djnz r2, fum ret
/* get_next_byte: mov res, #0 djnz r5, contin_f23 mov r5, #8 contin_f23: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov temp1, a anl a, #0FH cpl sclk cpl sclk djnz r3, dec_f23a djnz r2, dec_f23a mov r2, #2 call clear_64 dec_f23a: mov a, sdhc anl a, #0F0H swap a add a, temp1 rrc a mov f0, c anl r4, #0F0H add a, r4 mov c, f0 */ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; constant_sample0 constant_sample0: cpl sclk cpl sclk
195
Appendix I FLAC_r.h mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 add a, #80H ;;;;;;;;;;;; mov r0, a ;;;;;;;;;;;; ;mov dac0h, a djnz r3, dec_f7 djnz r2, dec_f7 mov r2, #2 call clear_64 dec_f7: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk djnz r3, dec_f8 djnz r2, dec_f8 mov r2, #2 call clear_64 dec_f8: mov a, sdhc anl a, #0F0H swap a push acc add a, r5 mov r1, a pop acc ;;;;;;;;;;;; rl a ;;;;;;;;;;;; add a, r5 mov dac0l, a ;;;;;;;;;;;; mov a, r0 addc a, #0 mov dac0h, a ;;;;;;;;;;;; cpl sclk
196
Appendix I FLAC_r.h cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 mov frame_type1, a djnz r3, dec_f9 djnz r2, dec_f9 mov r2, #2 call clear_64 dec_f9: jmp subframe_type_1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; constant sample1 constant_sample1: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 add a, #80H mov dac1h, a djnz r3, dec_f10 djnz r2, dec_f10 mov r2, #2 call clear_64 dec_f10: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 mov dac1l, a djnz r3, dec_f11
197
Appendix I FLAC_r.h djnz r2, dec_f11 mov r2, #2 call clear_64 dec_f11: cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dec_f12 djnz r2, dec_f12 mov r2, #2 call clear_64 dec_f12: cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dec_f13 djnz r2, dec_f13 mov r2, #2 call clear_64 dec_f13: cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dec_f14 djnz r2, dec_f14 mov r2, #2 call clear_64 dec_f14: cpl sclk cpl sclk cpl sclk cpl sclk djnz r3, dec_f15 djnz r2, dec_f15 mov r2, #2 call clear_64 dec_f15: jmp fin_subframe
///////////////////////////////////// get_next_byte
198
Appendix I FLAC_r.h get_next_byte: mov r5, #8 cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov temp1, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, temp1 ;;;;;;;;;;;;;;;; ;mov f0, c ;mov temp5, a ;mov a, emi0cn ;cjne a, #4, testes ;push emi0cn ;mov emi0cn, #0DH ;mov a, temp5 ;movx @r1, a ;pop emi0cn ;testes: ;mov a, temp5 ;mov c, f0 ;;;;;;;;;;;;;;;; rrc a mov f0, c mov temp1, a mov a, r4 anl a, #080H add a, temp1 mov c, f0 mov r4, a ;mov temp1, a djnz r3, dec_f23a djnz r2, dec_f23a mov r2, #2 call clear_64 dec_f23a: ret
/////////////////////////////////////// get coefficient // // argument: 30H is current byte (shifted), 32H is bit offset (first time), 33H is pr%8 // uses: precision, r0, 33H // returns: 30H last byte used (shifted), 31H bit offset,
199
Appendix I FLAC_r.h // coefficient in xram, modified 31H // /////////////////////////////////////////////////////// get_coefficient: mov 34H, #0 mov 35H, #0 mov 36H, 32H inc 36H mov 37H, precision jnb flag_first_time, gc_nf ////// shift first byte gcl: djnz 36H, gcl_c jmp gcl_f gcl_c: mov a, 30H clr c rlc a mov 30H, a jmp gcl gc_nf: mov a, 37H clr c subb a, 32H mov 37H, a jmp gc2 gcl_f: mov a, 32H cpl a setb c addc a, #8 mov 36H, a mov a, 37H clr c subb a, 36H jnc gc2_a mov 36H, 37H inc 36H mov 37H, #0FFH jmp gc2 gc2_a: mov 37H, a inc 36H gc2: djnz 36H, gc2_c jmp gc2_f
200
Appendix I FLAC_r.h gc2_c: clr c mov a, 30H rlc a mov 30H, a mov a, 35H rlc a mov 35H, a mov a, 34H rlc a mov 34H, a jmp gc2 gc2_f: mov a, 37H cjne a, #0FFH, f? mov a, 34H movx @r0, a inc r0 mov a, 35H movx @r0, a inc r0 setb flag_first_time ret ;;;;;;;;;; get next byte f?: jbc flag_first_time, f?_f call get_byte clr flag_first_time mov 31H, a f?_f: mov 30H, 31H mov a, #8 clr c subb a, 37H jnc f?? mov a, 37H clr c subb a, #8 mov 37H, a mov 36H, #9 jmp gc2 f??: mov 36H, 37H mov 37H, #0FFH mov a, #8 clr c subb a, 36H inc 36H mov 32H, a jmp gc2
201
Appendix I FLAC_r.h ;;; find out if whole next byte is needed sjmp $ ;;;;;;;;;;;;;;;;;; mov a, 32H add a, 33H mov b, #8 div ab mov 32H, b mov 36H, b inc 36H jmp gcl_f mov 36H, 32H inc 36H sjmp $ fin_gc: ret /////////////////////////////// get_par get_par: mov garbage2, #4 mov a, rice_encoding jz screwy mov garbage2, #5 screwy: mov b, #0 cont_get_par: djnz r5, contin_f23z call get_next_byte contin_f23z: mov a, r4 rlc a mov r4, a xch a, b rlc a xch a, b djnz garbage2, cont_get_par mov a, b cjne a, rice_parameter, testyz ret testyz: mov rice_parameter, a ret //////////////////////////////////////// get partition info // // assumes: block size = {r6-1, r7}
202
Appendix I FLAC_r.h get_partition_info: ;mov frame_size_16, r6 ;dec frame_size_16 ;mov frame_size_LSB, r7 mov partition_size_16, r6 dec partition_size_16 mov partition_size_LSB, r7 mov a, #7 subb a, partition_order jnc noh_f // if partition_order > 7 oh_f: mov a, #15 subb a, partition_order jc $ mov 30H, r7 mov 31H, r6 mov 32H, partition_order inc 32H orl psw, #00011000B mov partition_count, 32H anl psw, #11100111B call d16by8 mov r7, 33H mov r6, 34H mov partition_size_lsb, r7 mov partition_size_16, r6 jmp sloop noh_f: mov garbage, partition_order inc garbage mov a, #1 gpi_l: djnz garbage, gpi_c jmp gpi_f gpi_c: clr c rlc a clr c xch a, partition_size_16 rrc a xch a, partition_size_16 xch a, partition_size_LSB rrc a xch a, partition_size_LSB jmp gpi_l gpi_f: mov partition_count, a
203
Appendix I FLAC_r.h mov a, partition_size_LSB clr c subb a, predictor_order mov r7, a mov a, partition_size_16 subb a, #0 mov r6, a ;;;;;;;;;; handle off by one errors in msb sloop: mov a, r7 cjne a, #0, nx jmp nx_c nx: inc r6 nx_c: mov a, partition_size_LSB cjne a, #0, ny jmp ny_c ny: inc partition_size_16 ny_c: ret
////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ret
#endif
204
Appendix J LPC_r.h #ifndef lpc_r #define lpc_r
continu: sjmp $ orl psw, #00011000B clr flag_sign clr f0 mov r0, backup1 mov r1, r1_backup // sample addr is in r0 // mul result addr is in r1 // register bank 3 //mov a, r0 //inc a //inc a //rr a //mov r2, a //mov a, predictor_order //clr c //subb a, r2 //inc a //mov temp4, a // number of results to calculate in temp4 movx a, @r0 add a, #80H mov dac0h, a add a, #80H inc r0 jnb acc.7, sam_p setb flag_sign cpl a jmp sam_n sam_p: anl a, #07FH sam_n: mov r2, a // abs(sample_H) is in r2 // sign(sample) is in flag_sign, f0 movx a, @r0 mov dac0l, a inc r0 //mov backup1, a jnb flag_sign, sam_p2 cpl a add a, #1 mov r3, a clr a
205
Appendix J LPC_r.h addc a, r2 mov r2, a jmp sam_n2 sam_p2: mov r3, a sam_n2: mov r0, backup2 inc emi0cn // abs(sample) is in {r2,r3} // co addr is in r0 ;; 12 bit precision: sell_you: mov a, precision cjne a, #12, $ mov r4, #7 mov r5, #8 jmp abs_co // sign mask is in r5 // abs mask is in r4 abs_co: movx a, @r0 inc r0 mov r6, a anl a, r5 // co sign is in a // co_H is in r6 jz co_p setb f0 mov a, r6 cpl a anl a, r4 mov r6, a co_p: co_n: // abs(co_h) is in r6 // sign(co) is in f0 movx a, @r0 inc r0 jnb f0, co_p2 cpl a add a, #1 mov r7, a clr a addc a, r6 mov r6, a jmp co_n2 co_p2: mov r7, a co_n2:
206
Appendix J LPC_r.h // abs(co) is in {r6,r7} mov a, r7 mov b, r3 mul ab mov r4, b mov r_3, a mov a, r7 mov b, r2 mul ab add a, r4 mov r_2, a clr a addc a, b mov r_1, a mov a, r6 mov b, r3 mul ab add a, r_2 mov r_2, a clr a addc a, b mov r4, a mov a, r6 mov b, r2 mul ab add a, r4 mov r5, a mov a, b addc a, #0 mov r4, a mov a, r5 add a, r_1 mov r5, a clr a addc a, r4 mov r4, a mov r7, r_3 mov r6, r_2 // abs(co)*abs(sam) is in {r4,r5,r6,r7} mov emi0cn, emi_backup jnb flag_sign, sam_p3 cpl f0 sam_p3: jnb f0, re_p mov a, r7 cpl a add a, #1 ;mov r7, a ;;;;;;;;;;;;;
207
Appendix J LPC_r.h movx @r1, a inc r1 ;;;;;;;;;;;;; mov a, r6 cpl a addc a, #0 ;mov r6, a mov f0, c movx @r1, a inc r1 cjne r1, #0, sell_this2 inc emi0cn sell_this2: mov c, f0 mov a, r5 cpl a addc a, #0 ;mov r5, a movx @r1, a inc r1 mov a, r4 cpl a addc a, #0 ;mov r4, a movx @r1, a inc r1 cjne r1, #0, sell_this4 inc emi0cn sell_this4: re_p: // 28-bit signed result is in {r4,r5,r6,r7} ;mov emi0cn, emi_backup ;mov a, r7 ;movx @r1, a ;inc r1 ;;cjne r1, #0, sell_this ;;inc emi0cn ;;sell_this: ;mov a, r6 ;movx @r1, a ;inc r1 ;cjne r1, #0, sell_this2 ;inc emi0cn ;sell_this2: ;mov a, r5 ;movx @r1, a ;inc r1 ;cjne r1, #0, sell_this3 ;inc emi0cn ;sell_this3: ;mov a, r4 ;movx @r1, a
208
Appendix J LPC_r.h ;inc r1 ;cjne r1, #0, sell_this4 ;inc emi0cn ;sell_this4: mov a, r0 cjne a, r1_max, sell_you2 jmp sell_you3 sell_you2: mov emi_backup, emi0cn jmp sell_you // 28-bit signed result is in {emi0cn,r1} sell_you3: mov a, backup2 cjne a, #0, sell clr flag_first_time mov r1_backup, a mov squish2, predictor_order inc squish2 mov emi_backup, a jmp fin_isr2_flac sell: clr c subb a, #2 mov backup2, a mov a, squish1 add a, r1_backup mov r1_backup, a clr a addc a, emi0cn mov emi_backup, emi0cn anl psw, #11100111B jmp fin_isr2_flac
isr2_lpc: sjmp $ ;;;;;;;;;;;;;;;;;;;;; Example: ;; ;; order = [1,64] ;; limit order max = 16 ;; ;; n = [0, order-1] ;; sn = sn ;; sn+1 = s0*cn + s1*cn-1 + s2*cn-2 +... sn*c0 ;; sn+2 = s1*cn + s2*cn-2... sn+1*c0 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
209
Appendix J LPC_r.h ;;;;;;;;;;;;;;;;;;;;; Algorithm: ;; ;; store results BIG ENDIAN ;; ;; can work in 0x00-0xdff ;; ;; get s0 stored in 0xe00 ;; multiply s0 by cn ;; store results in: 0x00-0x0(4*n) ;; ;; get s1 stored in 0xe01 ;; multiply s1 by cn-1, cn ;; store results in: 0x0(4*n)-0x0(8*n) ;; ;; get s2 stored in 0xe02 ;; multiply s2 by cn-2,cn-1,cn ;; store results in: 0x0(8*n)-0x(12*n) ;; ;; ............... ;; ;; get sn stored in 0xe0n ;; multiply sn by all c ;; store results in 0x0(4*n^2)-0x(5*n^2) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; calculate sn+1 and store in 0xe(n+1) ;; multiply sn by all c ;; store results in: 0x000-0x0(4*n) over s0's results ;; ;; use: 2*predictor_order^2 bytes of memory ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;; variables ;;;;;;;;;;; ;; ;; ;; ;; squish1 = 4*predictor order ;; temp4 ;; register bank 0 ;; backup1 = r0 ;; backup2 = r1 ;; r_0 - r_4 : for 32-bit calculations ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; jnb flag_first_time, asdf0 mov emi0cn, #0EH ;;mov r0, backup1
210
Appendix J LPC_r.h ;;mov r1, backup2 jmp continu asdf0: jmp asdf ;; backup1 = r0 = current offset to retrieve from asdf: orl psw, #00011000B clr a mov emi0cn, emi_backup mov r7, a mov r6, a mov r5, a mov r4, a mov r2, #4 mov r1, predictor_order pie_on_your_face: mov r0, backup1 movx a, @r0 inc r0 add a, r7 mov r7, a movx a, @r0 inc r0 addc a, r6 mov r6, a cjne r0, #0, pie inc emi0cn pie: movx a, @r0 inc r0 addc a, r5 mov r5, a movx a, @r0 addc a, r4 mov r4, a cjne r0, #0, pie2 inc emi0cn pie2: djnz r1, pie_on_your_face2 jmp sell_your_couch_joker pie_on_your_face2: djnz squish2, pie_on_your_sell sjmp $ pie_on_your_sell: mov r2, #4 mov a, squish1 add a, r2 add a, backup1
211
Appendix J LPC_r.h mov backup1, a jnc sell_pie inc emi0cn sell_pie: jmp pie_on_your_face sell_your_couch_joker: mov a, co_shift cjne a, #12, fartsy mov a, r4 anl a, #0FH swap a mov r4, a mov a, r5 anl a, #0F0H swap a add a, r4 mov r4, a mov a, r5 anl a, #0FH swap a mov r5, a mov a, r6 anl a, #0F0H swap a add a, r5 mov r3, a mov a, r4 mov r2, a sjmp $ jmp a_c ;; {r4,r5} = shifted sum fartsy: cjne a, #10, $ clr c mov a, r6 rlc a mov r6, a mov a, r5 rlc a mov r5, a mov a, r4 rlc a mov r4, a clr a rlc a mov r3, a clr c mov a, r6 rlc a mov r6, a mov a, r5
212
Appendix J LPC_r.h rlc a mov r5, a mov a, r4 rlc a mov r4, a mov a, r3 rlc a mov r3, a mov a, r3 jnz $ mov a, r5 mov r3, a mov a, r4 mov r2, a jmp a_c a_c: anl psw, #11100111B call get_res orl psw, #00011000B add a, r3 mov r3, a mov a, b addc a, r6 mov r2, a sjmp $ anl psw, #11100111B ;;mov r1, backup2 //cjne r0 sjmp $ sf_unknown: sjmp $
sf_lj: sjmp $ mov a, frame_type0 anl a, #11100000B cjne a, #20H, sf_unknown mov a, frame_type0 anl a, #00011111B inc a mov predictor_order, a mov a, predictor_order cjne a, #28, huh? huh?: jnc $ clr c
213
Appendix J LPC_r.h rlc a mov garbage2, a mov emi0cn, #0EH mov r1, #0 mov a, r_1 movx @r1, a djnz garbage2, nz_g doney_predictey_y: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r4 djnz r3, sf_a djnz r2, sf_a mov r2, #2 call clear_64 sf_a: inc r1 mov emi0cn, #0CH movx @r1, a mov emi0cn, #0EH jmp doney_predictey_z nz_g: inc r1 mov a, r_2 movx @r1, a ;djnz garbage2, nz_l ;jmp doney_predictey_y ;nz_g2: ;;;;;;;;;;;;;; retreive remaining warm up samples ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;mov r5, #00 ;mov r0, #0 ;mov emi0cn, #0 ;call test_SDHC ;sjmp $ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; inc garbage2
214
Appendix J LPC_r.h ;inc r1 ;mov a, backup1 ;movx @r1, a djnz garbage2, nz_l jmp doney_predictey nz_l: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov r4, a cpl sclk cpl sclk jmp fart1 ;djnz r3, fart1 ;djnz r2, fart1 ;mov r2, #2 ;call clear_64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;mov r5, #00 ;mov r0, #0 ;mov emi0cn, #0 ;call test_SDHC ;sjmp $ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fart1: mov a, sdhc anl a, #0F0H swap a add a, r4 inc r1 movx @r1, a djnz r3, nz1 djnz r2, nz1 mov r2, #2 call clear_64 nz1: djnz garbage2, nz_l doney_predictey: dp_lf: doney_predictey_z: movx a, @r1 mov r4, a cpl sclk cpl sclk mov a, sdhc
215
Appendix J LPC_r.h anl a, #0F0H mov r5, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, r5 mov r5, a djnz r3, fart2 djnz r2, fart2 mov r2, #2 call clear_64 fart2: cpl sclk cpl sclk mov a, sdhc anl a, #0F0H mov backup1, a cpl sclk cpl sclk mov a, sdhc anl a, #0F0H swap a add a, backup1 mov backup1, a djnz r3, fart3 djnz r2, fart3 mov r2, #2 call clear_64 fart3: no_gl: mov a, r4 anl a, #0F0H swap a cjne a, #00001111B, gl_c sjmp $ gl_c: inc a mov precision, a mov a, r4 anl a, #0FH rl a mov r4, a mov a, r5 anl a, #80H rl a add a, r4
216
Appendix J LPC_r.h mov co_shift, a ;; get coefficients mov emi0cn, #0FH ;mov r0, 1 mov r0, #0 mov a, precision mov b, #8 div ab mov 33H, b mov 30H, r5 mov 31H, backup1 mov 32H, #1 setb flag_first_time mov r5, predictor_order get_co: call get_coefficient djnz r5, get_co ;; get partition data: mov garbage, 32H mov a, #10 ;; get 12 bits clr c subb a, garbage mov 31H, a ;; count 12 bits with 31H inc garbage ;; get garbage num bits from first byte mov r5, #0 mov r4, #0 ;; {r4,r5} will hold partition data mov 32H, #0 gp_l: djnz garbage, gp_c jmp gp_f gp_c: clr c mov a, 30H rlc a mov 30H, a mov a, r4 rlc a mov r4, a mov a, r5 rlc a mov r5, a jmp gp_l gp_f: mov a, 32H cjne a, #0FFH, farts jmp farty_fin
217
Appendix J LPC_r.h farts: push 4 call get_byte pop 4 mov 30H, a mov a, #8 clr c subb a, 31H ;; cmp 31H, #8 jc farty mov 32H, #0FFH jz farty ;; if 31H >= 8 get whole bite farty: mov a, 31H clr c subb a, #8 mov 31H, a mov garbage, #9 jmp gp_l farty_fin: mov a, r5 // (partition method) anl a, #00000110B rr a mov rice_encoding, a mov a, r5 anl a, #00000001B rl a rl a rl a mov b, a mov a, r4 anl a, #11100000B rl a rl a rl a add a, b mov partition_order, a mov a, rice_encoding jnz fu mov a, r4 anl a, #00011110B rr a mov rice_parameter, a mov a, r4 rrc a mov a, 30H rrc a mov r4, a mov a, 34H add a, #4
218
;; jg
Appendix J LPC_r.h mov b, a mov a, #8 clr c subb a, b mov r5, a jnc ok_sh sjmp $ ok_sh: jmp fu_fin fu: cjne a, #1, uh_oh mov a, r4 anl a, #00011111B mov rice_parameter, a fu_fin: call get_partition_info clr a mov r0, a mov r1, a mov r1_backup, a mov emi_backup, a mov emi0cn_max, #0DH mov backup1, a mov a, predictor_order rl a mov r1_max, a dec a dec a mov backup2, a mov a, predictor_order mov b, #4 mul ab mov squish1, a /////////////////// ///////////////////// PIES ret uh_oh: sjmp $ #endif
219
Appendix K var_const.inc //////////////////////// Variables and Constants /////// // // ////////////////////////////////////////////////////////// // 8-bit temp variables: ;;;;;;;;;;;;;;;;;;;;; 61H-64H critical variables temp1_16 data 61H temp2_16 data 62H temp3_16 data 63H temp4_16 data 64H fat_sectors_32 data 61H rice_encoding data 61H predictor_order data 62H rice_parameter data 63H co_shift data 64H
// unnecessary
reserved_sectors_16 data 65H // unnecessary backup1 data 65H reserved_sectors_LSB data 66H // unnecessary backup2 data 66H cluster_size data 67H // sectors per cluster emi_backup data 67H sequence_addr_16 data 68H current_time_BCD2 data 68H last_sample_16 data 68h current_time_BCD1 data 69H sequence_addr_16_LSB data 69H last_sample_LSB data 69H ;;;;;;;;;; num_samples_32 critical variable: FIA_NAME_24 data 6BH// unnecessary ;temp1_16 data 6BH num_samples_32 data 6BH ;temp2_16 data 6CH num_samples_2 data 6CH ;temp3_16 data 6DH num_samples_1 data 6DH ;temp4_16 data 6EH num_samples_LSB data 6EH FIA_CRC17 data 6EH // unnecessary? FIA_CRC18 data 6FH OFFSET_L data 6FH toggle2 data 6FH
220
// unnecessary?
Appendix K var_const.inc emi data 78H q0 data 78H OFFSET_H data 78H
// unnecessary?
temp1_32 data 74H column_l data 74H temp2_32 data 75H column_h data 75H temp3_32 data 76H temp3 data 76H garbage1 DATA 76H garbage2 DATA 77H temp4_32 data 77H count2 data 77H
// unnecessary? // used during Header Lookup
q1 data 77H r1_backup data 77H garbage3 data 77h ;;;;;;;;;;;;;;;;;;; 7AH-7DH critical variables addr_1 DATA 7AH song_fin_1 DATA 7AH addr_2 DATA 7BH song_fin_2 DATA 7BH addr_3 DATA 7CH song_fin_3 DATA 7CH addr_4 DATA 7DH song_fin_4 DATA 7DH r_0 data 7AH r_1 data 7BH r_2 data 7CH r_3 data 7DH FIA_32 data 70H temp0 data 70H frame_type0 data 70H frame_type1 data 71H r_4 data 71H test data 72H FIA_32_LSB data 73H all_pl_addr_32 data 70H all_pl_addr_32_LSB data 73H chunk_size_32 DATA 44H block_size_24 DATA 45H partition_count DATA 45H partition_size_16 DATA 46H partition_size_LSB DATA 47h
221
Appendix K var_const.inc block_size_LSB DATA 47H chunk_size_LSB DATA 47H emi0cn_min DATA 57H emi0cn_max2 DATA 57H res data 58H emi0cn_max DATA 58H // permanent variables r1_max data 36H partition_order data 37H precision data 38H temp5 data 38H sample1_16 data 39H sample1_LSB data 3AH sample2_16 data 3BH sample2_LSB data 3CH temp4 data 3DH song_length_16 data 3EH song_length_LSB data 3FH sample_size DATA 40H sample_rate_16 DATA 41H sample_rate_LSB DATA 42H channels DATA 43H channel_assign DATA 43H audio_file_type DATA 48H current_song_32 DATA 49H current_song_2 DATA 4AH current_song_3 DATA 4BH current_song_LSB DATA 4CH current_pl_32 DATA 4DH sprite_pos_max_16 DATA 51H sprite_pos_max_LSB DATA 52H sprite_pos_16 DATA 53H sprite_pos_LSB DATA 54H playlist_pos DATA 55H garbage DATA 56H all_pl_crc18 DATA 59H temp2 DATA 5EH temp1 DATA 5FH toggle DATA 60H // used during SDHC reading CRC DATA 79H RCA_H DATA 07EH RCA_L DATA 07FH sprite_pos_min_LSB DATA 7FH // unused sfrs: squish1 data tmr3h
222
Appendix K var_const.inc squish2 data tmr3l count_it data tl4 county_saeggy data th4 // 1-bit variable Status Flags T0_STAT DATA 20H flag_sequence_found BIT 0 flag_sign bit 0 flag_CMD_fail BIT 1 flag_DAT_received bit 2 flag_DAT_fail bit 3 flag_block_received bit 4 flag_main_decode bit 5 flag_decode_first bit 6 flag_first_time bit 6 flag_DAT_valid bit 7 flag_decode_f bit 7 T0_MODE DATA 21H sequence_rec bit 8 write_18 bit 9 write_x bit 0AH write_indef bit 0BH find_count bit 0CH cmd_stat data 22H short_rsp bit 10H check_rsp bit 11H _SHIFT_B1 DATA 23H _shift_play bit 18H _shift_stop bit 19H _shift_right bit 1AH _shift_left bit 1BH _SHIFT_B2 DATA 24H _shift_mode bit 22H _shift_menu bit 23H _shift_down bit 24H _shift_up bit 25H push_flags data 25H push_flag_play bit 28H push_flag_menu bit 29H push_flag_left bit 2AH push_flag_right bit 2BH push_flag_stop bit 2CH push_flag_mode bit 2DH audio_flags data 26H flag_finish_play bit 30H
223
Appendix K var_const.inc play_mode_flags data 27H flag_pause bit 38H flag_repeat_1 bit 39H DATA_FAIL_COUNT EQU 0FFFFH CMD_FAIL_COUNT EQU 80 test0 data 28h test1 data 29h test2 data 2ah test3 data 2bh test4 data 2ch test5 data 2dh test6 data 2eh test7 data 2fh track_pos data 2fH // Constants // -120 for 16 MHz sysclk/1 // Tim0 EQU -120 // hz_200 = -47040 for 11 MHz // hz_200 = tim0 equ -120 tim_read EQU -120 max_read EQU -16 hz_200 EQU 0 xram_timing EQU 0FFH//0100101B // Hardware Settings CMD EQU P3.0 B1 EQU P2 B2 EQU P3 SCLK EQU P3.1 SDHC EQU P2 EMI_CMD EQU P4 // Pushbuttons Play EQU P2.0 Stop EQU P2.1 Right EQU P2.2 Left EQU P2.3 Mode EQU P3.2 Menu EQU P3.3 Down EQU P3.4 Up EQU P3.5 ////
224
Appendix K var_const.inc IXRAM EQU 0 IXRAM_MAX EQU 10H EXRAM EQU 20H EXRAM_MAX EQU 40H LCD_CMD EQU 10H LCD_DAT EQU 11H // Flash Drive Data Locations LOCATION_cluster_size equ 0DH // In boot sector LOCATION_reserved_sectors equ 0EH LOCATION_fat_size equ 24H LOCATION_cluster_addr equ 26 LOCATION_first_string equ 6 LOCATION_next_string equ 6 MAX_char_header equ 17 // Card RCA default_RCA_H equ 0E6H default_RCA_L equ 024H OFFSET_text equ 16
// Audio Settings // -45 for 16 MHz, sysclk/1, 44.1 KHz 16 bit sample rate tim1 equ -45 // Sequence Recognition BOOT1 equ 0EBH BOOT2 equ 058H BOOT3 equ 090H SECTOR0_1 equ 2 SECTOR0_2 equ 3 SECTOR0_3 equ 1 SECTOR0_4 equ 0BH // all_pl.dat: pl_index_name1 equ 41H pl_index_name2 equ 4CH pl_index_name3 equ 4CH pl_index_name4 equ 5FH pl_index_name5 equ 50H pl_index_name6 equ 4CH pl_index_name7 equ 20H pl_index_name8 equ 20H pl_index_name9 equ 50H /*************/ pl_index_name10 equ 4CH
225
Appendix K var_const.inc pl_index_name11 equ 58H One_Block equ 800H // ISR0 MODES read_block_17 equ 0 find_seq_17 equ 1 find_seq_18 equ 3 read_next_block_17 equ 4 read_blocks_18 equ 8 find_count_18 equ 16 //read_block_18_after_sequence equ 7 //read_block_17x equ 4 //find_seq_17x equ 5 //find_seq_18x equ 7 // sampling rates // 44100 @ 16 MHz = -374 // 22050 @ 16 MHz = -748 // 16000 @ 16 Mhz = -1000 fs_44100 equ -1360 ;;;;;;;;;;;;;;;;;; ;fs_44100 equ -13 ;;;;;;;;;;;;;;;;;; fs_44100_12 equ -30 value equ 1 // decodeable file types riff equ 1 flac equ 2 mp3 equ 3 // tag types name_tag equ 1 artist_tag equ 2 album_tag equ 3 subframe_constant equ 0 subframe_verbatim equ 1 subframe_fixed_1 equ 9 subframe_LPC_1 equ 17
226
Appendix L Bibliography Bibliography Coalson, Josh. FLAC – format. Sourceforge.com. 2008. http://flac.sourceforge.net/format.html
Gorontzi, Kay. Online CRC Calculation. GHSI.edu. 2002. https://www.ghsi.de/CRC/index.php
Langenberger, Brian. Audio Formats Reference. Sourceforge.com. April 19, 2010. http://iweb.dl.sourceforge.net/project/audiotools/audio%20formats%20reference/2.14/ audioformats_2.14_letter.pdf
Microsoft. Microsoft EFI FAT32 File System Specification. MSDN.com. 2000. http://msdn.microsoft.com/en-us/windows/hardware/gg463080
SD Group. Simplified Physical Layer Specifications. SDCard.org. September 25, 2006. http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
227