PicoSystem API Cheatsheet

By Pimoroni

Courtesy of Pimoroni

Guide by Pimoroni

While you're developing games for PicoSystem you may find keeping this API ‎function reference open handy.‎

The PicoSystem API is intentionally designed to be lightweight and get out of ‎your way when you're developing games. The entire API is exposed as ‎around 40 functions which provide access to the hardware and help with ‎drawing, audio, and user input.‎

Game Loop

The PicoSystem game loop works by calling three functions declared in your ‎code.


  • init() is called once when your program starts so that you can perform ‎any setup that's required like generating map data or initialising the ‎player state.‎
  • update(tick) called every frame to allow you to process user input, trigger ‎sound effects, do collision detection, and update the player state.
  • draw(tick) called every frame and is where you should perform all ‎drawing such as the map, player and enemy sprites, and HUD.

‎The game loop will run at fifty frames per second (the same refresh rate as ‎the screen) so long as your update() and draw() function don't take too long to ‎complete. Every cycle round the game loop will increment tick by one.

‎The reason update() and draw() are implemented as separate functions is ‎because it both helps you separate your game processing logic from your ‎drawing code (good practise!) and it allows the game processing code to run ‎in the background while the screen is updating (if you did drawing operations ‎during the screen updates you'd potentially see an effect called "tearing").‎

The full game loop (including the internal bits) looks like this:


From the diagram you can see that there are points where we must stall the ‎game loop to wait for external events like the screen update and vertical sync ‎from the display.‎


PicoSystem has a 240x240 resolution screen and can either run in full ‎resolution or a pixel doubled mode. The decision of which resolution to use is ‎both aesthetic and limitation driven - you may want the retro look of larger ‎pixels, or need the extra RAM saved by having a smaller framebuffer or need ‎lots of cycles per pixel to calculate visual effects.

  • ‎Full resolution

240x240 @ 16bpp = 112KB framebuffer & ~100 cycles per pixel @ ‎‎40fps.

  • Pixel doubled

‎120x120 @ 16bpp = 28KB framebuffer & ~450 cycles per pixel @ 40fps.‎

The pixel format is the same in both modes with 16 bits per pixel split up into ‎‎4 bits per channel (red, green, blue, and alpha) allowing for 4,096 different ‎colours on screen at any time. Because pixels are 4 bits per channel all colour ‎values passed into and returned by API functions are between 0 and 15.‎

Drawing state

PicoSystem's graphics library is designed to be simple to work with - it has a ‎single global set of state (such as pen colour, camera offset, etc) which all ‎drawing operations adhere to.

Note: All drawing state methods can be called with no parameters to reset to ‎default (i.e. startup) state.

pen(r, g, b, [a]) or pen(color)

‎Set the colour of the pen. Either passing in red, green, blue (with optional ‎alpha) or a pre-baked colour created with the rgb or hsv functions.‎


‎Set a global alpha level for drawing operations. Only relevant if the current ‎blend mode supports alpha blending.‎

clip(x, y, w, h)

‎Set the clipping rectangle - pixels outside of this rectangle will not be drawn.


Set the blend mode to use when drawing semi-transparent pixels. Using the ‎most appropriate blend mode can help with performance. See the section on ‎blend modes for more detail.


Set the target buffer for future drawing operations. The default target is the ‎screen buffer, but you can create your own off-screen buffers if needed. Just ‎remember to set the target back to SCREEN when you're done...

camera(x, y)‎

Offsets all future drawing operations. Ideal for managing a two-dimensional ‎camera.‎


Set a buffer to use as the spritesheet for future calls to sprite(). PicoSystem ‎comes with a default spritesheet which can be disabled or replaced if needed.‎

cursor(x, y)

‎Move the position of the current cursor position used in calls to text() to x, y.‎

font(w, [h], [s], [data])‎

Set metrics for text rendering.‎

  • w: fixed character width in pixels or -1 for variable character widths
  • h: line height in pixels
  • s: space between characters in pixels
  • data: buffer of font data (96 * 9 bytes long)‎

Drawing operations

All drawing operations take into account the drawing state and will be ‎performed on the currently selected target. As a general rule you should only ‎ever call these functions during the draw() callback.‎


Fills all pixels.‎

pixel(x, y)‎

Sets the pixel at x, y to the current pen color.‎

rect/frect(x, y, w, h)

‎Draw an outline or filled rectangle with width w and height h at x, y.‎

circle/fcircle(x, y, r)‎

Draw an outline or filled circle centred at x, y with radius r.

‎ellipse/fellipse(x, y, rx, ry)‎

Draw an outline or filled ellipse centred at x, y with radius rx, ry.

‎poly/fpoly({x1, y1, x2, y2, ...})‎

Draw an outline or filled polygon defined by the points x1, y1 to xn, yn.

‎line(x1, y1, x2, y2)

‎Draw a line from x1, y1 to x2, y2.‎

hline/vline(x, y, l)

‎Draw a horizontal or vertical line starting at x, y of length l. Much faster ‎than line().‎

text(message, [x, y,] [wrap])

Print the contents of message at position x, y or at the current cursor position. ‎Newline characters will reset the cursor to the start of the next line. If wrap is ‎specified, then the text will be wrapped on word boundaries if it ‎exceeds wrap width in pixels.‎

sprite(i, x, y, [flags])

‎Draw the sprite at index i in the current sprite sheet to position x, y on the ‎screen. The sprite can be flipped and mirrored by passing VFLIP, or HFLIP, or ‎both in as flags.‎

blit(source, sx, sy, sw, sh, dx, dy, [dw, dh,] [flags])‎

Copy an area of width sw and height sh from sx, sy in the source buffer to dx,dy in the current target buffer. Optionally scales if you provide a destination ‎width and height in dw and dh. The image can be flipped and mirrored by ‎passing VFLIP, or HFLIP, or both in as flags.


voice(attack, decay, sustain, release, [bend], [bend_ms], [reverb], [noise], [distort])‎

Returns a new voice based on the parameters supplied. Voices can be ‎passed into play().

  • attack: duration of the attack phase of the ADSR envelope in ‎milliseconds.‎
  • decay: duration of the decay phase of the ADSR envelope in milliseconds.
  • sustain: volume of the sustain phase (of duration hold milliseconds) ‎between 0 and 100.
  • release: duration of the release phase of the ADSR envelope in ‎milliseconds.
  • bend / bend_ms: number of hz to shift frequency by ‎every bend_ms milliseconds.‎
  • reverb: number of milliseconds before reverb is triggered.
  • noise: percentage of noise to mix into sound from 0 to 100.
  • distort: level of distortion (bit crushing) to apply from 0 to 100.‎

play(voice, frequency, [duration], [volume])‎

Play the supplied voice at frequency. Optionally set the duration in milliseconds ‎and volume between 0 and 100.‎


Returns the current audio playback position in milliseconds or -1 if no audio is ‎playing.‎


These functions provide access to the PicoSystem hardware features.‎


‎Returns true if input b has just been pressed. This function only ‎returns true when called from the first update() after the key press occurred - ‎ideal for events that trigger on press like jumping. b can be one ‎of A, B, X, Y, UP, DOWN, LEFT, and RIGHT.‎


Returns true if input b is currently pressed. This function will always return the ‎current input state - useful for events that require long presses like ‎walking. b can be one of A, B, X, Y, UP, DOWN, LEFT, and RIGHT.‎


Returns the current battery level as a number between 0 and 100.‎


Set the backlight brightness to b - between 0 and 100.‎

led(r, g, b)‎

Set the brightness of the RGB LED - each channel is between 0 and 100.‎


A collection of helpful functions that provide features which are a bit of a ‎chore to implement yourself.‎

str(n, [d])

Convert the number n into a string optionally limiting the number of decimal ‎places to d.‎

time() or time_us()

‎Return the time since PicoSystem started in milliseconds or microseconds.

‎sleep(d) or sleep_us(d)

‎Sleep for d milliseconds or microseconds.

‎rgb(r, g, b, [a]) or hsv(h, s, v, [a])‎

Returns a new colour created from red, green, and blue values or hue, ‎saturation, and value - both with optional alpha.‎

buffer(w, h, [data])

‎Returns a new buffer of width w and height h. If data is supplied, then it will be ‎used as the storage for pixel data and must be at least w * h * 2 bytes long.‎

intersects(x1, y1, w1, h1, x2, y2, w2, h2)‎

Returns true if the first rectangle intersects with the second rectangle.‎

intersection(x1, y1, w1, h1, x2, y2, w2, h2)‎

Modifies the first rectangle to be the intersection between the first rectangle ‎and the second rectangle.

contains(x1, y1, x2, y2, w2, h2)

‎Returns true if the point x1, y1 is inside the rectangle.‎

contains(x1, y1, w1, h1, x2, y2, w2, h2)‎

Returns true if the first rectangle is completely inside the second rectangle.‎

measure(message, w, h, [wrap])

‎Modifies w and h to be the width and height of the bounding box that would ‎contain message if it was drawn with text().

‎fsin(v) or fcos(v)‎

Fast, low resolution, implementations of sin and cos functions.‎

mix(c1, c2, m)‎

Returns a mixed colour between c1 and c2 based on the value of m which is ‎between 0 and 15.‎



  • COPY: Copy source pixels to destination ignoring alpha. The fastest blend ‎mode due to its simplicity, ideal if you're drawing with solid colours or ‎blitting images without transparency.
  • ALPHA: Blend the source pixels with the destination using the source ‎alpha. Allows for "overlaying" transparency effects such as glass or ‎water. Relatively slow due to the complexity of the calculations needed ‎per pixel.‎
  • MASK: Copy source pixels to destination only if source alpha is not zero. ‎Ideal for blitting images that just need 1-bit transparency.
  • PEN: Same as ALPHA but uses the current pen colour instead of source ‎colour when blitting. Useful for masking sprites or drawing their shape ‎in a single colour (e.g. shadows).‎
  • DARKEN: Compares source and destination colour channels and selects ‎the darker of the two.‎
  • LIGHTEN: Compares source and destination colour channels and selects ‎the lighter of the two.‎
  • ADD: Adds source and destination channels clamping for overflow if ‎needed.
  • SUBTRACT: Subtracts source and destination channels clamping for ‎underflow if needed.‎
  • MULTIPLY: Multiplies source and destination channels clamping for ‎overflow if needed.
  • DISSOLVE: Selects either source or destination colour depending on a ‎comparison of a hash of the destination pointer and the source/global ‎alpha. Similar to the "air brush" effect in early 90s paint programs.‎

That's all folks!‎

Key Parts and Components

Add all Digi-Key Parts to Cart
  • 1778-PIM559-ND

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.

Visit TechForum