v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
vram.h
1 /* -*- mode: C; c-basic-offset: 4; intent-tabs-mode: nil -*-
2  *
3  * This file is part of the public interface to the Sifteo SDK.
4  * Copyright <c> 2012 Sifteo, Inc. All rights reserved.
5  */
6 
7 #ifndef _SIFTEO_ABI_VRAM_H
8 #define _SIFTEO_ABI_VRAM_H
9 
10 #include <sifteo/abi/types.h>
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /*
17  * _SYSVideoRAM is a representation of the 1KB of RAM resident in each
18  * cube, which is used for storing the state of its graphics engine.
19  *
20  * The combination of this VRAM and the cube's current flash memory
21  * contents must contain all information necessary to compose a frame
22  * of graphics.
23  *
24  * The specific layout of this RAM may change depending on video mode
25  * settings. This union describes multiple different ways to access
26  * the VRAM.
27  */
28 
29 // Total size of VRAM, in bytes
30 #define _SYS_VRAM_BYTES 1024
31 #define _SYS_VRAM_BYTE_MASK (_SYS_VRAM_BYTES - 1)
32 
33 // Total size of VRAM, in words
34 #define _SYS_VRAM_WORDS (_SYS_VRAM_BYTES / 2)
35 #define _SYS_VRAM_WORD_MASK (_SYS_VRAM_WORDS - 1)
36 
37 #define _SYS_VRAM_BG0_WIDTH 18 // Width/height of BG0 tile grid
38 #define _SYS_VRAM_BG1_WIDTH 16 // Width/height of BG1 bitmap
39 #define _SYS_VRAM_BG1_TILES 144 // Total number of opaque tiles in BG1
40 #define _SYS_VRAM_BG2_WIDTH 16 // Width/height of BG2 tile grid
41 #define _SYS_VRAM_SPRITES 8 // Total number of linear sprites
42 #define _SYS_SPRITES_PER_LINE 4 // Maximum visible sprites per scanline
43 #define _SYS_CHROMA_KEY 0x4f // Chroma key MSB
44 #define _SYS_CKEY_BIT_EOL 0x40 // Chroma-key special bit, end-of-line
45 
46 // Bits for 'flags'
47 
48 #define _SYS_VF_RESERVED 0x01 // Reserved, must be zero
49 #define _SYS_VF_TOGGLE 0x02 // Toggle bit, to trigger a new frame render
50 #define _SYS_VF_SYNC 0x04 // Sync with LCD vertical refresh
51 #define _SYS_VF_CONTINUOUS 0x08 // Render continuously, without waiting for toggle
52 #define _SYS_VF_A21 0x10 // Flash A21 bank select
53 #define _SYS_VF_XY_SWAP 0x20 // Swap X and Y axes during render
54 #define _SYS_VF_X_FLIP 0x40 // Flip X axis during render
55 #define _SYS_VF_Y_FLIP 0x80 // Flip Y axis during render
56 
57 // Values for 'mode'
58 
59 #define _SYS_VM_MASK 0x3c // Mask of valid bits in VM_MASK
60 
61 #define _SYS_VM_POWERDOWN 0x00 // Power saving mode, LCD is off
62 #define _SYS_VM_BG0_ROM 0x04 // BG0, with tile data from internal ROM
63 #define _SYS_VM_SOLID 0x08 // Solid color, from colormap[0]
64 #define _SYS_VM_FB32 0x0c // 32x32 pixel 16-color framebuffer
65 #define _SYS_VM_FB64 0x10 // 64x64 pixel 2-color framebuffer
66 #define _SYS_VM_FB128 0x14 // 128x48 pixel 2-color framebuffer
67 #define _SYS_VM_BG0 0x18 // Background BG0: 18x18 grid
68 #define _SYS_VM_BG0_BG1 0x1c // BG0, plus overlay BG1: 16x16 bitmap + 144 indices
69 #define _SYS_VM_BG0_SPR_BG1 0x20 // BG0, multiple linear sprites, then BG1
70 #define _SYS_VM_BG2 0x24 // Background BG2: 16x16 grid with affine transform
71 #define _SYS_VM_STAMP 0x28 // Reconfigurable 16-color framebuffer with transparency
72 #define _SYS_VM_SLEEP 0x3c // Puts cube to sleep after fading out display
73 
74 // Important VRAM addresses
75 
76 #define _SYS_VA_BG0_TILES 0x000
77 #define _SYS_VA_BG2_TILES 0x000
78 #define _SYS_VA_BG2_AFFINE 0x200
79 #define _SYS_VA_BG2_BORDER 0x20c
80 #define _SYS_VA_BG1_TILES 0x288
81 #define _SYS_VA_COLORMAP 0x300
82 #define _SYS_VA_BG1_BITMAP 0x3a8
83 #define _SYS_VA_SPR 0x3c8
84 #define _SYS_VA_BG1_XY 0x3f8
85 #define _SYS_VA_BG0_XY 0x3fa
86 #define _SYS_VA_FIRST_LINE 0x3fc
87 #define _SYS_VA_NUM_LINES 0x3fd
88 #define _SYS_VA_MODE 0x3fe
89 #define _SYS_VA_FLAGS 0x3ff
90 #define _SYS_VA_STAMP_PITCH 0x320
91 
92 struct _SYSSpriteInfo {
93  /*
94  * Sprite sizes must be powers of two, and the
95  * size/position must both be negated.
96  *
97  * Sprites can be disabled by setting height to zero.
98  * A zero width with nonzero height will give undefined
99  * results.
100  */
101  int8_t mask_y; // 0x00 (-height), 0 == disable
102  int8_t mask_x; // 0x01 (-width)
103  int8_t pos_y; // 0x02 (-top)
104  int8_t pos_x; // 0x03 (-left)
105  uint16_t tile; // 0x04 Address in 7:7 format
106 };
107 
108 // Equivalent to an augmented matrix (3x2), in 8.8 fixed-point
109 struct _SYSAffine {
110  int16_t cx; // X initial value
111  int16_t cy; // Y initial value
112  int16_t xx; // X delta, for every horizontal pixel
113  int16_t xy; // Y delta, for every horizontal pixel
114  int16_t yx; // X delta, for every vertical pixel
115  int16_t yy; // Y delta, for every vertical pixel
116 };
117 
118 union _SYSVideoRAM {
119  uint8_t bytes[_SYS_VRAM_BYTES];
120  uint16_t words[_SYS_VRAM_WORDS];
121 
122  struct {
123  uint16_t bg0_tiles[324]; // 0x000 - 0x287
124  uint16_t bg1_tiles[144]; // 0x288 - 0x3a7
125  uint16_t bg1_bitmap[16]; // 0x3a8 - 0x3c7
126  struct _SYSSpriteInfo spr[8]; // 0x3c8 - 0x3f7
127  int8_t bg1_x; // 0x3f8
128  int8_t bg1_y; // 0x3f9
129  uint8_t bg0_x; // 0x3fa 0 <= x <= 143
130  uint8_t bg0_y; // 0x3fb 0 <= y <= 143
131  uint8_t first_line; // 0x3fc 0 <= x <= 127
132  uint8_t num_lines; // 0x3fd 1 <= x <= 128
133  uint8_t mode; // 0x3fe
134  uint8_t flags; // 0x3ff
135  };
136 
137  struct {
138  uint8_t fb[768]; // 0x000 - 0x2ff
139  uint16_t colormap[16]; // 0x300 - 0x31f
140  uint8_t stamp_pitch; // 0x320
141  uint8_t stamp_height; // 0x321
142  uint8_t stamp_x; // 0x322
143  uint8_t stamp_width; // 0x323
144  uint8_t stamp_key; // 0x324
145  };
146 
147  struct {
148  uint16_t bg2_tiles[256]; // 0x000 - 0x1ff
149  struct _SYSAffine bg2_affine; // 0x200 - 0x20b
150  uint16_t bg2_border; // 0x20c - 0x20d
151  };
152 };
153 
154 /*
155  * The _SYSVideoBuffer is a low-level data structure that serves to
156  * collect graphics state updates so that the system can send them
157  * over the radio to cubes.
158  *
159  * These buffers allow the system to send graphics data at the most
160  * optimal time, in the most optimal format, and without any
161  * unnecessary redundancy.
162  *
163  * VRAM is organized as a 1 kB array of bytes or words. We keep a few
164  * bitmaps at different resolutions, for the synchronization protocol
165  * below. These bitmaps are ordered MSB-first.
166  *
167  * Synchronization Protocol
168  * ------------------------
169  *
170  * To support the system's asynchronous access requirements, these
171  * buffers have a very strict synchronization protocol that user code
172  * must observe:
173  *
174  * 1. Set the 'lock' bit(s) for any words you plan to update,
175  * using an atomic store.
176  *
177  * 2. Update the VRAM buffer, using any method and in any order you like.
178  *
179  * 3. Set change bits in cm1, using an atomic OR such as
180  * __builtin_or_and_fetch().
181  *
182  * 4. Set change bits in cm16, using an atomic OR. After this point the
183  * system may start sending data over the radio at any time.
184  *
185  * 5. Soon after step (4), clear the lock bits you set in (1). Since
186  * the system treats lock bits as read-only, you can do this using
187  * a plain atomic store.
188  *
189  * Note that cm16 is the primary trigger that the system uses in order
190  * to determine if hardware VRAM needs to be updated. The lock bits do
191  * not prevent the system from reading VRAM, but rather they're used as
192  * part of the following invariant:
193  *
194  * - For any given word, we are guaranteed that the hardware's value
195  * matches the current buffered value if and only if the 'lock' bit
196  * is zero and the 'cm1' bit is zero.
197  *
198  * If not for the lock bits, this invariant would not be possible to
199  * maintain, since the system would have no idea when userspace code
200  * has modified the buffer, if it hasn't yet set the cm1 bits.
201  *
202  * Streaming over the radio can begin any time after cm16 has been
203  * updated. For bandwidth efficiency, it's best to wait until after a
204  * large update, then OR a single value with cm16 in order to trigger
205  * the update.
206  *
207  * The system may still start streaming updates while the 'lock' bit
208  * is set, but it will not be able to use the full range of protocol
209  * optimization techniques, since some of these rely on knowing for
210  * certain the values of words that have already been transmitted. So
211  * it is recommended that userspace clear the 'lock' bits as soon as
212  * possible after cm16 is set.
213  *
214  * Asynchronous Pipeline
215  * ---------------------
216  *
217  * When working with the graphics subsystem, it's helpful to keep in mind
218  * the pipeline of asynchronous rendering stages:
219  *
220  * 1. Changes are written to a locked vbuf (lock)
221  * 2. The vbuf is unlocked, changes can start to stream over the air (cm16 <- lock)
222  * 3. Streaming is finished (cm16 <- 0)
223  * 4. The cube hardware begins rendering a frame
224  * 5. The cube acknowledges rendering completion
225  *
226  * At any of these stages, a video buffer change can 'invalidate' the
227  * ongoing rendering, meaning we may need to render an additional frame before
228  * the final intended output is actually present on the display. Rendering is
229  * only considered to be 'finished' if we make it through steps 3-5 without
230  * any modifications to the video buffer.
231  *
232  * Paint Control
233  * -------------
234  *
235  * The _SYS_paint() call is a no-op for cubes who have had no drawing occur.
236  * This state is tracked, separately from the dirty bits, using a NEED_PAINT
237  * flag. This flag is cleared by _SYS_paint() itself, whereas the actual dirty
238  * bits are propagated through the firmware's model of the render pipeline.
239  * Userspace code can force a cube to redraw by setting NEED_PAINT, even
240  * without making any VRAM changes.
241  *
242  * This flag is set automatically by _SYS_vbuf_lock().
243  */
244 
245 #define _SYS_VBF_NEED_PAINT (1 << 0) // Request a paint operation
246 // All other bits are reserved for system use.
247 
248 struct _SYSVideoBuffer {
249  uint32_t flags;
250  uint32_t lock;
251  uint32_t cm16;
252  uint32_t cm1[16];
253  union _SYSVideoRAM vram;
254 };
255 
256 /*
257  * In general, the system likes working with raw _SYSVideoBuffers: but in
258  * userspace, it's very common to want to know both the _SYSVideoBuffer and
259  * the ID of the cube it's currently attached with. For these cases, we
260  * provide a standardized memory layout.
261  */
262 
263 struct _SYSAttachedVideoBuffer {
264  _SYSCubeID cube;
265  uint8_t reserved[3];
266  struct _SYSVideoBuffer vbuf;
267 };
268 
269 /*
270  * Tiles in the _SYSVideoBuffer are typically encoded in 7:7 format, in
271  * which a 14-bit tile ID is packed into the upper 7 bits of each byte
272  * in a 16-bit word.
273  */
274 
275 #define _SYS_TILE77(_idx) ((((_idx) << 2) & 0xFE00) | \
276  (((_idx) << 1) & 0x00FE))
277 
278 #define _SYS_INVERSE_TILE77(_t77) ((((_t77) & 0xFE00) >> 2) | \
279  (((_t77) & 0x00FE) >> 1))
280 
281 #ifdef __cplusplus
282 } // extern "C"
283 #endif
284 
285 #endif