mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
Compare commits
1 Commits
dht20
...
gbadisplay
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d1b0c39cc |
@@ -0,0 +1,85 @@
|
||||
// Package gbadisplay implements a simple driver for the GameBoy Advance
|
||||
// display.
|
||||
package gbadisplay
|
||||
|
||||
import (
|
||||
"device/gba"
|
||||
"errors"
|
||||
"image/color"
|
||||
"runtime/volatile"
|
||||
"unsafe"
|
||||
|
||||
"tinygo.org/x/drivers/pixel"
|
||||
)
|
||||
|
||||
// Image buffer type used by the GameBoy Advance.
|
||||
type Image = pixel.Image[pixel.RGB555]
|
||||
|
||||
const (
|
||||
displayWidth = 240
|
||||
displayHeight = 160
|
||||
)
|
||||
|
||||
var (
|
||||
errOutOfBounds = errors.New("rectangle coordinates outside display area")
|
||||
)
|
||||
|
||||
type Device struct{}
|
||||
|
||||
// New returns a new GameBoy Advance display object.
|
||||
func New() Device {
|
||||
return Device{}
|
||||
}
|
||||
|
||||
var displayFrameBuffer = (*[160 * 240]volatile.Register16)(unsafe.Pointer(uintptr(gba.MEM_VRAM)))
|
||||
|
||||
type Config struct {
|
||||
// TODO: add more display modes here.
|
||||
}
|
||||
|
||||
// Configure the display as a regular 15bpp framebuffer.
|
||||
func (d Device) Configure(config Config) {
|
||||
// Use video mode 3 (in BG2, a 16bpp bitmap in VRAM) and Enable BG2.
|
||||
gba.DISP.DISPCNT.Set(gba.DISPCNT_BGMODE_3<<gba.DISPCNT_BGMODE_Pos |
|
||||
gba.DISPCNT_SCREENDISPLAY_BG2_ENABLE<<gba.DISPCNT_SCREENDISPLAY_BG2_Pos)
|
||||
}
|
||||
|
||||
// Size returns the fixed size of this display.
|
||||
func (d Device) Size() (x, y int16) {
|
||||
return displayWidth, displayHeight
|
||||
}
|
||||
|
||||
// Display is a no-op: the display framebuffer is modified directly.
|
||||
func (d Device) Display() error {
|
||||
// Nothing to do here.
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPixel changes the pixel at (x, y) to the given color.
|
||||
func (d Device) SetPixel(x, y int16, c color.RGBA) {
|
||||
if x < 0 || y < 0 || x >= displayWidth || y > displayHeight {
|
||||
// Out of bounds, so ignore.
|
||||
return
|
||||
}
|
||||
val := pixel.NewColor[pixel.RGB555](c.R, c.G, c.B)
|
||||
displayFrameBuffer[(int(y))*240+int(x)].Set(uint16(val))
|
||||
}
|
||||
|
||||
// DrawBitmap updates the rectangle at (x, y) to the image stored in buf.
|
||||
func (d Device) DrawBitmap(x, y int16, buf Image) error {
|
||||
width, height := buf.Size()
|
||||
if x < 0 || y < 0 || int(x)+width > displayWidth || int(y)+height > displayHeight {
|
||||
return errOutOfBounds
|
||||
}
|
||||
|
||||
// TODO: try to do a 4-byte memcpy if possible. That should significantly
|
||||
// speed up the copying of this image.
|
||||
for bufY := 0; bufY < int(height); bufY++ {
|
||||
for bufX := 0; bufX < int(width); bufX++ {
|
||||
val := buf.Get(bufX, bufY)
|
||||
displayFrameBuffer[(int(y)+bufY)*240+int(x)+bufX].Set(uint16(val))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
+32
-1
@@ -16,7 +16,7 @@ import (
|
||||
// particular display. Each pixel is at least 1 byte in size.
|
||||
// The color format is sRGB (or close to it) in all cases.
|
||||
type Color interface {
|
||||
RGB888 | RGB565BE | RGB444BE
|
||||
RGB888 | RGB565BE | RGB555 | RGB444BE
|
||||
|
||||
BaseColor
|
||||
}
|
||||
@@ -46,6 +46,8 @@ func NewColor[T Color](r, g, b uint8) T {
|
||||
return any(NewRGB888(r, g, b)).(T)
|
||||
case RGB565BE:
|
||||
return any(NewRGB565BE(r, g, b)).(T)
|
||||
case RGB555:
|
||||
return any(NewRGB555(r, g, b)).(T)
|
||||
case RGB444BE:
|
||||
return any(NewRGB444BE(r, g, b)).(T)
|
||||
default:
|
||||
@@ -140,6 +142,35 @@ func (c RGB565BE) RGBA() color.RGBA {
|
||||
return color
|
||||
}
|
||||
|
||||
// Color format used on the GameBoy Advance among others.
|
||||
//
|
||||
// Colors are stored as native endian values, with bits 0bbbbbgg_gggrrrrr (red
|
||||
// is least significant, blue is most significant).
|
||||
type RGB555 uint16
|
||||
|
||||
func NewRGB555(r, g, b uint8) RGB555 {
|
||||
return RGB555(r)>>3 | (RGB555(g)>>3)<<5 | (RGB555(b)>>3)<<10
|
||||
}
|
||||
|
||||
func (c RGB555) BitsPerPixel() int {
|
||||
// 15 bits per pixel, but there are 16 bits when stored
|
||||
return 16
|
||||
}
|
||||
|
||||
func (c RGB555) RGBA() color.RGBA {
|
||||
color := color.RGBA{
|
||||
R: uint8(c>>10) << 3,
|
||||
G: uint8(c>>5) << 3,
|
||||
B: uint8(c) << 3,
|
||||
A: 255,
|
||||
}
|
||||
// Correct color rounding, so that 0xff roundtrips back to 0xff.
|
||||
color.R |= color.R >> 5
|
||||
color.G |= color.G >> 5
|
||||
color.B |= color.B >> 5
|
||||
return color
|
||||
}
|
||||
|
||||
// Color format that is supported by the ST7789 for example.
|
||||
// It may be a bit faster to use than RGB565BE on very slow SPI buses.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user