<< Back

 

Cesky: , English:

ATpad

Game console with ATmega8

Building a powerful and inexpensive computer using modern components is no longer a problem. But using a completely inappropriate and underpowered processor - that's the real challenge! :-D ... And why specifically ATmega8?

  1. It's quite cheap,
  2. easy to use,
  3. I have an overstock of them :-/
  4. and it's a bad enough idea to do it!

Note: Click to enlarge the images shown here

Sample video of ATpad on YouTube: https://www.youtube.com/watch?v=jmdYueKbfG8

Contents

Features of ATpad

ATpad generates the image signal in software. The output can be connected to a TV with RGB input (PAL or NTSC TV standards) or a VGA computer monitor. Via a reducer, the RGB and SYNC signals can be merged into a black and white composite signal (by simply connecting the wires) and connected via the CINCH connector to the composite input of the TV (suitable if the TV does not support RGB input).

A regular SD card is used to run the programs. The card must be formatted with FAT16. The remaining space of the SD card can be used in the normal way with FAT32.

The processor contains a 2 KB boot loader which, after reset, searches the card for the BOOT.* boot loader file (file extension depends on the processor type) and loads it into the ROM Flash. By default, the boot loader is a program for selecting programs from the card - it ensures that the selected program is loaded into ROM memory and executed. If the SD card is not inserted during reset, the last program loaded from memory is executed.

The programs include an array of tile patterns in ROM memory. There is an array of tile indices in RAM (for a 20 x 14 tile resolution, the array takes only 280 bytes in RAM). The display routine reads the tile indexes from RAM and displays the corresponding tiles from ROM. Each tile occupies 32 bytes in ROM (8 x 8 pixels, 16 colors, i.e. 2 pixels per byte). The number of tiles is limited only by the size of the memory. This allows fast image manipulation with small memory requirements. Animations, such as simple video, can also be provided by suitably prepared tiles.

The size of the program in ROM is limited to 6 KB (the remaining 2 KB is taken up by the boot loader). It is also possible to run a larger program using the overlay technique - the program can load the necessary additional parts from the SD card at runtime (into ROM, RAM or EEPROM) - useful for e.g. loading scene definitions. By using a higher processor type (ATmega328p) you can load larger programs without the need for overlay ... but this is missing the fun of "fitting a program into 6 KB" :-) .

ATpad also allows to generate audio tones with rectangular or sawtooth waveform. The tones are created by modulation of horizontal synchronization. For TV picture the synchronization frequency is 16 kHz and therefore it is necessary to take into account the rather poor quality of the generated tone (high content of disturbing harmonics). When using a VGA monitor, the frequency is 32 kHz and the sound is considerably better. The sound quality would be better if, instead of carrier modulation, switching the output according to the tone period were used - but at the cost of reducing the accuracy of the tone frequency.

Type of processor and frequency

The minimum supported processor is the ATmega8 (8 KB ROM, 1 KB RAM, 512 B EEPROM). The last 2 KB of ROM are used for the bootloader, the remaining 6 KB are available for the application, including image tile patterns. The processor can be used in both a TQFP case and a PDIP case. The PDIP version has the advantage of being able to easily replace the processor - in case of failure or when experimenting with different processors.

In addition to the ATmega8, higher pin-compatible types can also be used. Programs must be translated for the specific processor and crystal frequency used. The sample programs provide translations for ATmega8, ATmega88 and ATmega328p. The ATmega88 is the lowest supported type of the more modern xx8 series. The ATmega328p is a cheaper type with larger memory (32 KB ROM, 2 KB RAM). This allows the use of higher screen resolution and larger applications.

The crystal frequency is not strictly specified. However, it is necessary to recompile the applications and the bootloader for the specific frequency used. During translation, the timing for software generation of the image signal is automatically calculated. The crystal frequency primarily determines the achievable resolution of the generated image. When using the nominal frequency (16 MHz for ATmega8 or 20 MHz for ATmegaxx8), the typical image resolution for a VGA monitor is not supported for most programs (this is only achieved by overclocking to a higher frequency). A split screen fallback mode is used, where the left and right halves of the image are displayed on top of each other. For TV modes the nominal frequency is sufficient, the image is displayed correctly.

Split screen on VGA monitor when using low frequency:

The sample applications are designed for a frequency of 24 MHz. Most processors (both ATmega8 and ATmegaxx8) can be overclocked to this frequency. Only with some older ATmega8s have I encountered a limitation to 16 MHz. Some processors can be overclocked up to 27 MHz, but you have to select the processors for this frequency. The benefit may be a higher horizontal resolution, but the limitation may already be the size of the RAM and so this frequency is supported only as a point of interest.

In order to have versions for different processors and different frequencies on the same SD card, the files differ in extension and ATpad only selects the versions with the correct extension. The extension name is stored in the bootloader and is determined during compilation. The following extensions are used in the sample programs:

Running applications from the SD card

Applications are launched from the SD card. In the last 2 KB of the ROM memory is stored a bootloader that loads and runs the BOOT.* program from the root directory of the SD card, where the file extension is determined by the processor type and crystal frequency (see previous section). The programs are loaded into the first 6 KB of ROM memory, or in the case of the ATmega328p, into the first 30 KB of ROM memory. The program is retained in memory even after the ATpad is turned off. If an SD card with a valid BOOT.* file is not inserted after power-up, the last loaded application (located in ROM) is started.

The number of ROM writes is limited to about 10,000. This is a sufficient number for normal use, but may be a limitation if the SD card is inserted and a frequent reset is performed.

The bootloader BOOT.* (in the sample programs, the !BootLoader folder) is used to boot applications from the SD card. The program displays a list of applications on the SD card. It will only display files with the correct extension (=correct processor and frequency). Files can also be placed in folders.

BootLoader allows you to set the display configuration. Combining the B button (top right) with simultaneous pressing of the arrow changes the type of display used. Running programs will take the selected configuration from the EEPROM memory and switch to the correct display type on boot. The configuration is only applied to programs with UNI display mode.

The SD card must be formatted in the card reader to FAT16 format (the only format supported by ATpad) before use. There can be multiple partitions on the SD card (max. 4), ATpad will use the first partition found with FAT16 format. Procedure for creating an SD card under Windows:

  1. Right-click on "This computer" and select "Manage". Select the "Storage" - "Disk Management" row.
  2. Insert the SD card into the reader and locate the appropriate disk in the list of disks at the bottom. BE CAREFUL not to select the wrong disk, you can easily destroy the contents of another of your disks! It must be a "Removable Media" and the listed capacity must match.
  3. If the disk contains any partitions, select and delete them (right mouse button and "Delete Volume" option). BEWARE if you have any data on the disk, deleting a partition will delete the data!
  4. Click in the empty "Unassigned" space and select "New Simple Volume".
  5. When the wizard opens, select the size in MB for the ATpad partition. A few tens of MB is sufficient, e.g. 100 MB (the sample programs take 2 MB in total).
  6. In the next step, choose a drive letter (you can change it later).
  7. In the next step, select the FAT file system. Check "Quick format". Select the size of the allocation unit according to the table below to match the FAT16 format. If the value is too small, the system may require a switch to FAT32, if the value is too large, the system will select FAT12. For example, for 100 MB, select 4096 B.
  8. After formatting the partition, copy the ATpad programs to disk.
  9. You can continue by creating another partition in the remaining space of the SD card. Additional partitions can also be created before the ATpad partition, but in that case they must not use the FAT16 format (they can use FAT32).

Allocation unit size FAT16 disk size from- FAT16 disk size to-
512 B 2 MB 32 MB
1024 B 4 MB 64 MB
2048 B 8 MB 128 MB
4096 B 16 MB 256 MB
8192 B 32 MB 512 MB
16 KB 64 MB 1 GB
32 KB 128 MB 2 GB

Wiring diagram

ATpad is available in 2 versions, depending on the type of processor housing - TQFP (SMD mounting) or PDIP (sleeve).

Wiring diagram of TQFP variant (click to enlarge):

Wiring diagram of PDIP variant (click to enlarge):

The processor is equipped with a reset button S1, which can be used to get from the program to the bootloader. The S5 ISP connector is a programming connector, used to program the processor. Use any standard programmer for AVR processors with a 6-pin ISP connector. At the same time, the ISP programming signals are fed to the SD card, via resistor dividers used to adjust the 5V and 3.3V levels. This may not be necessary, but it is better not to connect the programmer if you have an SD card inserted. This could damage its contents. The X1S mini-USB connector is the power connector. It does not use data wires, it only provides +5V power from a standard charging source (or from a computer's USB port). The regulator IC2 prepares the +3.3V voltage for the SD card. Resistor R17 provides a HIGH level on the CS input of the SD card during processor startup when the outputs are at HIGH impedance, to prevent random state signals from modifying the SD card contents. The SD card connector does not use card insertion signals or write protection (card write protection is not implemented in the ATpad software). An indicator LED is connected to the CS signal of the SD card to monitor the SD card read activity, and also as a program signal LED.

Resistors R7 to R12, R19, R30 and R31 are resistive dividers, to change the output level of the processor to RGB video signals. Resistors R19, R30 and R31 are not required. They were added in an effort to improve the impedance matching of the outputs to the 75-ohm input of the TV, to improve the edge-stops of the picture. The cornering has not improved much (the problem is probably somewhere else) and if you want to omit these 3 resistors, in that case change resistors R7 to R12 to values 680 and 1K5. Resistors R21 and R29 create the voltage levels needed for the SWITCH and BLANK signals for the SCART connector. Both the X4 RGB connector and the X2 VGA connector can be used for output to TV or VGA. Both connectors contain all necessary signals. The audio output is fed non-standardly to pin 14 of the VGA connector (normally used for VSYNC). Due to the input impedance of 75 ohms, the audio signal is attenuated and will not be incorrectly treated as a VSYNC signal. When the connector is inserted into the X3 AUDIO output, the signal is disconnected from the VGA connector so that it is not attenuated by the VGA monitor. The sync signal is routed to both connectors as a sync mix (HSYNC and VSYNC together), which is also supported by VGA monitors. It is possible not to use the X4 RGB connector and to use only the X2 VGA connector - it is easier to fly (more distance between pins) and the mini-DIN connector is hard to handle (too soft connector for too thick cable).

If the TV does not support RGB input, you can use a black and white composite video signal - just connect the R, G, B and SYNC outputs together. On some TVs, the input may already be overdriven by too high a signal level (the top of the picture synchronises badly and is blurred) - in which case it may be necessary to add a limiting resistor.

The X6 JOY connector is a port connector. It contains 2 digital input/output pins (B1 and B2) and 2 analog input pins (X1 and Y1). A standard analog joystick with a 15-pin CANON connector can be connected to the connector. For this purpose, resistors R6 and R13 are used, which together with the variable resistance of the joystick (0 to 100 kOhm) produce an input voltage in the range +2.5 to +5.0V (the value measured on the ADC converter will be in the range 512 to 1023). An example is not provided in the sample programs to access the ports. It is assumed that the ADC input reading handler will be incorporated into the vertical video output synchronization handler. When reading the ADC inputs, it must be remembered that for technical reasons, random data is sent to pins PC4 and PC5 during video signal generation, which results in random connection and disconnection of the 36 kOhm pull-up resistors. This would distort the value measured from the analog joystick. Therefore, it is advisable to add an ADC input reading handler to the vertical synchronization handler, during which the pull-up resistors can be disabled. Alternatively, as a last resort, it would be possible to disable the internal pull-up resistors of the processor globally (PUD switch) and treat the inputs from the buttons with external pull-up resistors.

Signals B1 and B2 (BTN1 and BTN2) can be used as digital inputs or digital outputs. The pins can also be used for I2C serial communication (2-wire serial bus TWI, signals SDA and SCL). In this way, multiple devices can be interconnected with processors, in the form of a bus. The signals use open-collector outputs. There is no example ready for I2C.

To minimize the design, omit the X4 RGB connector, resistors R19, R30, R31, the X6 JOY port connector with resistors R2-R6, R13 and capacitor C8 (audio filter).

Surface connection and mounting

The surface joints are designed as double-sided, without punched holes, with the need for several interconnections between the upper and lower layers. The bottom layer can be replaced with wire jumpers (the joints are mainly routed in the top layer). The joints are created in the free version of Eagle, so they are limited to 10x15 cm. At the same time, it is also the size suitable for the box used. Buttons, SD connector, USB connector and processor in TQFP version are mounted on the top. If you use buttons with locking tabs, I recommend to file the tabs so that the buttons fit tightly on the PCB - the inner height of the box fits tightly on the buttons, leaving the tabs would make the buttons obstruct.

When fitting, I recommend fitting the USB connector first and checking for +5V voltage. Next, solder the stabilizer and check the +3.3V voltage at its output. With the stabilizer, beware that each manufacturer uses a different connection of the stabilizer pins. Do not follow the pin orientation shown here (it may not match your stabilizer). Even vendors (like GME) include datasheets from other manufacturers that, while electrically compatible, do not match pins. That's why it's important to verify the correct function of the stabilizer at the beginning, it's hard to find the fault later.

PCB production: use a double-sided PCB board with a size of 10x15 cm. For it, the aiming crosses in the corners of the joint template are prepared. Print the template on an inkjet or laser printer. It is necessary to use a transparent film for inkjet or laser printer. The ink may not adhere to other film. Print each side of the master twice, mirror reversed. Attach the two prints together, assemble them precisely (according to the coverage of the finest parts of the joint) and glue them together with adhesive. Attach the pattern print downwards on the surface joint (hence the mirror reversed print), place the sighting crosses in the corners exactly on the corners of the 10x15 cm joint. Illuminate the joint with a UV lamp or UV LEDs. Test the exact illumination time on the PCB strip beforehand. The illumination time is about 8 minutes for a strip with 15 UV LEDs at a distance of 30 cm. After illuminating one side, turn the board over and illuminate it using the other template (make sure that the sides are oriented correctly towards each other). Develop the joint in a 1% sodium hydroxide solution (Tesco, drugstore) and etch in a 7% hydrochloric acid solution (PeMi, OBI) with 1% hydrogen peroxide (Barvy Laky).

Top side (TQFP and PDIP variant):

Bottom side (TQFP and PDIP variant):

Printing of the lower side (TQFP and PDIP variant):

Mounting - view from the bottom (TQFP and PDIP variant):

Pin soldering on the bottom side (TQFP and PDIP variant):

Construction and box

The PCB is ready to be placed in the KM78 box.The following holes must be cut in the walls and lid of the box (click to enlarge; note the upward arrow in the side views). The hole for the USB connector will need to be cut quite large, the connector is deeply recessed and the plug and its insulation need to be inserted.

The plate is attached to the bottom by 5 mm long spacers with M3 thread. The thread of the post has to be filed down a bit so that it is not longer than the post of the box. The M3 thread holds well in the box columns, but can easily be pulled off by careless screwing of the column.

The plate is screwed into the columns with M3 screws.

The connectors on the bottom of the board fit snugly on the bottom of the box. The top lid of the box fits snugly over the button knobs. If you observe that the buttons do not respond to pressing (do not click), they are jammed by the box lid. In that case, you need to either shim the lid of the box, or enlarge the holes for the buttons (to fit them with their mounts), or from the underside of the lid, enlarge the holes by milling a groove (this is used in the photos).

I solved the printing of the box by printing a paper label and taping it over with transparent adhesive. I recommend that the label indicate the processor used, frequency and file extension. For this you can use ready-made prints.

Revive, processor programming

If you are using an already programmed processor, an indicator LED should flash after power-up (connecting a USB charger with a mini-USB connector) to indicate that the bootloader is trying to boot the boot program. If you are going to program the processor yourself, I recommend that you first try a test program that does nothing more than flash the indicator LED at a 1 Hz rhythm. This will verify that the processor is functional and that its oscillator is working properly. The package contains test programs translated for different variants of ATpad - according to the list of file extension designations given earlier. For the test program, use the following fuse settings (fast crystal, reset vector pointing to the application at address 0):

ATmega8: low 0xEF (default 0xE1), high 0xC9 (default 0xD9)
ATmega88: low 0xE7 (default 0x62), high 0xDF (default 0xDF), ext 0xF9 (default 0xF9)
ATmega328p: low 0xE7 (default 0x62), high 0xDB (default 0xD9), ext 0xFF (default 0xFF)

After a basic functionality check, program the BootLoader into the processor, which can be found in the root directory of the demonstration disk - These are files with a .HEX extension, the filename contains the name of the variant according to the list above. Program the fuses as follows:

ATmega8: low 0xEF (default 0xE1), high 0xC8 (default 0xD9)
ATmega88: low 0xE7 (default 0x62), high 0xDF (default 0xDF), ext 0xF8 (default 0xF9)
ATmega328p: low 0xE7 (default 0x62), high 0xDA (default 0xD9), ext 0xFF (default 0xFF)

In fuses, the settings are important - use a fast crystal, use a boot loader of 2 KB (= 1 K words), place the reset vector in the boot loader.

After writing the BootLoader, turn on the processor fuse BLB11. This is used to protect the boot loader against application error (so that the application cannot damage the boot loader by unauthorized writing). Without this fuse, the ATpad will also run, but it could happen that sometimes the boot loader stops working after an error.

Once programmed, an indicator LED should start flashing to indicate the boot loader is booting from the SD card. Once the display is connected, you should see an image of the boot loader programs. If no image is visible, try to enable the correct display type using the B+arrow buttons (VGA display is selected by default when first booting).

The easiest way to connect is for a VGA display, which you just plug into a VGA monitor. You can use either the X4 RGB connector (8-pin mini-DIN) or the X2 VGA connector to connect the TV. For both connectors, virtually all the necessary signals (including audio) are available. For the X4 RGB connector, the SWITCH and BLANK control signals for the SCART connector are available to ensure automatic switching of the TV input when the ATpad is switched on and to select the correct aspect ratio. For the X2 VGA connector, a 100R resistor connected to the SWITCH signal can be used for the BLANK signal. If the TV does not support an RGB input, a composite black and white signal can be created by simply connecting the R, G, B and SYNC outputs (possibly still via a limiting resistor if overexcitation occurs).

Sample programs

Root disk folder:

BOOT - program loader (in the source code, the !BootLoader folder). The program contains both an interface for selecting a program to run and a 2 KB boot loader at the end. It is available on disk as a BOOT.* file, which is automatically loaded into memory after a reset, and also as a HEX file that can be written to the processor by the programmer. Running the program without using the programmer loads only the application boot loader into memory, the boot loader section is ignored. Keys: up/down = move cursor through files, left/right = switch pages, A = start program or change directory, B+up = switch to VGA monitor, B+left = TV with PAL, B+right = TV with NTSC. On low *L processors, the file number is not displayed.

DEMO folder (demonstration):

LINES - random line pattern generation. The program uses attribute graphics similar to ZX Spectrum - each group of 8x8 pixels has a color attribute indicating the background color and foreground color. The resolution achieved depends on the type of processor (RAM size) and the speed of the crystal. For 24 and 27 MHz crystals, the resolution of ATmega8 and ATmega88 processors is 88x56 pixels, while the ATmega328p processor has a resolution of 112x104 pixels. For slower crystals, the resolution is slightly lower. Keys: B = exit program.
MELODY - play the tune "Silent Night". As I mentioned above, the TV uses 16 kHz horizontal sync modulation to generate the tones, so the quality of the generated sound is poor. On a VGA monitor, the sound is better. Keys: B = exit program.
PHOTO - view pictures and photos. The program uses attribute graphics (see the LINES program). For ATmega8 and ATmega88 the image resolution is 96x56 pixels, for ATmega328p 120x104 pixels. The low crystal speed versions use a split screen at the VGA monitor. There is a program called ATpad_graph that converts images (TGA without compression) into an internal format with attributes, which the program then loads from disk into video memory as an overlay. Keys: B = exit the program.

PI - demonstration of large number calculation. The program calculates the number PI to 200 digits using Machin's formula. After the calculation, it checks the result by comparing it with the table PI number. The program also demonstrates how to speed up the program run by shrinking the displayed image (during the PI calculation the image is shrunk to only 1 line, thus speeding up the program run by a factor of 10). The low crystal speed versions of ATpad use a split screen for the VGA monitor. Keys: A = repeat calculation, B = exit program.

GAME folder (games):

FIFTEEN - game Fifteen. There are 15 numbered stones on the board, randomly placed. The object is to arrange the stones in order from 1 to 15. Low crystal speed versions of the ATpad use a split screen on a VGA monitor. Keys: Arrow = move, B = exit.
MAZE - game Maze. It demonstrates the algorithm of random maze creation. The task is to walk through the maze to the starting door. Only the boxes near the player are visible. For the low crystal speed version, a smaller maze is generated. Keys: arrow keys = move, A = show door, B = exit.
PONG - game Television Tennis. The opponent is a computer. The program uses attribute graphics. The low crystal speed versions of ATpad use a split screen on a VGA monitor. Keys: arrow keys = move, A = serve the ball, B = exit the program.
SOKOBAN1 - the classic popular Sokoban game. In this variant there are 84 scenes of the "Box World" set. The scenes are loaded as overlays from the disc. Each scene includes a macro demonstrating the scene solution. The program comes with a program for RLE compression of the scene solution macro. The low crystal speed versions of ATpad use a split screen on a VGA monitor. Keys: arrow keys = move, A = demonstrate scene solution, B = exit program.
SOKOBAN2 - the classic popular Sokoban game. In this variant there are 40 scenes of the "Mini Cosmos" set and 16 remaining scenes of the "Box World" set (i.e. 56 scenes in total). The scenes are loaded as an overlay from the disc. Each scene includes a macro demonstrating the scene solution. The low crystal speed versions of ATpad use a split screen on a VGA monitor. Keys: arrow keys = move, A = demonstrate scene solution, B = exit program.
SOKOBAN3 - the classic popular Sokoban game. In this variant there are 88 scenes of the "XSokoban" set. The scenes are loaded as an overlay from the disc. Each scene includes a macro demonstrating the scene solution. The low crystal speed versions of the ATpad use a split screen on a VGA monitor. Keys: arrow keys = move, A = demonstrate scene solution, B = exit program.
TETRIS - the classic game of Tetris. The low crystal speed versions of the ATpad use a split screen on the VGA monitor. Keys: left/right = move sideways, up = rotate, down = place, A = pause, B = end game.
TRAIN - train on the Snake principle. The goal is to collect all the items and pass through the goal gate. Scenes are loaded as an overlay from the disc. There are 50 scenes. A scene can be selected by entering a password. The low crystal speed versions of ATpad use a split screen on a VGA monitor. Keys: arrow keys = move, A = enter password, B = interrupt scene. B+top = sample scene solution. The program can only be interrupted by resetting the ATpad.

TEST folder (ATpad testing and diagnostics):

BUTTONS - ATpad button test. Buttons 1 and 2 are digital inputs from the port connector (in ATpad prototype version 1 these are X and Y buttons). The low crystal speed versions of the ATpad use a split screen for the VGA monitor. The program can only be interrupted by resetting the ATpad.
COLORS - horizontal test bars of colours with index 1 to 15 (black colour with index 0 is missing). Keys: B = exit program.
COLORS2 - vertical test stripes of colours with index 1 to 15 (black colour with index 0 is missing). The low crystal speed versions of the ATpad use a split screen for the VGA monitor and will also display black 0. Keys: B = exit program.
COLORS3 - combined test pattern. The top and bottom bars (black and white background colours) may already be outside the displayable part of the screen. The low crystal speed versions of the ATpad use a split screen for the VGA monitor. Keys: B = exit program.
COLORS4 - combined test pattern with numbered table. Resulting color attribute = row*16 + column. The low crystal speed version of ATpad will display a table 2x as high. Keys: B = exit program.

FONT6 - 6x8 pixel font character set display. The low crystal speed versions of the ATpad use a split screen for the VGA monitor. Keys: A = switch between lower and upper half of characters, B = exit program.

FONT8 - 8x8 pixel font character set display. The low crystal speed versions of ATpad use split screen on a VGA monitor. Keys: A = switch between lower and upper half of characters, B = exit program.

FONTIBM - displaying the IBM 8x8 pixel font character set. The low crystal speed versions of the ATpad use a split screen for the VGA monitor. Keys: A = switch between lower and upper half of characters, B = exit program.
LED - test flashing of the indication LED, with an interval of 1 second. All other functions are suppressed, there is no output to the display. The program can only be interrupted by resetting the ATpad.

TUTORIAL folder:

HELLO - the simplest sample program. It prints the text on the screen. The program can only be interrupted by resetting the ATpad.

Compilation and creating applications

The programs for the ATpad (including the boot loader) are written in C together with the AVR assembler and compiled on the PC using the WinAVR 20100110 compiler (avr-gcc 4.3.3). The installer can be downloaded e.g. from SourceForge https://sourceforge.net/projects/winavr/. The installer should add to the PATH system variable the path to the C:\WinAVR\bin folder from where the compiler will be called.

Extract the ATpad source archive to a new folder. Inside you will find folders with individual applications. The !BootLoader folder contains the boot loader code (2 KB permanently located at the end of the ROM) along with the program to start the applications. After compiling, a HEX file is generated which you write to the processor ROM with the programmer. After writing, set the processor fuses and locks as described in the Recovery section. You will no longer write other translated programs to the processor with the programmer, but save them to the SD card and run them in the ATpad with the boot loader. The SD card must be formatted to FAT16, instructions were given in the SD card section.

Applications are compiled with the c.bat command file (=compile). Unnecessary translation products can be deleted with d.bat (=delete). The generated files are also copied to the !OK folder at the same time. After all applications have been translated, the folder will contain the SD disk image. All programs at once can be translated with the batch file c_all.bat. It takes about half an hour to translate all applications.

The "_timings" folder contains the ATpad_timings program, which is used to calculate timings. It is called during translation. The necessary parameters are passed to the program via the command line. From the timings.ini file, it reads the configuration of the libraries (the number of clock cycles of each branch of the program). If possible, do not interfere with the libraries in the "video" folder, changes would require correcting the timing parameters.

The "_sprites" folder contains common graphical documentation - font definitions and programs for importing fonts, images and sprites into ATpad.

The "_lib" folder contains libraries used by ATpad applications, mostly written in assembly language - math operations, display handler, random generator, file handler and sound. See the Libraries section for a detailed description of the functions.

If you want to create your own application:

A good example is the HELLO app. It does nothing but display text in the middle of the screen. There is a good view of the minimum needed to translate the app. The file "asm_sprites.S" contains the graphical background (fonts, sprites). It is compiled by the assembler to control the alignment of the fields. The "include.h" file contains references to all the *.h files used (definitions) and is nested in each *.c file. The main.c file is the main program, main.h is its header file (making definitions available for other parts of the program). The makefile file contains references to the compiled parts of the program - you add the names of all the *.c and *.S files you add to it.

The first statement of the main() function should always be Init(). It initializes the ATpad, both software and hardware. The second command is ReadConfigLoader() - it reads the display configuration and switches the display to PAL, NTSC or VGA. The display is switched programmatically only when using UNI mode (universal mode). In UNI mode, the size of the video mode is limited by the most demanding element - which usually means a VGA display. If you choose the display type explicitly (select PAL, NTSC or VGA instead of UNI), you can use a much higher horizontal resolution for TV modes. However, this comes at the price that the program cannot be switched to a different display type (or you have to generate a separate file for each display).

If the application uses a random number generator, the Randomize() command should follow. This will ensure that the default value of the random generator is read from EEPROM, thus varying the randomness on repeated executions. This is followed by the main loop of the program - usually an infinite while(1) {} loop. It is advisable for the loop to contain a WaitFrame() statement. The command waits for a vertical synchronization pulse, and this ensures that the program runs independent of the processor speed.

Libraries

The library files are located in the "_lib" folder. They are added to the application using the makefile reference "include ..\_lib\makefile", in asm_sprites.S the reference "#include ..\_lib\asm.inc" and in include.h the reference "#include ..\_lib\base.h". The library contains the following folders: add sum of numbers, bits bitwise operations, disp text display, div division of numbers, func math functions, mul multiplication of numbers, rand random generator, shift bit shifts, video video signal generator. In the basic libraries folder you will find keyboard support, initialization, wait, text display, eeprom, file handler, graphical display and audio handler. While you can also use standard WinAVR operations for math operations, they tend to be much slower and larger - especially when it comes to 64-bit operations. The common.h file contains many useful definitions common to both C and assembler-bit constants, colors, key codes. The base.h file contains definitions used only in C-character definitions, data types, function headers. During compilation, a file timings.h is created in the application folder, from which you can use the definitions for the display - especially the constants WIDTH and HEIGHT, representing the width and height of the display (or video memory) in characters (sprites). In graphics mode, these constants again represent the size in characters, i.e. an 8x8 pixel box.

All library files are translated during translation. The compiler ensures that only the elements used are included in the final code. Using means not only putting the function in the code, but also calling the code from a function that will not be emitted, e.g. main(). Thus, function translation does not increase the size of the resulting code, it only slows down the translation. To speed up translation, you can comment out unused functions called from the makefile (in the _lib folder) by putting a # at the beginning of the line.

Because of the function dumping mechanism, each function in the assembler is listed in a separate *.S file. This is because if the compiler discovers that a function is to be used in the code, it includes the entire *.S file in the resulting code, not just the called function (in fact, it doesn't even know which parts of the file belong to the function and which don't). Therefore, the functions must be separated.

Global definitions:

WIDTH ... display width in characters (sprites)
HEIGHT ... display height in characters (sprites)
Board[] ... video memory of size WIDTH*HEIGHT. For text modes with color attribute, the size is 2* larger. For graphic modes, it contains color attributes.
BoardColor[] ... line colours for MONO text modes with full-colour line (bits 0..3=foreground, 4..7=background)
Graph[] ... bitmap graphics in graphics mode (1 bit = 1 pixel, distinguishes whether the background or foreground color from the Board[] field is displayed.
Sprites ... start of graphic background in ROM (fonts, sprites)
s32 abs(s32 n) ... absolute value of the integer
void Init() ... ATpad initialization
B0..B31 ... constant representing bit 0..31
BIT(pos) ... macro defining bit 0..31
COLOR(bg,fg) ... merge background and foreground color components into a color attribute

add library

Sum of unsigned integers, output is u64 (QWORD)

u64 AddQB(u64 num1, u8 num2);
u64 AddQW(u64 num1, u16 num2);
u64 AddQD(u64 num1, u32 num2)
u64 AddQQ(u64 num1, u64 num2)

bits library

Finding the order of the highest bit (=bit position + 1), binary logarithm. Number 0 returns 0.

u8 OrderByte(u8 val);
u8 OrderWord(u16 val);
u8 OrderDWord(u32 val);
u8 OrderQWord(u64 val);

Finding mask of the number, i.e. a binary number from "1" greater than or equal to the specified number. E.g. 0x123 returns 0x1FF.

u8 MaskByte(u8 val);
u16 MaskWord(u16 val);
u32 MaskDWord(u32 val);
u64 MaskQWord(u64 val);

div library

Division of unsigned numbers, with different combinations of input and output dimensions. The "rem" parameter is a pointer to the remainder after division (= modulo), can be NULL.

extern u8 DivBB(u8 num, u8 d, u8* rem);
extern u8 DivB10(u8 num);
extern u8 ModB10(u8 num, u8* quot);
extern u8 DivWBB(u16 num, u8 d, u8* rem);
extern u16 DivWB(u16 num, u8 d, u8* rem);
extern u16 DivWW(u16 num, u16 d, u16* rem);
extern u16 DivW10(u16 num);
extern u8 ModW10(u16 num, u16* quot);
extern u16 DivDWW(u32 num, u16 d, u16* rem);
extern u32 DivDB(u32 num, u8 d, u8* rem);
extern u32 DivDW(u32 num, u16 d, u16* rem);
extern u32 DivDD(u32 num, u32 d, u32* rem);
extern u32 DivD10(u32 num);
extern u8 ModD10(u32 num, u32* quot);
extern u32 DivQDB(u64 num, u8 d, u8* rem);
extern u32 DivQDW(u64 num, u16 d, u16* rem);
extern u32 DivQDD(u64 num, u32 d, u32* rem);
extern u64 DivQB(u64 num, u8 d, u8* rem);
extern u64 DivQW(u64 num, u16 d, u16* rem);
extern u64 DivQD(u64 num, u32 d, u32* rem);
extern u64 DivQQ(u64 num, u64 d, u64* rem);

mul library

Multiplication of unsigned numbers with different combinations of input and output dimensions.

extern u8 MulBB(u8 num1, u8 num2);
extern u8 MulB10(u8 num);
extern u16 MulWBB(u8 num1, u8 num2);
extern u16 MulWB(u16 num1, u8 num2);
extern u16 MulWW(u16 num1, u16 num2);
extern u16 MulW10(u16 num);
extern u32 MulDWB(u16 num1, u8 num2);
extern u32 MulDWW(u16 num1, u16 num2);
extern u32 MulDB(u32 num1, u8 num2);
extern u32 MulDW(u32 num1, u16 num2);
extern u32 MulDD(u32 num1, u32 num2);
extern u32 MulD10(u32 num);
extern u64 MulQDB(u32 num1, u8 num2);
extern u64 MulQDW(u32 num1, u16 num2);
extern u64 MulQDD(u32 num1, u32 num2);
extern u64 MulQB(u64 num1, u8 num2);
extern u64 MulQW(u64 num1, u16 num2);
extern u64 MulQD(u64 num1, u32 num2);
extern u64 MulQQ(u64 num1, u64 num2);
extern u64 MulQ10(u64 num);

shift library

Bit shift of unsigned integers (Shl left, Shr right).

extern u8 ShlB(u8 num, s8 shift);
extern u16 ShlW(u16 num, s8 shift);
extern u32 ShlD(u32 num, s8 shift);
extern u64 ShlQ(u64 num, s8 shift);
extern u8 ShrB(u8 num, s8 shift);
extern u16 ShrW(u16 num, s8 shift);
extern u32 ShrD(u32 num, s8 shift);
extern u64 ShrQ(u64 num, s8 shift);

video library

Video output operation (video signal rendering).

volatile s16 VLine; ... next rendered video line
volatile u16 Frame; ... current frame (used for timing)
u8 DispMode; ... currently selected display VGA, PAL, NTSC
u8 SplitMode; ... current display mode (0 normal, 1 split screen, 2 double line height, 3 half line height)
u8 Hor; ... horizontal resolution in the sprites
s16 VVisible; ... number of visible video lines (used to darken part of the image)
s16 VSyncBeg; ... beginning of the vertical synchronization pulse
s16 VSyncEnd; ... end of vertical synchronization pulse
s16 VLines; ... total number of video lines

u16 GetVLine(); ... get current video line
void SetVLine(s16 num); ... set current video line
Bool CheckVSync(); ... test if vertical blanking is occurring
void SetVVisible(s16 num); ... setting the number of visible video lines
void SetVSyncBeg(s16 num); ... setting the start of the vertical synchronization pulse
void SetVSyncEnd(s16 num); ... setting the end of the vertical synchronization pulse
void SetVLines(s16 num); ... setting the total number of vertical video lines
void WaitVSync(); ... waiting for the vertical synchronization pulse
u16 GetFrame(); ... get current frame (increments each frame, can be used as a timer)
void WaitFrame(); ... waiting for the next frame (used as a timer after 20 ms or 16.7 ms)
void WaitFrameNum(u16 num); ... waiting for the specified number of frames

key library

Keyboard service. Key indices can be found in common.h (KEY_1 = B0, ...)

u8 KeyCnt[KEY_NUM]; ... counters to detect button presses.
u8 KeyMap; ... map of pressed buttons
void KeyLoop(); ... button service, should be called repeatedly preferably every video frame
u8 GetKeyMap(); ... get the map of pressed buttons (bit positions KEY_1 etc), first it is necessary to call KeyIn()
u16 KeyIn(); ... button input (press or release), in the high byte returns the KEY_REL button release flag; 0=no change
void KeyFlush(); ... emptying the key buffer
void KeyAllOff(); ... waiting for all buttons to be released

wait library

Waiting service. Waiting takes the form of a waiting loop with a countdown of processor clocks. It is accurate only if no interrupts are in progress. If the display is being serviced, the wait loops can slow down up to 10 times. To make the wait independent of CPU load, use WaitFrame().

void wait1us(); ... delay 1 us
void waitus(u16 us); ... delay 2 to 65535 us
void waitms(u16 ms); ... delay 1 to 65535 ms

disp library

Output to text display.

u8 Color ... currently selected color (default color for text output; bits 0..3=foreground, 4..7=background)
void SetCol(u8 bg, u8 fg); ... setting the current colour
void SetFgCol(u8 fg); ... setting the foreground colour
void SetBgCol(u8 bg); ... background colour setting

u8* BoardAddr(u8 x, u8 y); ... calculation of address in video memory

s16 GetHCycles(); ... number of clock cycles per horizontal line
s16 GetHSyncLen(); ... length of the horizontal synchronization pulse
s16 GetVLines(); ... total number of vertical lines
s16 GetVVisible(); ... number of visible vertical lines
s16 GetVFreq(); ... vertical frequency in Hz * 256
s16 GetVBP(); ... vertical back porch (between vsync and image)
s16 GetVFP(); ... vertical front porch (between image and vsync)
u8 GetVSyncLen(); ... length of vertical synchronization pulse
u8 GetRowLines(); ... number of lines per row of sprites
u8 GetSplit(); ... split mode (0 normal, 1 split display, 2 double height, 3 half height)
u8 GetHor(); ... number of sprites horizontally

s16 GetViewDefStart() ... implicit starting visible line
s16 GetViewStart(); ... starting visible line
s16 GetViewDefHeight() ... implicit visible height
s16 GetViewHeight(); ... visible height
void SetView(s16 start, s16 height); ... setting the start and height of visible lines
void SetViewRel(s16 start, s16 height); ... set start and height of visible image relatively (in 1/1000)
void DispOff() ... turn off display (to speed up calculations)
void DispOn() ... turn on the display
void OpenView(s16 minheight); ... opening the display - lighting up for 1/3 second
void CloseView(s16 minheight); ... closing of the display - dimming for 1/3 second

u8 ConvAsc(u8 ch); ... ASCII character to sprite index conversion

The following functions are in variants: x = display with default color Color, xCol = with specified color, xNoCol = without color change

Displaying a character

void DispChar(u8 x, u8 y, u8 ch);
void DispCharCol(u8 x, u8 y, u8 ch, u8 col);
void DispCharNoCol(u8 x, u8 y, u8 ch);

Repeated display of a character

void DispCharRep(u8 x, u8 y, u8 ch, u8 num);
void DispCharRepCol(u8 x, u8 y, u8 ch, u8 num, u8 col);
void DispCharRepNoCol(u8 x, u8 y, u8 ch, u8 num);

Display space character

void DispSpc(u8 x, u8 y);
void DispSpcCol(u8 x, u8 y, u8 col);
void DispSpcNoCol(u8 x, u8 y);

Repeated display of space character

void DispSpcRep(u8 x, u8 y, u8 num);
void DispSpcRepCol(u8 x, u8 y, u8 num, u8 col);
void DispSpcRepNoCol(u8 x, u8 y, u8 num);

Display text from ROM (text has attribute PROGMEM)

void DispTextROM(u8 x, u8 y, const char* txt, u8 len);
void DispTextROMCol(u8 x, u8 y, const char* txt, u8 len, u8 col);
void DispTextROMNoCol(u8 x, u8 y, const char* txt, u8 len);

Display text from RAM

void DispTextRAM(u8 x, u8 y, const char* txt, u8 len);
void DispTextRAMCol(u8 x, u8 y, const char* txt, u8 len, u8 col);
void DispTextRAMNoCol(u8 x, u8 y, const char* txt, u8 len);

Decoding a number from the end of the OutBuf buffer with trailing 0, returns a pointer to the beginning of the text.

u8* DecNum(u32 num);
u8* DecNumW(u16 num);
u8* DecNumB(u8 num);

Length of the number in OutBuf (input is a pointer to the beginning of the text from DecNum)

u8 LenNum(u8* text);

Display a right-aligned number (x is the position of the last character)

void DispNumR(u8 x, u8 y, u32 num);
void DispNumRCol(u8 x, u8 y, u32 num, u8 col);
void DispNumRNoCol(u8 x, u8 y, u32 num);

Display left-aligned number (x is the position of the first character)

void DispNum(u8 x, u8 y, u32 num);
void DispNumCol(u8 x, u8 y, u32 num, u8 col);
void DispNumNoCol(u8 x, u8 y, u32 num);

Display HEX number (number of digits: 1, 2, 4, 8)

void DispHexN(u8 x, u8 y, u8 n);
void DispHexNCol(u8 x, u8 y, u8 n, u8 col);
void DispHexNNoCol(u8 x, u8 y, u8 n);

void DispHexB(u8 x, u8 y, u8 n);
void DispHexBCol(u8 x, u8 y, u8 n, u8 col);
void DispHexBNoCol(u8 x, u8 y, u8 n);

void DispHexW(u8 x, u8 y, u16 n);
void DispHexWCol(u8 x, u8 y, u16 n, u8 col);
void DispHexWNoCol(u8 x, u8 y, u16 n);

void DispHexD(u8 x, u8 y, u32 n);
void DispHexDCol(u8 x, u8 y, u32 n, u8 col);
void DispHexDNoCol(u8 x, u8 y, u32 n);

Display RAM data in HEX format

void DispHexData(u8 x, u8 y, const u8* data, u8 num);
void DispHexDataCol(u8 x, u8 y, const u8* data, u8 num, u8 col);
void DispHexDataNoCol(u8 x, u8 y, const u8* data, u8 num);

Display HEX data from DOS sector 512 B, off=offset in the sector (ensures loading from SD card)

void DispHexSect(u8 x, u8 y, u32 sect, u16 off, u8 num);
void DispHexSectCol(u8 x, u8 y, u32 sect, u16 off, u8 num, u8 col);
void DispHexSectNoCol(u8 x, u8 y, u32 sect, u16 off, u8 num);

Clear the screen

void DispClear();
void DispClearCol(u8 col);
void DispClearNoCol();

void SetDispCol(u8 col); ... Full screen color setting and default color setting (does not erase characters)
void SetRowCol(u8 y, u8 col); ... Setting the colour of one row
void SetDispMode(u8 dispmode); ... Reinitialisation of display mode

eeprom library

EEPROM memory service (saving program configurations). Each program uses its 16-bit MAGIC number to indicate its configuration. The numbers 0, 1 and 0xFFFF are reserved for the system. There can be 6 bytes of configuration data. sConfig (in eeprom.h) is a configuration structure.

u16 ConfigFind(u16 magic); ... find configuration record (returns offset in EEPROM, -1=not found)
Bool ConfigRead(void* config); ... load configuration data (False=not found)
Bool ConfigVerify(const void* config, u16 off); ... verification of configuration data (False=does not match)
Bool ConfigWrite(const void* config); ... write configuration data
sConfig_Loader ConfigLoader; ... boot loader configuration record
void ReadConfigLoader(); ... loading the boot loader configuration and setting the display mode

file library

File service. File functions in ATpad use a smaller SECT_SIZE sector size than the standard 512 B, due to the limited RAM size (for ATmega8 it is 64 bytes). SD cards require 512 byte access - ATpad reads only the necessary part of the physical sector, the rest is discarded. Therefore, reading from SD disk is slower than it could be. The sectors are loaded into the DiskBuf buffer.

void FileOpen(sFile* file, u16 sclust); ... open a file or directory by specifying the initial cluster (=location block)
Bool FileSeek(sFile* file, u32 off); ... move a pointer in a file or directory
s16 FileReadSect(sFile* file, u32 off); ... loading a sector into DiskBuf (file/directory must be open with FileOpen)
Bool FileRead(sFile* file, u32 off, void* buf, s16 len); ... loading an open file into the buffer in RAM

func library

Mathematical functions - basic goniometric functions.

Integer sin/cos. The input is a relative angle in the range 0 to 255. An angle value of 0 to 256 corresponds to an angle of 0 to 90 degrees. The output is a relative number 0..255, representing a value of 0 to 1.

u8 SinB(u8 angle);
u8 CosB(u8 angle);

sin/cos in full range. The input is a number 0..255 representing an angle of 0..360 degrees. The output is a value of -127 to +127, corresponding to -1..+1.

s8 SinBFull(u8 angle);
s8 CosBFull(u8 angle);

graph library

Graphical display service - bitmap with color attributes, 1 attribute is assigned to an 8x8 pixel array. The definition of color mode "colormode" can be found in graph.h - display without color change, with color input, pixel setting, pixel reset, pixel change. Drawing functions do not control overflow of display borders.

void DrawPixel(u8 x, u8 y, u8 colormode, u8 col); ... draw a pixel
void DrawLine(u8 x1, u8 y1, u8 x2, u8 y2, u8 colormode, u8 col); ... draw a line
void DrawBox(u8 x, u8 y, u8 w, u8 h, u8 colormode, u8 col); ... draw a box

sound library

Audio output service. If possible, use only the Beep function to output single tones. The melody play function is ROM intensive.

void Beep(u16 f, u8 len); ... tone playback, f=time constant (tone depends on horizontal display frequency), len=length in frames
Bool Playing(); ... test whether the melody is being played (specified by the Play command)
void WaitPlaying(); ... waiting for the melody to finish playing
void PlayLoop(); ... melody playback service (should be called periodically from the main loop)

Playing a melody from ROM (entered as text with PROGMEM attribute). Text syntax:
On ... base octave setting n=0..7
Ln ... setting the default length n=0..7
+ ... octave increase for the next 1 note
- ... decrease the octave for the following 1 note
C, C#, D, D#, E, F, F#, G, G#, B (or H) ... play a note, can be followed by a digit 0..7 indicating the length, dot will extend by half
R ... play a pause, may be followed by a digit 0..7 indicating length, dot extends by half
n ... the digit 0...7 following the note or pause indicates the length of the note
. ... the dot following the note or pause (and possibly the length digit) will extend the length by half

void Play(const char* melody); ... playing a melody specified as text in ROM (attribute PROGMEM)

rand library

Random generator.

u32 RandSeed; ... seed of random generator
void SetRandSeed(u32 seed); ... initialize random generator
u32 RandShift(); ... shift the random generator by 1 step (returns the new RandSeed value)

Calculating an unsigned random number

u8 RandByte();
u16 RandWord();
u32 RandDWord();
u64 RandQWord();

Calculating a signed random number

s8 RandChar()
s16 RandShort()
s32 RandInt()
s64 RandLong()

Calculation of an unsigned random number in the range 0 to max (including the specified boundary value)

u8 RandByteMax(u8 max);
u16 RandWordMax(u16 max);
u32 RandDWordMax(u32 max);
u64 RandQWordMax(u64 max);

Calculation of a signed random number in the range 0 to max (including the specified boundary value, max can be negative)

s8 RandCharMax(s8 max);
s16 RandShortMax(s16 max);
s32 RandIntMax(s32 max);
s64 RandLongMax(s64 max);

Calculation of a random number in the specified range min to max (including specified boundary values). If min > max, a number outside the interval is generated.

u8 RandByteMinMax(u8 min, u8 max);
u16 RandWordMinMax(u16 min, u16 max);
u32 RandDWordMinMax(u32 min, u32 max);
u64 RandQWordMinMax(u64 min, u64 max);
s8 RandCharMinMax(s8 min, s8 max);
s16 RandShortMinMax(s16 min, s16 max);
s32 RandIntMinMax(s32 min, s32 max);
s64 RandLongMinMax(s64 min, s64 max);

void Randomize(); ... initialization of the random generator by a number from EEPROM. It should be called only once when the application starts. The function will ensure that the next time the application is started, it will have a different default state of the random generator.

boot library

Resident boot loader function. The boot loader starts at the BootStart address, which corresponds to the address of the reset vector. For the ATmega8 this is address 0x1800 (offset 6 KB). Note that the boot loader does not use physical 512 byte sectors (as required by SD cards), but uses smaller SECT_SIZE sectors (due to limited RAM, typically 64 bytes). Items referencing sectors are converted to logical sectors.

Data of the boot loader in the RAM

u8 DiskBuf[SECT_SIZE]; ... disk buffer (logical sector from SD disk is read here)
u32 DiskBufSect; ... current logical sector loaded in DiskBuf (-1 = none)
u16 RootNum; ... number of entries in the ROOT directory
u16 ClustSizeSect; ... cluster size in number of logical sectors
u32 FatBase; ... logical sector of the beginning of the FAT
u32 RootBase; ... logical sector of the beginning of the ROOT directory
u32 DataBase; ... logical sector of the start of the data
u16 FileClust; ... start cluster of the currently running program
u16 DirClust; ... start cluster of the directory with the currently running program
u16 FileInx; ... index of the running program in the directory
u8 ClustSizeSectBits; ... number of bits representing the size of the cluster in number of sectors (0=1 sector)
u8 SDType; ... type of SD card

Data on start of boot loader (they are in ROM, with attribute PROGMEM)

const u8 BootVer PROGMEM; ... boot loader version (bits 7..4 major digits, bits 3..0 minor digits)
const u8 BootVar PROGMEM; ... processor variant (bit 7..4 ROM size in KB, 3=8KB...7=128KB, bit 3..0 MCU alternative)
const u8 BootFile[8] PROGMEM; ... name of the boot loader ("BOOT")
const u8 BootExt[4] PROGMEM; ... extension of the name of the loaded programs

Boot loader functions

void BootReset(); ... reset of the boot loader
void SDInit(); ... initialize SD card
Bool SDConnect(); ... connect SD card
void SDDisconnect(); ... disconnecting the SD card
Bool SDReadSect(u32 sector, u8* buffer); ... read sector from SD card
u8 SDSendCmd(u8 cmd, u32 arg); ... send command to SD card
void SDSel(); ... enable SD card selection
void SDUnsel(); ... turning off SD card selection
u8 SDByte(u8 data); ... receiving and sending a byte to the SD card (send 0xFF if you want to read only)
void DiskInit(); ... initialize disk handler (call SDInit() before)
extern Bool DiskMount(); ... mount the disk
extern void DiskUnmount(); ... unmount the disk
void DiskExecFile(u16 clust, u32 size); ... running the program specified by the initial cluster and size
Bool DiskReadFile(u16 clust, u32 off, u16 num, u16 addr, u8 mem); .... reading a file into ROM, RAM, EEPROM
void DiskWriteMem(u16 addr, u8 off, u8 len, u8 mem); ... write data from DiskBuf to ROM, RAM, EEPROM
Bool DiskMoveBuf(u32 sect); ... move the window in DiskBuf to the specified sector
Bool DiskClustValid(u16 clust); ... cluster validation check
u32 DiskClustSect(u16 clust); ... recalculate the cluster to a logical sector
u16 DiskReadFat(u16 clust); ... read the FAT entry for the specified cluster
u8 DiskGetByte(u32 sect, u16 off); ... read a byte from a DOS sector (sect is the physical sector number 512 B, off is the offset in the sector)
u8 DiskCheckFS(u32 sect); ... check FAT file system (sect is the physical sector number 512 B)
void SpmWait(); ... wait for SPM write completion
void SpmCmd(u8 cmd); ... execution of the SPM instruction
void SpmWrite(void* dst, void* src); ... write SPM page to ROM
void EEWait(); ... waiting for the end of writing to EEPROM
u8 EERead(u16 addr); ... reading a byte from EEPROM
void EEWrite(u16 addr, u8 data); ... write byte to EEPROM
void EEWriteData(u16 dst, const void* src, u16 num); ... writing data to EEPROM
void MemCpy(void* dst, const void* src, u16 len); ... copy data in RAM

Videomodes

There are 12 predefined video modes available in the "video" library. While it is possible to create your own video modes, this would require modifying the ATpad_timings program, which is used to calculate the timing of the render functions.

The horizontal resolution of the video mode depends on the frequency of the crystal used. The timing calculation program checks for boundary crossings during compilation, in which case it reports an error and the compilation is aborted. The boundaries between the horizontal sync pulses are checked, not the displayability. The actual displayable portion is slightly less than the distance between pulses and needs to be checked by test. Especially small portable TVs crop the image considerably.

(0) MODE_ASCMONO6 - mono ASCII text 6x8 pixels. The character table uses only the first half, i.e. the lower 128 characters. Only 6 pixels of the characters are displayed on the line. No color can be assigned to individual characters. However, it is possible to set the color for the whole line at once. This mode is very memory efficient both for ROM (the character table consumes 1 KB) and RAM. Compared to the following mode (with 8 pixels), it allows to display more characters per line.

(1) MODE_ASCMONO8 - the same as the previous mode, but the characters are wider (8 pixels instead of 6 pixels) and so the display line can accommodate slightly fewer characters.

(2) MODE_MONO6 - differs from ASCMONO6 in that all 256 characters are available. This is more demanding on ROM memory (the character table consumes 2 KB).

(3) MODE_MONO8 - differs from ASCMONO8 in that all 256 characters are available. This is more demanding on ROM memory (the character table consumes 2 KB).

(4) MODE_ASCTEXT6 - colored ASCII text 6x8 pixels. The character table only uses the first half, i.e. the lower 128 characters, so the character table only takes 1 KB of ROM. Of the characters, only 6 pixels are displayed, this allows more characters to be displayed than an 8x8 font. A color attribute can be assigned to each character (in video memory, characters with color attributes alternate) - at the cost of 2x the RAM consumption of MONO video memory.

(5) MODE_ASCTEXT8 - differs from the previous mode by using 8x8 pixel characters (slightly fewer characters can fit on a line)

(6) MODE_TEXT6 - differs from ASCTEXT6 mode by using a full 256 character table (more ROM intensive, character table takes 2 KB)

(7) MODE_TEXT8 - differs from ASCTEXT8 mode by a full table of 256 characters (more ROM intensive, character table takes 2 KB)

(8) MODE_TILE6 - colored tiles (sprites) 6x8 pixels. In video-RAM there are indexes to the array of tiles. Fully colored tiles can be defined this way. Animations can also be provided by suitable preparation of the sprites. However, tiles are very ROM intensive (1 tile takes 28 bytes).

(9) MODE_TILE7 - 7x8 pixel color tiles. Memory requirements are the same as the following 8x8 pixel mode (1 tile takes 32 bytes), with the advantage of a slightly larger number of sprites per line.

(10) MODE_TILE8 - colored tiles 8x8 pixels. 1 tile takes 32 bytes in ROM.

(11) MODE_GRAPH - graphic mode with color attributes (in the style of ZX Spectrum graphics). Very RAM intensive. There is a bitmap in the Graph field. Each 1 bit represents 1 pixel on the screen and toggles whether to display the background or foreground color. The Board field contains color attributes with foreground and background color. Each attribute corresponds to an 8x8 pixel array.

Shortcomings and errors

Downloads

Sample applications (compiled for ATmega8, 88 and 328p, frequency 16/20/24/27 MHz)

Source codes of boot loader and applications

Box printings

Shematic diagram in Eagle Free

Graphics resource (diagram and PCB)

Complete download of ATpad documents

Used components

The selection of components was tailored to the GM Electronics shop

Total price for everything is 432 Kc (including photocuprextit, box and mini-din plug).

Prototype of version 1

The above version of ATpad is already the 3rd prototype version. However, the first prototype (ATpad version 1) also had interesting features that could serve as inspiration for further development. What made it different:

Miroslav Nemecek

<< Back