├── .gitignore ├── .gitmodules ├── README.md ├── firmware ├── .gitignore ├── 1bitsy-1up.sublime-project ├── LICENSE_GPLV3.txt ├── LICENSE_LGPLV3.txt ├── Makefile ├── README.md ├── libopencm3.rules.mk ├── libopencm3.target.mk ├── scripts │ └── black_magic_probe_flash.scr └── src │ ├── 1bitsy-stm32f415rgt-gfx.ld │ ├── Makefile │ ├── README.md │ ├── assets │ ├── .gitignore │ ├── 1bitsy-1up-game1.tmx │ ├── README.md │ ├── fblocks.png │ ├── gen-assets.py │ ├── spritesheet.png │ └── tilesheet.png │ ├── audio.c │ ├── audio.h │ ├── audio_app.c │ ├── audio_app.h │ ├── button_boot.c │ ├── button_boot.h │ ├── fblocks_app.c │ ├── fblocks_app.h │ ├── gamepad.c │ ├── gamepad.h │ ├── gfx-pixslice.c │ ├── gfx-pixslice.h │ ├── gfx-types.h │ ├── gpio.c │ ├── gpio.h │ ├── i2c.c │ ├── i2c.h │ ├── intr.h │ ├── lcd.c │ ├── lcd.h │ ├── led.c │ ├── led.h │ ├── main.c │ ├── math-util.h │ ├── munch_app.c │ ├── munch_app.h │ ├── pam8019.c │ ├── pam8019.h │ ├── systick.c │ ├── systick.h │ ├── text.c │ ├── text.h │ ├── tile_app.c │ ├── tile_app.h │ ├── touch.c │ ├── touch.h │ ├── volume.c │ └── volume.h └── hardware ├── NOTES.md ├── V0.1 ├── 1bitsy-1up-cache.lib ├── 1bitsy-1up.kicad_pcb ├── 1bitsy-1up.pro └── 1bitsy-1up.sch ├── contrib └── 1up-mini │ ├── 1up-mini-cache.lib │ ├── 1up-mini.kicad_pcb │ ├── 1up-mini.pro │ ├── 1up-mini.sch │ ├── README.md │ └── fp-lib-table └── v0.2 ├── 1bitsy-1up-cache.lib ├── 1bitsy-1up.kicad_pcb ├── 1bitsy-1up.pro ├── 1bitsy-1up.sch ├── 1bitsy.sch ├── icebreaker.sch └── sym-lib-table /.gitignore: -------------------------------------------------------------------------------- 1 | *bak 2 | _autosave-* 3 | *.net 4 | *.zip 5 | .gdbinit 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hardware/lib/pkl"] 2 | path = hardware/lib/pkl 3 | url = https://github.com/esden/pretty-kicad-libs.git 4 | [submodule "hardware/lib/1bitsy"] 5 | path = hardware/lib/1bitsy 6 | url = https://github.com/1Bitsy/1bitsy-hardware-lib.git 7 | [submodule "lib/pkl"] 8 | path = lib/pkl 9 | url = https://github.com/esden/pretty-kicad-libs.git 10 | [submodule "firmware/libopencm3"] 11 | path = firmware/libopencm3 12 | url = https://github.com/libopencm3/libopencm3.git 13 | [submodule "firmware/src/assets/miniwi"] 14 | path = firmware/src/assets/miniwi 15 | url = https://github.com/josuah/miniwi.git 16 | [submodule "hardware/lib/stm32"] 17 | path = hardware/lib/stm32 18 | url = https://github.com/esden/stm32-kicad-lib.git 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Join the chat at https://gitter.im/1bitsy/1bitsy-1up](https://badges.gitter.im/1bitsy/1bitsy-1up.svg)](https://gitter.im/1bitsy/1bitsy-1up?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 2 | 3 | This repository contains the board and code used on the 1Bitsy 1UP. 4 | 5 | ## Intro 6 | 7 | 1Bitsy 1UP is a retro inspired handheld game console, the design is based 8 | around the following __semi arbitrary constraints and requirements.__ 9 | 10 | * Formfactor: PCB the size of the inside of a GB DMG (the gray one) This will 11 | hopefully eventually allow us to put the 1UP pcb inside a modified GB DMG 12 | case, either original or new molds sold by several online stores. 13 | * Main CPU: All code should be able to execute on a 1Bitsy that is fitted with 14 | an STM32F415RGT6. That particular chip (due to the package size) does not 15 | contain external ram support or LCD display engine. Making LCD drive little 16 | bit more tricky. It is a nice constraint that makes coding for the platform 17 | bit more of a challenge in the style of classic conloles and 8bit computers 18 | because it does not have enough memory for a full framebuffer. ("racing the 19 | beam" FTW) 20 | * Main CPU Mounting: The board contains the 1Bitsy compatible low profile 21 | socket using [SL-115-TT-19](https://www.samtec.com/products/sl-115-tt-19) 22 | and [BBL-115-T-E](https://www.samtec.com/products/bbl-115-t-e) Samtec 23 | connectors as well as one MillMax PogoPin spring loaded SMD connector. 24 | * LCD: The LCD is a 240x320 TFT display with capacitive touch, connected 25 | through the 8bit parallel interface to the 1Bitsy. This allows us to push the 26 | data speed to the display quite high and reach good framerates that would not 27 | be possible through the SPI interface. The capacitive touch screen adds an 28 | interesting aspect of control that was not available on classic consoles 29 | prior to DS. (That was also resistive not capacitive) 30 | * Audio: We are connecting the STM32F4 built in DAC lines for audio generation. 31 | This is not as slick and good as an i2s part but will likely make things 32 | "interesting". 33 | * Controls: The gamepad consists of the classic D-Pad, ABXY, Select, Start set 34 | of buttons. Because we have the capacitive touch no other analog controls are 35 | considered necessary. 36 | * Storage: To simplify storing games and data in large quantities we have 37 | connected a microSD card over the SDIO interface to the STM32, allowing for 38 | reasonabely fast load and save times and maybe even some other interesting 39 | hacks. 40 | * Expansion: The platform will receive future expansions and improvements that 41 | will strive to remain transparent. Meaning all code written for the first 42 | version of the platform should work either out of the box or only with very 43 | minor modifications. 44 | 45 | The display used is a TFT LCD with I2C CapTouch and ILI9341 driver. 46 | 47 | __The most basic design consists of:__ 48 | * 1Bitsy STM32F415RGT6 (168MHz, 192kb RAM, 1MB Flash) 49 | * 240x320 2.8" TFT with capacitive touch and PWM backlight control 50 | * D-Pad, ABXY, Start, Select buttons 51 | * DAC audio out to headphones. (speakers optional) 52 | * SDCard connected over SDIO interface 53 | 54 | Second tier addons for quality of life: 55 | * Lipo battery and charger built in 56 | * Speaker audio 57 | 58 | __Future "transparent" expansions:__ 59 | These expansions will contribute to new and interesting hacks possible on the 60 | platform, they are not considered forward compatible but backward compatible. 61 | This means that we do not anticipate the expansions to exist from the beginning 62 | of the platform life and the software written at that time will not support the 63 | future expansions, but the old software has to function as is or only with very 64 | minor changes on the new device that contains the new expansions. 65 | 66 | ## Hacking 67 | 68 | The board design is in the hardware subdirectory. 69 | -------------------------------------------------------------------------------- /firmware/.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.elf 3 | *.map 4 | *.o 5 | *.bin 6 | *.hex 7 | *.sublime-workspace 8 | -------------------------------------------------------------------------------- /firmware/1bitsy-1up.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": ".", 6 | "file_exclude_patterns": ["*.elf", "*.bin", "*.hex", "*.d", "*.o", "*.map"] 7 | }, 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /firmware/LICENSE_LGPLV3.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /firmware/Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is part of the libopencm3 project. 3 | ## 4 | ## Copyright (C) 2009 Uwe Hermann 5 | ## 6 | ## This library is free software: you can redistribute it and/or modify 7 | ## it under the terms of the GNU Lesser General Public License as published by 8 | ## the Free Software Foundation, either version 3 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This library is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU Lesser General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU Lesser General Public License 17 | ## along with this library. If not, see . 18 | ## 19 | 20 | PREFIX ?= arm-none-eabi 21 | #PREFIX ?= arm-elf 22 | 23 | # Be silent per default, but 'make V=1' will show all compiler calls. 24 | ifneq ($(V),1) 25 | Q := @ 26 | # Do not print "Entering directory ...". 27 | MAKEFLAGS += --no-print-directory 28 | endif 29 | 30 | # In case you are using an older compiler or want to set the C standard to a 31 | # specific version globally for the project this is where that would go. 32 | #CFLAGS += -std=gnu11 33 | 34 | OPENCM3_DIR := $(realpath libopencm3) 35 | BUILD_RULES = elf 36 | 37 | all: build 38 | 39 | bin: BUILD_RULES += bin 40 | hex: BUILD_RULES += hex 41 | srec: BUILD_RULES += srec 42 | list: BUILD_RULES += list 43 | images: BUILD_RULES += images 44 | 45 | bin: build 46 | hex: build 47 | srec: build 48 | list: build 49 | images: build 50 | 51 | build: lib src 52 | 53 | lib: 54 | $(Q)if [ ! "`ls -A libopencm3`" ] ; then \ 55 | printf "######## ERROR ########\n"; \ 56 | printf "\tlibopencm3 is not initialized.\n"; \ 57 | printf "\tPlease run:\n"; \ 58 | printf "\t$$ git submodule init\n"; \ 59 | printf "\t$$ git submodule update\n"; \ 60 | printf "\tbefore running make.\n"; \ 61 | printf "######## ERROR ########\n"; \ 62 | exit 1; \ 63 | fi 64 | $(Q)$(MAKE) -C libopencm3 lib TARGETS="stm32/f4" 65 | 66 | src: lib 67 | @printf " BUILD $@\n"; 68 | $(Q)$(MAKE) --directory=$@ OPENCM3_DIR=$(OPENCM3_DIR) $(BUILD_RULES) 69 | 70 | flash: src 71 | @printf " FLASH $@\n"; 72 | $(Q)$(MAKE) --directory=src flash 73 | 74 | clean: 75 | $(Q)$(MAKE) -C libopencm3 clean 76 | $(Q)$(MAKE) -C src clean 77 | 78 | stylecheck: src.stylecheck 79 | styleclean: src.styleclean 80 | 81 | 82 | %.clean: 83 | $(Q)if [ -d $* ]; then \ 84 | printf " CLEAN $*\n"; \ 85 | $(MAKE) -C $* clean OPENCM3_DIR=$(OPENCM3_DIR) || exit $?; \ 86 | fi; 87 | 88 | %.styleclean: 89 | $(Q)$(MAKE) -C $* styleclean OPENCM3_DIR=$(OPENCM3_DIR) 90 | 91 | %.stylecheck: 92 | $(Q)$(MAKE) -C $* stylecheck OPENCM3_DIR=$(OPENCM3_DIR) 93 | 94 | 95 | .PHONY: build lib examples install clean stylecheck styleclean \ 96 | bin hex srec list images 97 | 98 | -------------------------------------------------------------------------------- /firmware/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | This repository/directory contains code for the 1Bitsy 1UP retro inspired 4 | handheld game console. Expect it to morph and change as the time goes by. Feel 5 | free to rip out the code you need for your 1bitsy projects. But respect the 6 | licenses of the files. 7 | 8 | 1UP is a retro inspired handheld game console subproject of the 1Bitsy dev 9 | board project. 10 | 11 | For more information visit https://hackaday.io/project/25632-1bitsy-1up 12 | 13 | The 1Bitsy is an open hardware stm32F415 based small microcontroller development 14 | board. 15 | 16 | For more information visit http://1bitsy.org 17 | 18 | The libopencm3 project aims to create an open-source firmware library for 19 | various ARM Cortex-M3 microcontrollers. 20 | 21 | For more information visit http://libopencm3.org 22 | 23 | ## Usage 24 | 25 | You will have to fetch the libopencm3 submodule by running: 26 | 27 | git submodule init 28 | git submodule update 29 | 30 | You compile the needed part of the library and the project firmware by invoking 31 | "make" in the toplevel directory. 32 | 33 | Executing "make flash" will try to use arm-none-eabi-gdb to connect ta a Black 34 | Magic Probe and upload the firmware to your target. 35 | 36 | ## Notes 37 | 38 | If you are using an older GCC compiler. (pre V5) You may need to provide the C 39 | standard to the compiler. Otherwise the compiler might complain. To solve the 40 | issue you can invoke the `make` command in the top level directory by setting the 41 | `CFLAGS` variable: 42 | ``` 43 | CFLAGS=-std=c99 make 44 | ``` 45 | 46 | If your own project is using some specific extensions to the C standard you can 47 | add the necessary `CFLAGS` variable setting to your project Makefile in the src 48 | subdirectory. 49 | 50 | ## Contributions 51 | 52 | Pull requests simplifying improving modularizing and all the polish possible 53 | are very welcome! Join the 1Bitsy 1UP community at: 54 | https://gitter.im/1bitsy/1bitsy-1up 55 | -------------------------------------------------------------------------------- /firmware/libopencm3.rules.mk: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is part of the libopencm3 project. 3 | ## 4 | ## Copyright (C) 2009 Uwe Hermann 5 | ## Copyright (C) 2010 Piotr Esden-Tempski 6 | ## Copyright (C) 2013 Frantisek Burian 7 | ## 8 | ## This library is free software: you can redistribute it and/or modify 9 | ## it under the terms of the GNU Lesser General Public License as published by 10 | ## the Free Software Foundation, either version 3 of the License, or 11 | ## (at your option) any later version. 12 | ## 13 | ## This library is distributed in the hope that it will be useful, 14 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ## GNU Lesser General Public License for more details. 17 | ## 18 | ## You should have received a copy of the GNU Lesser General Public License 19 | ## along with this library. If not, see . 20 | ## 21 | 22 | # Be silent per default, but 'make V=1' will show all compiler calls. 23 | ifneq ($(V),1) 24 | Q := @ 25 | NULL := 2>/dev/null 26 | endif 27 | 28 | ############################################################################### 29 | # Executables 30 | 31 | PREFIX ?= arm-none-eabi 32 | 33 | CC := $(PREFIX)-gcc 34 | CXX := $(PREFIX)-g++ 35 | LD := $(PREFIX)-gcc 36 | AR := $(PREFIX)-ar 37 | AS := $(PREFIX)-as 38 | OBJCOPY := $(PREFIX)-objcopy 39 | OBJDUMP := $(PREFIX)-objdump 40 | GDB := $(PREFIX)-gdb 41 | STFLASH = $(shell which st-flash) 42 | STYLECHECK := /checkpatch.pl 43 | STYLECHECKFLAGS := --no-tree -f --terse --mailback 44 | STYLECHECKFILES := $(shell find . -name '*.[ch]') 45 | 46 | 47 | ############################################################################### 48 | # Source files 49 | 50 | LDSCRIPT ?= $(BINARY).ld 51 | 52 | OBJS += 53 | 54 | 55 | ifeq ($(strip $(OPENCM3_DIR)),) 56 | # user has not specified the library path, so we try to detect it 57 | 58 | # where we search for the library 59 | LIBPATHS := ./libopencm3 ../libopencm3 60 | 61 | OPENCM3_DIR := $(wildcard $(LIBPATHS:=/locm3.sublime-project)) 62 | OPENCM3_DIR := $(firstword $(dir $(OPENCM3_DIR))) 63 | 64 | ifeq ($(strip $(OPENCM3_DIR)),) 65 | $(warning Cannot find libopencm3 library in the standard search paths.) 66 | $(error Please specify it through OPENCM3_DIR variable!) 67 | endif 68 | endif 69 | 70 | ifeq ($(V),1) 71 | $(info Using $(OPENCM3_DIR) path to library) 72 | endif 73 | 74 | INCLUDE_DIR = $(OPENCM3_DIR)/include 75 | LIB_DIR = $(OPENCM3_DIR)/lib 76 | SCRIPT_DIR = ../scripts 77 | 78 | ############################################################################### 79 | # C flags 80 | 81 | CFLAGS += -g 82 | CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration 83 | CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes 84 | CFLAGS += -fno-common -ffunction-sections -fdata-sections 85 | 86 | ############################################################################### 87 | # C++ flags 88 | 89 | CXXFLAGS += -Os -g 90 | CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++ 91 | CXXFLAGS += -fno-common -ffunction-sections -fdata-sections 92 | 93 | ############################################################################### 94 | # C & C++ preprocessor common flags 95 | 96 | CPPFLAGS += -MD 97 | CPPFLAGS += -Wall -Wundef 98 | CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS) 99 | 100 | ############################################################################### 101 | # Linker flags 102 | 103 | LDFLAGS += --static -nostartfiles 104 | LDFLAGS += -L$(LIB_DIR) 105 | LDFLAGS += -T$(LDSCRIPT) 106 | LDFLAGS += -Wl,-Map=$(*).map 107 | LDFLAGS += -Wl,--gc-sections 108 | ifeq ($(V),99) 109 | LDFLAGS += -Wl,--print-gc-sections 110 | endif 111 | 112 | ############################################################################### 113 | # Used libraries 114 | 115 | LDLIBS += -l$(LIBNAME) 116 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 117 | 118 | ############################################################################### 119 | ############################################################################### 120 | ############################################################################### 121 | 122 | .SUFFIXES: .elf .bin .hex .srec .list .map .images 123 | .SECONDEXPANSION: 124 | .SECONDARY: 125 | 126 | all: elf 127 | 128 | elf: $(BINARY).elf 129 | bin: $(BINARY).bin 130 | hex: $(BINARY).hex 131 | srec: $(BINARY).srec 132 | list: $(BINARY).list 133 | 134 | images: $(BINARY).images 135 | flash: $(BINARY).flash 136 | stlink-flash: $(BINARY).stlink-flash 137 | 138 | %.images: %.bin %.hex %.srec %.list %.map 139 | @printf "*** $* images generated ***\n" 140 | 141 | %.bin: %.elf 142 | @printf " OBJCOPY $(*).bin\n" 143 | $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin 144 | 145 | %.hex: %.elf 146 | @printf " OBJCOPY $(*).hex\n" 147 | $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex 148 | 149 | %.srec: %.elf 150 | @printf " OBJCOPY $(*).srec\n" 151 | $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec 152 | 153 | %.list: %.elf 154 | @printf " OBJDUMP $(*).list\n" 155 | $(Q)$(OBJDUMP) -S $(*).elf > $(*).list 156 | 157 | %.elf %.map: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a 158 | @printf " LD $(*).elf\n" 159 | $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(*).elf 160 | 161 | %.o: %.c 162 | @printf " CC $(*).c\n" 163 | $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).c 164 | 165 | %.o: %.cxx 166 | @printf " CXX $(*).cxx\n" 167 | $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx 168 | 169 | %.o: %.cpp 170 | @printf " CXX $(*).cpp\n" 171 | $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp 172 | 173 | clean:: 174 | @printf " CLEAN\n" 175 | $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map 176 | 177 | stylecheck: $(STYLECHECKFILES:=.stylecheck) 178 | styleclean: $(STYLECHECKFILES:=.styleclean) 179 | 180 | # the cat is due to multithreaded nature - we like to have consistent chunks of text on the output 181 | %.stylecheck: % 182 | $(Q)$(SCRIPT_DIR)$(STYLECHECK) $(STYLECHECKFLAGS) $* > $*.stylecheck; \ 183 | if [ -s $*.stylecheck ]; then \ 184 | cat $*.stylecheck; \ 185 | else \ 186 | rm -f $*.stylecheck; \ 187 | fi; 188 | 189 | %.styleclean: 190 | $(Q)rm -f $*.stylecheck; 191 | 192 | 193 | %.stlink-flash: %.bin 194 | @printf " FLASH $<\n" 195 | $(Q)$(STFLASH) write $(*).bin 0x8000000 196 | 197 | ifeq ($(OOCD_SERIAL),) 198 | %.oocd-flash: %.hex 199 | @printf " FLASH $<\n" 200 | @# IMPORTANT: Don't use "resume", only "reset" will work correctly! 201 | $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ 202 | -f board/$(OOCD_BOARD).cfg \ 203 | -c "init" -c "reset init" \ 204 | -c "flash write_image erase $(*).hex" \ 205 | -c "reset" \ 206 | -c "shutdown" $(NULL) 207 | else 208 | %.oocd-flash: %.hex 209 | @printf " FLASH $<\n" 210 | @# IMPORTANT: Don't use "resume", only "reset" will work correctly! 211 | $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ 212 | -f board/$(OOCD_BOARD).cfg \ 213 | -c "ft2232_serial $(OOCD_SERIAL)" \ 214 | -c "init" -c "reset init" \ 215 | -c "flash write_image erase $(*).hex" \ 216 | -c "reset" \ 217 | -c "shutdown" $(NULL) 218 | endif 219 | 220 | ifeq ($(BMP_PORT),) 221 | BMP_PORT_CANDIDATES := $(wildcard \ 222 | /dev/serial/by-id/usb-Black_Sphere_Technologies_Black_Magic_Probe_*-if00 \ 223 | /dev/cu.usbmodem*1) 224 | ifeq ($(words $(BMP_PORT_CANDIDATES)),1) 225 | BMP_PORT := $(BMP_PORT_CANDIDATES) 226 | else 227 | BMP_PORT = $(error Black Magic Probe gdb serial port not found, please provide the device name via the BMP_PORT variable parameter$(if \ 228 | $(BMP_PORT_CANDIDATES), (found $(BMP_PORT_CANDIDATES)))) 229 | endif 230 | endif 231 | %.flash: %.elf 232 | @printf " BMP $(BMP_PORT) $(*).elf (flash)\n" 233 | $(Q)$(GDB) -nx --batch \ 234 | -ex 'target extended-remote $(BMP_PORT)' \ 235 | -x $(SCRIPT_DIR)/black_magic_probe_flash.scr \ 236 | $(*).elf 237 | 238 | .PHONY: images clean stylecheck styleclean elf bin hex srec list 239 | 240 | -include $(OBJS:.o=.d) 241 | -------------------------------------------------------------------------------- /firmware/libopencm3.target.mk: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is part of the libopencm3 project. 3 | ## 4 | ## Copyright (C) 2009 Uwe Hermann 5 | ## Copyright (C) 2010 Piotr Esden-Tempski 6 | ## Copyright (C) 2011 Fergus Noble 7 | ## 8 | ## This library is free software: you can redistribute it and/or modify 9 | ## it under the terms of the GNU Lesser General Public License as published by 10 | ## the Free Software Foundation, either version 3 of the License, or 11 | ## (at your option) any later version. 12 | ## 13 | ## This library is distributed in the hope that it will be useful, 14 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ## GNU Lesser General Public License for more details. 17 | ## 18 | ## You should have received a copy of the GNU Lesser General Public License 19 | ## along with this library. If not, see . 20 | ## 21 | 22 | LIBNAME = opencm3_stm32f4 23 | DEFS = -DSTM32F4 24 | 25 | FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16 26 | ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS) 27 | 28 | ################################################################################ 29 | # OpenOCD specific variables 30 | 31 | OOCD ?= openocd 32 | OOCD_INTERFACE ?= stlink-v2 33 | OOCD_BOARD ?= stm32f4discovery 34 | 35 | ################################################################################ 36 | # Black Magic Probe specific variables 37 | # Set the BMP_PORT to a serial port and then BMP is used for flashing 38 | BMP_PORT ?= 39 | 40 | ################################################################################ 41 | # texane/stlink specific variables 42 | #STLINK_PORT ?= :4242 43 | 44 | 45 | include ../libopencm3.rules.mk 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /firmware/scripts/black_magic_probe_flash.scr: -------------------------------------------------------------------------------- 1 | # Disable asking for confirmation. (All questions are automatically answered 2 | # with y if ran in batch mode, but it still prints warnings that don't look 3 | # very good. :D ) 4 | set confirm off 5 | # Print the Black Magic Probe firmware version 6 | monitor version 7 | # Optional: Enable target power 8 | #monitor tpwr enable 9 | # Optional: Enable system Reset on connect 10 | #monitor connect_srst enable 11 | # Alternative: Use JTAG protocol to talk to the target 12 | #monitor jtag_scan 13 | # Scan for targets using SWD protocol 14 | monitor swdp_scan 15 | # Attach to the first device found 16 | attach 1 17 | # Erase and load the provided binary to flash 18 | load 19 | # Compare the loaded sections to the ones in the provided binary 20 | compare-sections 21 | # Reset and disconnect from the target 22 | kill 23 | -------------------------------------------------------------------------------- /firmware/src/1bitsy-stm32f415rgt-gfx.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * Copyright (C) 2011 Stephen Caudle 6 | * 7 | * This library is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library. If not, see . 19 | */ 20 | 21 | /* Linker script for 1Bitsy (STM32F415RGT, 1024K flash, 128K RAM). */ 22 | 23 | /* Define memory regions. */ 24 | MEMORY 25 | { 26 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K 27 | ram (rwx) : ORIGIN = 0x10000000, LENGTH = 64K /* Core Coupled RAM */ 28 | sram1 (rwx) : ORIGIN = 0x20000000, LENGTH = 112K /* System RAM 1 */ 29 | sram2 (rwx) : ORIGIN = 0x2001C000, LENGTH = 16K /* System RAM 2 */ 30 | } 31 | 32 | SECTIONS 33 | { 34 | .sram1 (NOLOAD) : { 35 | sram1_start = .; 36 | sram1_end = . + 112K; 37 | *(.sram1) 38 | } >sram1 39 | .sram2 (NOLOAD) : { 40 | sram2_start = .; 41 | sram2_end = . + 16K; 42 | *(.sram2) 43 | } >sram2 44 | } 45 | 46 | /* Include the common ld script. */ 47 | INCLUDE libopencm3_stm32f4.ld 48 | 49 | -------------------------------------------------------------------------------- /firmware/src/Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is part of the libopencm3 project. 3 | ## 4 | ## Copyright (C) 2017 Piotr Esden-Tempski 5 | ## 6 | ## This library is free software: you can redistribute it and/or modify 7 | ## it under the terms of the GNU Lesser General Public License as published by 8 | ## the Free Software Foundation, either version 3 of the License, or 9 | ## (at your option) any later version. 10 | ## 11 | ## This library is distributed in the hope that it will be useful, 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ## GNU Lesser General Public License for more details. 15 | ## 16 | ## You should have received a copy of the GNU Lesser General Public License 17 | ## along with this library. If not, see . 18 | ## 19 | 20 | BINARY = 1up-native 21 | 22 | OBJS := main.o audio.o audio_app.o button_boot.o gamepad.o \ 23 | gfx-pixslice.o gpio.o i2c.o lcd.o led.o munch_app.o systick.o \ 24 | text.o tile_app.o volume.o touch.o pam8019.o fblocks_app.o 25 | 26 | LDSCRIPT = 1bitsy-stm32f415rgt-gfx.ld 27 | 28 | V = 1 29 | include ../libopencm3.target.mk 30 | 31 | # You can enable size optimization for project deployment, but it can get 32 | # in the way of debugging your code 33 | cflags := $(filter_out -O%, $(CFLAGS)) -Werror -g 34 | # In theory this -O should be valid for everything but video.o but somehow it 35 | # affects everything? :( 36 | OPT := -O3 37 | CFLAGS = $(cflags) $(OPT) 38 | 39 | # If your project is using a specific C standard you can set it by uncommenting 40 | # the following line and adjusting the -std flag accordingly 41 | #CFLAGS += -std=gnu11 -pedantic 42 | 43 | LDLIBS += -lm 44 | 45 | lcd.o: OPT := -O0 46 | 47 | text.o tile_app.o: assets/assets.h 48 | 49 | assets/assets.h: assets/gen-assets.py assets/*.png assets/*.tmx assets/*/*.bdf 50 | @printf " ASSETS $?\n" 51 | $(Q)cd assets; python3 ./gen-assets.py > assets.h.new 52 | $(Q)mv assets/assets.h.new assets/assets.h 53 | 54 | clean:: 55 | $(Q)$(RM) -f assets/assets.h assets/assets.h.new 56 | 57 | 58 | -------------------------------------------------------------------------------- /firmware/src/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | This is the default firmware of the 1bitsy 1UP. 4 | 5 | It's intended for the 1Bitsy 1UP retro inspired handheld game console. 6 | 7 | ## Board connections 8 | 9 | *none required* 10 | -------------------------------------------------------------------------------- /firmware/src/assets/.gitignore: -------------------------------------------------------------------------------- 1 | assets.h 2 | -------------------------------------------------------------------------------- /firmware/src/assets/1bitsy-1up-game1.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 7 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 8 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,38,0,0,0,0,0,0,0,0,0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 9 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 10 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 11 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,16,16,0,0,0,0,0,0,0,195,195,195,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 12 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,7,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 13 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,7,7,7,8,0,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 14 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,16,16,0,0,0,0,0,6,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,3,3,3,3,0,0,0,0,0,0,0,6,7,7,7,8,0,0,0,0,0,0,0,0,0,2,3,3,27,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 15 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,49,27,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 16 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,7,7,8,0,0,6,7,7,8,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,195,195,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,2,3,3,1,1,1,1,1,1,0,6,7,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,49,27,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 17 | 0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,3,3,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,49,27,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 18 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,10,0,0,34,0,0,10,0,0,0,1,1,1,1,49,27,0,0,0,0,0,0,0,0,0,33,0,0,0,33,0,0,0,0,0,0,0,2,3,3,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,49,27,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 19 | 0,0,0,0,0,0,0,0,6,7,7,8,0,0,0,0,0,24,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,49,27,0,0,0,0,0,6,7,7,8,0,0,6,7,7,8,0,0,10,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,49,27,0,0,0,0,0,0,16,0,0,16,0,0,16,0,0,16,0,0,16,0,0,0,0,0,0,1, 20 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,46,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,49,27,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,49,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130, 21 | 0,10,0,0,0,0,0,0,12,0,0,0,34,0,10,24,46,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,49,3,3,4,233,233,233,233,233,233,233,233,233,233,233,233,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,1,1,1,1,1,1,1,1,1,49,27,0,10,0,33,0,34,0,0,0,0,0,10,0,0,0,0,0,0,0,191,0,0,0,152, 22 | 3,3,3,3,4,0,2,3,3,3,3,3,3,3,3,46,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,255,255,255,255,255,255,255,255,255,255,255,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,1,1,1,1,1,1,1,1,1,1,49,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 23 | 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,255,255,255,255,255,255,255,255,255,255,255,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /firmware/src/assets/README.md: -------------------------------------------------------------------------------- 1 | The graphic assets are based on the kenney.nl abstract-platformer tile set. It 2 | is licensed under CC0 1.0 Universal. 3 | 4 | You can find the original tileset at: 5 | http://www.kenney.nl/assets/abstract-platformer 6 | 7 | The assets created based on the kenny.nl abstract-platformer found in this 8 | directory are also licensed under CC0 1.0 Universal. 9 | -------------------------------------------------------------------------------- /firmware/src/assets/fblocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Bitsy/1bitsy-1up/54eddf3494c8faadea9018ee24a5c296e54b57db/firmware/src/assets/fblocks.png -------------------------------------------------------------------------------- /firmware/src/assets/gen-assets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from itertools import groupby 4 | import sys 5 | 6 | from PIL import Image 7 | from PIL import BdfFontFile 8 | from xml.etree import ElementTree 9 | 10 | white_pixel = 255 11 | 12 | defs = [] 13 | 14 | ######################################################################## 15 | # General helper functions 16 | ######################################################################## 17 | 18 | 19 | def by_n(n, seq): 20 | return ((x for (i, x) in g) 21 | for (k, g) in groupby(enumerate(seq), lambda x: x[0] // n)) 22 | 23 | 24 | def pack_rgb565(tup): 25 | return (tup[0] >> 3 << 11 | 26 | tup[1] >> 2 << 5 | 27 | tup[2] >> 3 << 0) 28 | 29 | 30 | def rgb888_to_rgb565(val): 31 | return (((val & 0xFF0000) >> 19) << 11 | 32 | ((val & 0x00FF00) >> 10) << 5 | 33 | ((val & 0x0000FF) >> 3) << 0) 34 | 35 | ######################################################################## 36 | # Definition functions 37 | ######################################################################## 38 | 39 | def pixmap(path, name): 40 | img = Image.open(path) 41 | img = img.convert("RGBA") 42 | pix = img.load() 43 | w, h = img.size 44 | packed = [[pack_rgb565(pix[x, y]) 45 | for x in range(w)] 46 | for y in range(h)] 47 | data = ',\n'.join(' {{ {} }}' 48 | .format(',\n '.join(', '.join('{:3d}'.format(b) 49 | for b in line) 50 | for line in by_n(8, row))) 51 | for row in packed) 52 | template = ''' 53 | #define {NAME}_PIXMAP_HEIGHT {h} 54 | #define {NAME}_PIXMAP_WIDTH {w} 55 | 56 | static const uint16_t {name}_pixmap[{NAME}_PIXMAP_HEIGHT][{NAME}_PIXMAP_WIDTH] = {{ 57 | {data} 58 | }};'''.lstrip() 59 | return template.format(name=name, NAME=name.upper(), h=h, w=w, data=data) 60 | 61 | def tilemap(path, name): 62 | e = ElementTree.parse(path).getroot() 63 | w = int(e.attrib['width']) 64 | h = int(e.attrib['height']) 65 | background = rgb888_to_rgb565(int(e.attrib['backgroundcolor'] 66 | .replace("#", ""), 16)) 67 | def filter_empty(x): 68 | return list(filter(lambda d: len(d) > 0, x)) 69 | # Split the data apart and remove empty stuff while doing it and convert the numbers to ints. 70 | layers = list(map(lambda l: list(map(lambda d: list(map(lambda i: int(i), filter_empty(d.split(",")))), 71 | filter_empty(l.find('data').text.split("\n")))), e.findall('layer'))) 72 | # Convert the gathered layer data into a usable C array. 73 | struct = ',\n'.join('{{ {} }}' 74 | .format(',\n ' 75 | .join('{{ {} }}' 76 | .format(',\n '.join(','.join('{:3d}'.format(b) 77 | for b in line) 78 | for line in by_n(16, row))) 79 | for row in layer)) 80 | for layer in layers) 81 | # We should restrict the tile indexes to 8bit, we can have multiple tilesets if needed... I don't think we need more 82 | # Than 255 tiles per tilemap. 83 | template = ''' 84 | #define {NAME}_TILEMAP_LAYERS {l} 85 | #define {NAME}_TILEMAP_HEIGHT {h} 86 | #define {NAME}_TILEMAP_WIDTH {w} 87 | #define {NAME}_TILEMAP_BG_COLOR {bg_color} 88 | 89 | static const uint16_t {name}_tilemap[{NAME}_TILEMAP_LAYERS][{NAME}_TILEMAP_HEIGHT][{NAME}_TILEMAP_WIDTH] = {{ 90 | {struct} 91 | }};'''.lstrip() 92 | return template.format(name=name, NAME=name.upper(), l=len(layers), h=h, w=w, 93 | bg_color=background, struct=struct) 94 | 95 | def font(path, name): 96 | ff = BdfFontFile.BdfFontFile(open(path, 'rb')) 97 | glyphs = [] 98 | for c in range(33, 127): 99 | glyph = [] 100 | glyph_pix = ff.glyph[c][3].load() 101 | for col in range(0, 4): 102 | col_byte = 0 103 | for row in range(0, 8): 104 | if glyph_pix[col, row] != 0: 105 | col_byte = col_byte | (0x1 << row) 106 | glyph.append(col_byte) 107 | glyphs.append(glyph) 108 | struct = ",\n".join('{{ {} }}'.format(", ".join('{:#04x}'.format(b) 109 | for b in glyph)) 110 | for glyph in glyphs) 111 | template = ''' 112 | #define {NAME}_FONT_WIDTH 4 113 | #define {NAME}_FONT_HEIGHT 8 114 | #define {NAME}_FONT_OFFSET 33 115 | #define {NAME}_FONT_GLYPH_COUNT {l} 116 | 117 | static const uint8_t {name}_font[{NAME}_FONT_GLYPH_COUNT][{NAME}_FONT_WIDTH] = {{ 118 | {struct} 119 | }};'''.lstrip() 120 | return template.format(name=name, NAME=name.upper(), l=len(glyphs), 121 | struct=struct) 122 | 123 | ######################################################################## 124 | # Game 1 125 | ######################################################################## 126 | 127 | defs += [ 128 | pixmap('tilesheet.png', 'ts'), 129 | pixmap('spritesheet.png', 'ss'), 130 | tilemap('1bitsy-1up-game1.tmx', 'tml1'), 131 | ] 132 | 133 | ######################################################################## 134 | # Falling blocks 135 | ######################################################################## 136 | 137 | defs += [ 138 | pixmap('fblocks.png', 'fblocks'), 139 | ] 140 | 141 | ######################################################################## 142 | # Miniwi font 143 | ######################################################################## 144 | 145 | defs += [ 146 | font('miniwi/miniwi-8.bdf', 'miniwi'), 147 | ] 148 | 149 | ######################################################################## 150 | # Asset header body and output 151 | ######################################################################## 152 | 153 | template = ''' 154 | #ifndef ASSETS_H 155 | #define ASSETS_H 156 | 157 | /* This file was automatically generated by {program}. Do not edit. */ 158 | 159 | #include 160 | 161 | {defs} 162 | 163 | #endif /* ASSETS_H */ 164 | '''.lstrip() 165 | 166 | print(template.format(program=sys.argv[0], defs='\n\n'.join(defs))) 167 | -------------------------------------------------------------------------------- /firmware/src/assets/spritesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Bitsy/1bitsy-1up/54eddf3494c8faadea9018ee24a5c296e54b57db/firmware/src/assets/spritesheet.png -------------------------------------------------------------------------------- /firmware/src/assets/tilesheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Bitsy/1bitsy-1up/54eddf3494c8faadea9018ee24a5c296e54b57db/firmware/src/assets/tilesheet.png -------------------------------------------------------------------------------- /firmware/src/audio.c: -------------------------------------------------------------------------------- 1 | #include "audio.h" 2 | 3 | #include 4 | 5 | #include 6 | #ifndef DAC_SR // XXX DAC_SR is missing? 7 | #define DAC_SR MMIO32(DAC_BASE + 0x34) 8 | #define DAC_SR_DMAUDR2 (1 << 29) 9 | #define DAC_SR_DMAUDR1 (1 << 13) 10 | #endif 11 | #include 12 | #include 13 | #include 14 | 15 | // The Reference Manual says TIM6 and TIM7 are for the DACs. We only 16 | // need one, so we use TIM6. 17 | // 18 | // 20.1 TIM6&TIM7 introduction 19 | // 20 | // They may be used as generic timers for time-base generation but 21 | // they are also specifically used to drive the digial-to-analog 22 | // converter (DAC). In fact, the timers are internally connected 23 | // to the DAC and are able to drive it through their trigger outputs. 24 | // 25 | // [Reference manual, Document RM0090] 26 | 27 | static uint32_t sample_rate; 28 | static audio_channel_count channel_count; 29 | static audio_sample_depth sample_depth; 30 | static void *sample_buffer; 31 | static size_t buffer_bytes; 32 | 33 | static audio_callback_fn *registered_callback; 34 | 35 | 36 | // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - 37 | 38 | 39 | uint32_t audio_get_sample_rate(void) 40 | { 41 | return sample_rate; 42 | } 43 | 44 | audio_channel_count audio_get_channel_count(void) 45 | { 46 | return channel_count; 47 | } 48 | 49 | audio_sample_depth audio_get_sample_depth(void) 50 | { 51 | return sample_depth; 52 | } 53 | 54 | void *audio_get_sample_buffer(void) 55 | { 56 | return sample_buffer; 57 | } 58 | 59 | size_t audio_get_frame_bytes(void) 60 | { 61 | return channel_count * sample_depth; 62 | } 63 | 64 | size_t audio_get_frame_count(void) 65 | { 66 | return buffer_bytes / audio_get_frame_bytes(); 67 | } 68 | 69 | size_t audio_get_byte_count(void) 70 | { 71 | return buffer_bytes; 72 | } 73 | 74 | 75 | // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - 76 | 77 | 78 | static void init_timer(void) 79 | { 80 | // XXX This happens to work but doesn't take into account all 81 | // XXX the ways the clocks could be configured. 82 | // XXX RCC_DCKCFGR.TIMPRE description: 83 | // XXX 84 | // XXX 0: If the APB prescaler (PPRE1, PPRE2 in the RCC_CFGR 85 | // XXX register) is configured to a division factor of 1, 86 | // XXX TIMxCLK = PCLKx. Otherwise, the timer clock 87 | // XXX frequencies are set to twice the frequency of the 88 | // XXX APB domain to which the timers are connected: 89 | // XXX TIMxCLK = 2xPCLKx. 90 | // XXX 1: If the APB prescaler (PPRE1, PPRE2 in the RCC_CFGR 91 | // XXX register) is configured to a division factor of 1, 92 | // XXX 2, or 4, TIMxCLK = HCLK. Otherwise, the timer clock 93 | // XXX frequencies are set to four times to the frequency 94 | // XXX [sic] of the APB domain to which the timers are 95 | // XXX connected: TIMxCLK = 4xPCLKx. 96 | 97 | uint32_t period = (2 * rcc_apb1_frequency + sample_rate / 2) / sample_rate; 98 | 99 | /* Enable TIM6 clock. */ 100 | rcc_periph_clock_enable(RCC_TIM6); 101 | rcc_periph_reset_pulse(RST_TIM6); 102 | /* Timer global mode: - No divider, Alignment edge, Direction up */ 103 | timer_set_mode(TIM6, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); 104 | timer_disable_preload(TIM6); 105 | timer_continuous_mode(TIM6); 106 | timer_update_on_overflow(TIM6); 107 | timer_set_period(TIM6, period); 108 | timer_set_master_mode(TIM6, TIM_CR2_MMS_UPDATE); 109 | } 110 | 111 | static void start_timer(void) 112 | { 113 | timer_enable_counter(TIM6); 114 | } 115 | 116 | static void stop_timer(void) 117 | { 118 | timer_disable_counter(TIM6); 119 | } 120 | 121 | 122 | // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - 123 | 124 | 125 | static void init_dma(void) 126 | { 127 | uint32_t mono_msize = 0, mono_psize = 0; 128 | uint32_t stereo_msize = 0, stereo_psize = 0; 129 | uint32_t cr_msize = 0, cr_psize = 0; 130 | volatile void *dhr1a = 0, *dhr2a = 0, *dhrda = 0; 131 | 132 | if (sample_depth == ASD_8BIT) { 133 | mono_msize = DMA_SxCR_MSIZE_8BIT; 134 | mono_psize = DMA_SxCR_PSIZE_8BIT; 135 | stereo_msize = DMA_SxCR_MSIZE_16BIT; 136 | stereo_psize = DMA_SxCR_PSIZE_16BIT; 137 | dhr1a = &DAC_DHR8R1; 138 | dhr2a = &DAC_DHR8R2; 139 | dhrda = &DAC_DHR8RD; 140 | } else if (sample_depth == ASD_12BIT) { 141 | mono_msize = DMA_SxCR_MSIZE_16BIT; 142 | mono_psize = DMA_SxCR_PSIZE_16BIT; 143 | stereo_msize = DMA_SxCR_MSIZE_32BIT; 144 | stereo_psize = DMA_SxCR_PSIZE_32BIT; 145 | dhr1a = &DAC_DHR12R1; 146 | dhr2a = &DAC_DHR12R2; 147 | dhrda = &DAC_DHR12RD; 148 | } 149 | 150 | if (channel_count == ACC_STEREO) { 151 | dhr1a = dhrda; 152 | cr_msize = stereo_msize; 153 | cr_psize = stereo_psize; 154 | } else if (channel_count == ACC_MONO) { 155 | cr_msize = mono_msize; 156 | cr_psize = mono_psize; 157 | } 158 | 159 | /* DAC channel 1 uses DMA controller 1 Stream 5 Channel 7. */ 160 | /* Enable DMA1 clock and IRQ */ 161 | rcc_periph_clock_enable(RCC_DMA1); 162 | 163 | /* Setup Stream5 Channel7 for DAC1 (mono) or both DACs (stereo) */ 164 | nvic_enable_irq(NVIC_DMA1_STREAM5_IRQ); 165 | dma_stream_reset(DMA1, DMA_STREAM5); 166 | dma_set_priority(DMA1, DMA_STREAM5, DMA_SxCR_PL_LOW); 167 | dma_set_memory_size(DMA1, DMA_STREAM5, cr_msize); 168 | dma_set_peripheral_size(DMA1, DMA_STREAM5, cr_psize); 169 | dma_enable_memory_increment_mode(DMA1, DMA_STREAM5); 170 | dma_enable_circular_mode(DMA1, DMA_STREAM5); 171 | dma_set_transfer_mode(DMA1, DMA_STREAM5, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); 172 | dma_set_peripheral_address(DMA1, DMA_STREAM5, (uint32_t) dhr1a); 173 | dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t) sample_buffer); 174 | dma_set_number_of_data(DMA1, DMA_STREAM5, audio_get_frame_count()); 175 | dma_enable_half_transfer_interrupt(DMA1, DMA_STREAM5); 176 | dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5); 177 | dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7); 178 | dma_enable_stream(DMA1, DMA_STREAM5); 179 | 180 | if (channel_count == ACC_MONO) { 181 | /* Setup Stream6 Channel7 for DAC2 */ 182 | dma_stream_reset(DMA1, DMA_STREAM6); 183 | dma_set_priority(DMA1, DMA_STREAM6, DMA_SxCR_PL_LOW); 184 | dma_set_memory_size(DMA1, DMA_STREAM6, cr_msize); 185 | dma_set_peripheral_size(DMA1, DMA_STREAM6, cr_psize); 186 | dma_enable_memory_increment_mode(DMA1, DMA_STREAM6); 187 | dma_enable_circular_mode(DMA1, DMA_STREAM6); 188 | dma_set_transfer_mode(DMA1, DMA_STREAM6, 189 | DMA_SxCR_DIR_MEM_TO_PERIPHERAL); 190 | dma_set_peripheral_address(DMA1, DMA_STREAM6, (uint32_t) dhr2a); 191 | dma_set_memory_address(DMA1, DMA_STREAM6, (uint32_t)sample_buffer); 192 | dma_set_number_of_data(DMA1, DMA_STREAM6, audio_get_frame_count()); 193 | dma_channel_select(DMA1, DMA_STREAM6, DMA_SxCR_CHSEL_7); 194 | dma_enable_stream(DMA1, DMA_STREAM6); 195 | } 196 | } 197 | 198 | static void stop_dma(void) 199 | { 200 | dma_disable_stream(DMA1, DMA_STREAM5); 201 | dma_disable_stream(DMA1, DMA_STREAM6); 202 | } 203 | 204 | void dma1_stream5_isr(void) 205 | { 206 | size_t half_frames = audio_get_frame_count() / 2; 207 | if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_HTIF)) { 208 | dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_HTIF); 209 | (*registered_callback)(sample_buffer, half_frames); 210 | } 211 | if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_TCIF)) { 212 | dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF); 213 | (*registered_callback)(sample_buffer + buffer_bytes / 2, half_frames); 214 | } 215 | } 216 | 217 | 218 | // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - 219 | 220 | 221 | static void init_dac() 222 | { 223 | uint32_t mamp1 = 0, mamp2 = 0; 224 | if (sample_depth == ASD_12BIT) { 225 | mamp1 = DAC_CR_MAMP1_1; 226 | mamp2 = DAC_CR_MAMP2_1; 227 | } else if (sample_depth == ASD_8BIT) { 228 | // Avoid quantization noise with a high masking noise. 229 | mamp1 = DAC_CR_MAMP1_5; 230 | mamp2 = DAC_CR_MAMP2_5; 231 | } 232 | 233 | /* Enable the DAC clock on APB1 */ 234 | rcc_periph_clock_enable(RCC_DAC); 235 | 236 | /* Setup the DAC channel 1 with timer 6 as trigger source. */ 237 | dac_trigger_enable(CHANNEL_1); 238 | dac_set_trigger_source(DAC_CR_TSEL1_T6); 239 | dac_dma_enable(CHANNEL_1); 240 | dac_enable(CHANNEL_1); 241 | dac_set_waveform_generation(DAC_CR_WAVE1_NOISE); 242 | dac_set_waveform_characteristics(mamp1); 243 | 244 | /* Setup the DAC channel 2 with timer 6 as trigger source. */ 245 | dac_trigger_enable(CHANNEL_2); 246 | dac_set_trigger_source(DAC_CR_TSEL2_T6); 247 | dac_dma_enable(CHANNEL_2); 248 | dac_enable(CHANNEL_2); 249 | dac_set_waveform_generation(DAC_CR_WAVE2_NOISE); 250 | dac_set_waveform_characteristics(mamp2); 251 | } 252 | 253 | static void stop_dac(void) 254 | { 255 | dac_load_data_buffer_dual(0, 0, RIGHT12); 256 | // Don't actually stop the DAC. Leave it running but stop feeding 257 | // it new samples. Otherwise it will probably click. 258 | } 259 | 260 | 261 | void audio_init(uint32_t Fs, 262 | audio_channel_count nchan, 263 | audio_sample_depth depth, 264 | void *buffer, 265 | size_t byte_count) 266 | { 267 | audio_stop(); 268 | 269 | sample_rate = Fs; 270 | channel_count = nchan; 271 | sample_depth = depth; 272 | if (buffer) { 273 | sample_buffer = buffer; 274 | buffer_bytes = byte_count; 275 | } 276 | } 277 | 278 | audio_callback_fn *audio_register_callback(audio_callback_fn *new) 279 | { 280 | audio_callback_fn *prev = registered_callback; 281 | registered_callback = new; 282 | return prev; 283 | } 284 | 285 | void audio_start(void) 286 | { 287 | init_timer(); 288 | init_dma(); 289 | init_dac(); 290 | start_timer(); 291 | } 292 | 293 | void audio_stop(void) 294 | { 295 | stop_dma(); 296 | stop_dac(); 297 | stop_timer(); 298 | } 299 | -------------------------------------------------------------------------------- /firmware/src/audio.h: -------------------------------------------------------------------------------- 1 | #ifndef AUDIO_included 2 | #define AUDIO_included 3 | 4 | #include 5 | #include 6 | 7 | 8 | // Terminology: 9 | // A `sample` is a single 8 or 12 bit PCM value. 10 | // A `frame` is a set of samples that should be emitted at the same instant. 11 | // (one sample for mono, two samples for stereo). 12 | // The sample rate is actually the number of frames per second, not samples. 13 | // 14 | // 12 bit samples are right-aligned: they come from the least 15 | // significant 12 bits of each 16 bit word. 16 | // 17 | // N.B., stereo mode causes less memory contention than mono. 18 | // So stereo may allow a higher video frame rate. 19 | 20 | 21 | typedef enum audio_channel_count { 22 | ACC_MONO = 1, 23 | ACC_STEREO = 2, 24 | } audio_channel_count; 25 | 26 | typedef enum audio_sample_depth { 27 | ASD_8BIT = 1, 28 | ASD_12BIT = 2, 29 | } audio_sample_depth; 30 | 31 | 32 | // Audio callback fills buffer with new frames. 33 | // 34 | // Type of buffer and number of samples depends on how audio was 35 | // initialized. 36 | // 37 | // Stereo channels are interleaved: even samples are left channel, odd 38 | // samples are right channel. 39 | // 40 | // sample_depth channel_count bytes_per_frame 41 | // 8 1 1 42 | // 8 2 2 43 | // 12 1 2 44 | // 12 2 4 45 | 46 | 47 | typedef void audio_callback_fn(void *frames_out, size_t frame_count); 48 | 49 | #define DEFINE_AUDIO_BUFFER(name, frames, channels, depth) \ 50 | static uint8_t name[2 * (frames) * (channels) * (depth)] \ 51 | __attribute__((section(".sram2"))); 52 | 53 | // Pass NULL for buffer to reuse existing buffer. 54 | extern void audio_init (uint32_t sample_rate, 55 | audio_channel_count, 56 | audio_sample_depth, 57 | void *buffer, 58 | size_t byte_count); 59 | 60 | extern uint32_t audio_get_sample_rate (void); 61 | extern audio_channel_count audio_get_channel_count (void); 62 | extern audio_sample_depth audio_get_sample_depth (void); 63 | extern void *audio_get_sample_buffer (void); 64 | extern size_t audio_get_frame_bytes (void); 65 | extern size_t audio_get_frame_count (void); 66 | extern size_t audio_get_byte_count (void); 67 | 68 | /* returns previous callback. */ 69 | extern audio_callback_fn *audio_register_callback (audio_callback_fn *); 70 | 71 | extern void audio_start (void); 72 | extern void audio_stop (void); 73 | 74 | #endif /* !AUDIO_included */ 75 | -------------------------------------------------------------------------------- /firmware/src/audio_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Piotr Esden-Tempski 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "audio_app.h" 21 | 22 | #include 23 | 24 | #include "audio.h" 25 | #include "button_boot.h" 26 | #include "gamepad.h" 27 | #include "lcd.h" 28 | #include "led.h" 29 | #include "math-util.h" 30 | #include "pam8019.h" 31 | #include "systick.h" 32 | #include "text.h" 33 | #include "volume.h" 34 | 35 | // Define these to test other audio paths. 36 | //#define MONO 37 | //#define BIT8 38 | 39 | #define Fs (44100.0) 40 | #define FREQ0 (440.0 / 8) // A1, 55Hz 41 | #define FREQ1 (523.3 / 8) // C2, 64 Hz 42 | 43 | #ifdef MONO 44 | #define ACC ACC_MONO 45 | #else 46 | #define ACC ACC_STEREO 47 | #endif 48 | 49 | #ifdef BIT8 50 | typedef uint8_t sample; 51 | #define SAMP_MAX 255 52 | #define ASD ASD_8BIT 53 | #else 54 | typedef uint16_t sample; 55 | #define SAMP_MAX 4095 56 | #define ASD ASD_12BIT 57 | #endif 58 | 59 | typedef enum text_row { 60 | TR_HEADER = 3, 61 | TR_INSTR = 5, 62 | TR_MODE = 7, 63 | TR_OUTPUT = 8, 64 | TR_VOL = 10, 65 | TR_VOLBAR = 11, 66 | TR_RAWVOL = 12, 67 | TR_RVBAR = 13, 68 | } text_row; 69 | 70 | typedef enum text_col { 71 | TC_LEFT = 4, 72 | } text_col; 73 | 74 | static const gfx_rgb565 bg_color = 0xF81F; 75 | static const gfx_rgb565 vol_color = 0x07E0; 76 | 77 | static bool vol_is_visible; 78 | static pam8019_mode cur_mode; 79 | static uint8_t vol; 80 | static uint8_t prev_vol; 81 | static uint16_t raw_vol; 82 | 83 | // char abuf[704] __attribute__((section(".sram2"))); 84 | #define FRAMES ((int)Fs / 250) 85 | DEFINE_AUDIO_BUFFER(abuf, FRAMES, ACC, ASD); 86 | 87 | #ifdef MONO 88 | 89 | static void audio_callback(void *buf, size_t frame_count) 90 | { 91 | sample *frames = buf; 92 | static float phase; 93 | 94 | for (size_t i = 0; i < frame_count; i++) { 95 | frames[i] = phase * SAMP_MAX; 96 | phase += FREQ0 / Fs; 97 | if (phase >= 1.0) 98 | phase -= 1.0; 99 | } 100 | } 101 | 102 | #else 103 | 104 | static void audio_callback(void *buf, size_t frame_count) 105 | { 106 | sample (*frames)[2] = buf; 107 | static float phase[2]; 108 | 109 | for (size_t i = 0; i < frame_count; i++) { 110 | frames[i][0] = phase[0] * SAMP_MAX; 111 | frames[i][1] = SAMP_MAX - phase[1] * SAMP_MAX; 112 | phase[0] += FREQ0 / Fs; 113 | phase[1] += FREQ1 / Fs; 114 | if (phase[0] >= 1.0) 115 | phase[0] -= 1.0; 116 | if (phase[1] >= 1.0) 117 | phase[1] -= 1.0; 118 | } 119 | } 120 | 121 | #endif 122 | 123 | void audio_app_init(void) 124 | { 125 | audio_init(44100, ACC, ASD, abuf, sizeof abuf); 126 | audio_register_callback(audio_callback); 127 | pam8019_set_mode(PM_NORMAL); 128 | audio_start(); 129 | prev_vol = volume_get(); 130 | } 131 | 132 | void audio_app_end(void) 133 | { 134 | audio_stop(); 135 | pam8019_set_mode(PM_SHUTDOWN); 136 | } 137 | 138 | void audio_animate(void) 139 | { 140 | // Volume control is visible if volume changed in last 800 msec. 141 | 142 | const uint32_t VOL_FADE_TIME = 800; 143 | static uint32_t vol_change_time = 0xF0000000; // large negative 144 | 145 | cur_mode = pam8019_get_mode(); 146 | vol = volume_get(); 147 | raw_vol = volume_get_raw(); 148 | 149 | if (prev_vol != vol) { 150 | prev_vol = vol; 151 | vol_change_time = system_millis; 152 | } 153 | vol_is_visible = system_millis - vol_change_time < VOL_FADE_TIME; 154 | 155 | uint16_t buttons = gamepad_get(); 156 | static uint16_t prev_buttons; 157 | 158 | if ((buttons & ~prev_buttons) & GAMEPAD_BSELECT) { 159 | 160 | cur_mode = pam8019_get_mode() + 1; 161 | if (cur_mode == PM_END) 162 | cur_mode = PM_START; 163 | pam8019_set_mode(cur_mode); 164 | } 165 | prev_buttons = buttons; 166 | } 167 | 168 | static void audio_draw_vol(gfx_pixslice *slice) 169 | { 170 | const int text_y = TR_VOL; 171 | const int text_x = TC_LEFT; 172 | const int bar_x = 8 * text_x; 173 | const int bar_y = TR_VOLBAR * 16; 174 | const int bar_h = 15; 175 | 176 | if (!vol_is_visible) { 177 | return; 178 | } 179 | 180 | 181 | int xoff = text_x; 182 | xoff = text_draw_str16(slice, "Volume: ", xoff, text_y, vol_color); 183 | 184 | /* hundreds place */ 185 | char h = vol < 100 ? ' ' : '0' + vol / 100 % 10; 186 | text_draw_char16(slice, h, xoff, text_y, vol_color); 187 | xoff++; 188 | 189 | /* tens place */ 190 | char t = vol < 10 ? ' ' : '0' + vol / 10 % 10; 191 | text_draw_char16(slice, t, xoff, text_y, vol_color); 192 | xoff++; 193 | 194 | /* ones place */ 195 | char o = '0' + vol / 1 % 10; 196 | text_draw_char16(slice, o, xoff, text_y, vol_color); 197 | xoff++; 198 | 199 | /* outline volume bar */ 200 | for (int y = bar_y; y < bar_y + bar_h; y++) { 201 | gfx_rgb565 *px = gfx_pixel_address(slice, bar_x, y); 202 | px[0] = px[VOLUME_MAX * 4] = vol_color; 203 | } 204 | gfx_rgb565 *px0 = gfx_pixel_address(slice, bar_x, bar_y); 205 | gfx_rgb565 *px1 = gfx_pixel_address(slice, bar_x, bar_y + bar_h - 1); 206 | if (px0) { 207 | for (int x = 4 * vol + 1; x < 4 * VOLUME_MAX; x++) { 208 | px0[x] = vol_color; 209 | } 210 | } 211 | if (px1) { 212 | for (int x = 4 * vol + 1; x < 4 * VOLUME_MAX; x++) { 213 | px1[x] = vol_color; 214 | } 215 | } 216 | 217 | /* fill volume bar */ 218 | for (int y = bar_y; y < bar_y + bar_h; y++) { 219 | gfx_rgb565 *px = gfx_pixel_address(slice, bar_x, y); 220 | if (px) { 221 | for (int x = 0; x < 4 * vol; x++) { 222 | if (x % 6) { 223 | px[x] = vol_color; 224 | } 225 | } 226 | } 227 | } 228 | } 229 | 230 | static void audio_draw_raw_vol(gfx_pixslice *slice) 231 | { 232 | const int text_y = TR_RAWVOL; 233 | const int text_x = TC_LEFT; 234 | const int bar_x = 8 * text_x; 235 | const int bar_y = TR_RVBAR * 16; 236 | const int bar_h = 15; 237 | 238 | if (!vol_is_visible) { 239 | return; 240 | } 241 | 242 | char *prefix = "raw vol: "; 243 | 244 | int xoff = text_x; 245 | for (const char *p = prefix; *p; p++) { 246 | text_draw_char16(slice, *p, xoff, text_y, vol_color); 247 | xoff++; 248 | } 249 | 250 | /* thousands place */ 251 | char k = raw_vol < 1000 ? ' ' : '0' + raw_vol / 1000 % 10; 252 | text_draw_char16(slice, k, xoff, text_y, vol_color); 253 | xoff++; 254 | 255 | /* hundreds place */ 256 | char h = raw_vol < 100 ? ' ' : '0' + raw_vol / 100 % 10; 257 | text_draw_char16(slice, h, xoff, text_y, vol_color); 258 | xoff++; 259 | 260 | /* tens place */ 261 | char t = raw_vol < 10 ? ' ' : '0' + raw_vol / 10 % 10; 262 | text_draw_char16(slice, t, xoff, text_y, vol_color); 263 | xoff++; 264 | 265 | /* ones place */ 266 | char o = '0' + raw_vol / 1 % 10; 267 | text_draw_char16(slice, o, xoff, text_y, vol_color); 268 | xoff++; 269 | 270 | /* outline volume bar */ 271 | for (int y = bar_y; y < bar_y + bar_h; y++) { 272 | gfx_rgb565 *px = gfx_pixel_address(slice, bar_x, y); 273 | px[0] = px[VOLUME_RAW_MAX >> 4] = vol_color; 274 | } 275 | gfx_rgb565 *px0 = gfx_pixel_address(slice, bar_x, bar_y); 276 | gfx_rgb565 *px1 = gfx_pixel_address(slice, bar_x, bar_y + bar_h - 1); 277 | if (px0) { 278 | for (int x = 1; x < VOLUME_RAW_MAX >> 4; x++) { 279 | px0[x] = vol_color; 280 | } 281 | } 282 | if (px1) { 283 | for (int x = 1; x < VOLUME_RAW_MAX >> 4; x++) { 284 | px1[x] = vol_color; 285 | } 286 | } 287 | 288 | /* fill volume bar */ 289 | for (int y = bar_y + 1; y < bar_y + bar_h - 1; y++) { 290 | gfx_rgb565 *px = gfx_pixel_address(slice, bar_x, y); 291 | if (px) { 292 | for (int x = 0; x < raw_vol >> 4; x++) { 293 | px[x] = vol_color; 294 | } 295 | } 296 | } 297 | } 298 | 299 | static void audio_draw_header(gfx_pixslice *slice) 300 | { 301 | int text_y = TR_HEADER; 302 | int text_x = TC_LEFT; 303 | text_draw_str16(slice, "Audio Saw Test", text_x, text_y, vol_color); 304 | } 305 | 306 | static void audio_draw_instructions(gfx_pixslice *slice) 307 | { 308 | int text_y = TR_INSTR; 309 | int text_x = TC_LEFT; 310 | text_draw_str16(slice, "Press SELECT to change mode.", 311 | text_x, text_y, vol_color); 312 | } 313 | 314 | static void audio_draw_mode(gfx_pixslice *slice) 315 | { 316 | const char *mode_str; 317 | switch (cur_mode) { 318 | case PM_SHUTDOWN: 319 | mode_str = "Shutdown"; 320 | break; 321 | 322 | case PM_MUTED: 323 | mode_str = "Muted"; 324 | break; 325 | 326 | case PM_NORMAL: 327 | mode_str = "Normal"; 328 | break; 329 | 330 | case PM_OVERRIDE_HP: 331 | mode_str = "Force Headphones"; 332 | break; 333 | 334 | case PM_OVERRIDE_SPKR: 335 | mode_str = "Force Speaker"; 336 | break; 337 | 338 | default: 339 | assert(false); 340 | } 341 | int text_y = TR_MODE; 342 | int text_x = TC_LEFT; 343 | int xoff = text_draw_str16(slice, "Mode: ", text_x, text_y, vol_color); 344 | xoff = text_draw_str16(slice, mode_str, xoff, text_y, vol_color); 345 | 346 | } 347 | 348 | static void audio_draw_output(gfx_pixslice *slice) 349 | { 350 | int text_y = TR_OUTPUT; 351 | int text_x = TC_LEFT; 352 | int xoff = text_draw_str16(slice, "Output: ", text_x, text_y, vol_color); 353 | const char *out = pam8019_output_is_headphones() ? "Headphones" : "Speaker"; 354 | xoff = text_draw_str16(slice, out, xoff, text_y, vol_color); 355 | } 356 | 357 | static void audio_render_slice(gfx_pixslice *slice) 358 | { 359 | audio_draw_header(slice); 360 | audio_draw_instructions(slice); 361 | audio_draw_mode(slice); 362 | audio_draw_output(slice); 363 | audio_draw_vol(slice); 364 | audio_draw_raw_vol(slice); 365 | } 366 | 367 | void audio_render(void) 368 | { 369 | if (lcd_bg_color() != bg_color) { 370 | lcd_set_bg_color(bg_color, true); 371 | } 372 | 373 | for (size_t y = 0, h; y < LCD_HEIGHT; y += h) { 374 | h = MIN(LCD_MAX_SLICE_ROWS, LCD_HEIGHT - y); 375 | gfx_pixslice *slice = lcd_alloc_pixslice(0, y, LCD_WIDTH, h); 376 | audio_render_slice(slice); 377 | lcd_send_pixslice(slice); 378 | } 379 | } 380 | -------------------------------------------------------------------------------- /firmware/src/audio_app.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Piotr Esden-Tempski 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef AUDIO_APP_H 21 | #define AUDIO_APP_H 22 | 23 | extern void audio_app_init(void); 24 | extern void audio_animate(void); 25 | extern void audio_render(void); 26 | extern void audio_app_end(void); 27 | 28 | #endif /* AUDIO_APP_H */ 29 | -------------------------------------------------------------------------------- /firmware/src/button_boot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2016 Piotr Esden-Tempski 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #include "button_boot.h" // module's own include is always first. 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "gpio.h" 29 | 30 | #define BLDR_ADDRESS 0x1FFF0000 31 | 32 | static const gpio_pin button_pin = { 33 | .gp_port = GPIOC, 34 | .gp_pin = GPIO1, 35 | .gp_mode = GPIO_MODE_INPUT, 36 | }; 37 | 38 | static uint32_t button_debounce = 0; 39 | 40 | void button_boot(void) { 41 | #if 0 42 | /* Enable GPIOC clock. */ 43 | rcc_periph_clock_enable(RCC_GPIOC); 44 | rcc_periph_clock_enable(RCC_GPIOA); 45 | /* Set GPIO1 (in GPIO port C) to 'input open-drain'. */ 46 | gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO1); 47 | gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8); 48 | #else 49 | gpio_init_pin(&button_pin); 50 | #endif 51 | 52 | /* Check if the user button is depressed, if so launch the factory bootloader */ 53 | #if 0 54 | if ((GPIOC_IDR & (1 << 1)) == 0) { 55 | #else 56 | if (button_pressed()) { 57 | #endif 58 | /* Set vector table base address. */ 59 | SCB_VTOR = BLDR_ADDRESS & 0xFFFF; 60 | /* Initialise master stack pointer. */ 61 | asm volatile("msr msp, %0"::"g" 62 | (*(volatile uint32_t *)BLDR_ADDRESS)); 63 | /* Jump to bootloader. */ 64 | (*(void (**)())(BLDR_ADDRESS + 4))(); 65 | } 66 | } 67 | 68 | bool button_pressed(void) { 69 | return gpio_get(button_pin.gp_port, button_pin.gp_pin) == 0; 70 | } 71 | 72 | bool button_pressed_debounce(void) { 73 | 74 | if (button_pressed()) { 75 | button_debounce <<= 1; 76 | button_debounce |= 1; 77 | } else { 78 | button_debounce = 0; 79 | } 80 | 81 | return (button_debounce == 0xFFFFFFFF); 82 | } 83 | 84 | bool button_released_debounce(void) { 85 | 86 | if (!button_pressed()) { 87 | button_debounce <<= 1; 88 | } else { 89 | button_debounce = 0xFFFFFFFF; 90 | } 91 | 92 | return (button_debounce == 0); 93 | } 94 | -------------------------------------------------------------------------------- /firmware/src/button_boot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2016 Piotr Esden-Tempski 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef COMMON_BUTTON_BOOT_H 21 | #define COMMON_BUTTON_BOOT_H 22 | 23 | #include 24 | 25 | /* This function sets up and checks the state of the user button. 26 | * If the user button is depressed the built in factory bootloader is launched. 27 | */ 28 | void button_boot(void); 29 | 30 | /* As we are already messing around with the user button in this driver we can 31 | * also check if it is depressed in the user code too. "it is fine" :D 32 | */ 33 | bool button_pressed(void); 34 | 35 | /* A version of button_pressed with built in debouncer state. It will only return 36 | * true when after 32 calls of the function the button is still depressed. 37 | */ 38 | bool button_pressed_debounce(void); 39 | 40 | /* A version of button_released with built in debouncer state. It will only return 41 | * true when after 32 calls of the function the button is still released. 42 | */ 43 | bool button_released_debounce(void); 44 | 45 | #endif /* COMMON_BUTTON_BOOT_H */ 46 | -------------------------------------------------------------------------------- /firmware/src/fblocks_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Nicolas Schodet 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "gamepad.h" 21 | #include "lcd.h" 22 | #include "math-util.h" 23 | #include "systick.h" 24 | #include "text.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "assets/assets.h" 32 | 33 | #define FBLOCKS_COLS 10 34 | #define FBLOCKS_ROWS 22 35 | #define FBLOCKS_VISIBLE_ROWS 20 36 | 37 | struct fblocks_shape_t { 38 | int rows, cols; 39 | uint8_t grid[4][4]; 40 | }; 41 | 42 | struct fblocks_piece_t { 43 | int shape_count; 44 | struct fblocks_shape_t shapes[4]; 45 | }; 46 | 47 | #define FBLOCKS_PIECES 7 48 | 49 | static const struct fblocks_piece_t fblocks_pieces[FBLOCKS_PIECES] = { 50 | /* {{{ */ 51 | { 2, { 52 | { 1, 4, { 53 | { 2, 2, 2, 2 }, 54 | { 0, 0, 0, 0 }, 55 | { 0, 0, 0, 0 }, 56 | { 0, 0, 0, 0 }, 57 | } }, 58 | { 4, 1, { 59 | { 2, 0, 0, 0 }, 60 | { 2, 0, 0, 0 }, 61 | { 2, 0, 0, 0 }, 62 | { 2, 0, 0, 0 }, 63 | } }, 64 | } }, 65 | { 1, { 66 | { 2, 2, { 67 | { 3, 3, 0, 0 }, 68 | { 3, 3, 0, 0 }, 69 | { 0, 0, 0, 0 }, 70 | { 0, 0, 0, 0 }, 71 | } }, 72 | } }, 73 | { 2, { 74 | { 2, 3, { 75 | { 0, 4, 4, 0 }, 76 | { 4, 4, 0, 0 }, 77 | { 0, 0, 0, 0 }, 78 | { 0, 0, 0, 0 }, 79 | } }, 80 | { 3, 2, { 81 | { 4, 0, 0, 0 }, 82 | { 4, 4, 0, 0 }, 83 | { 0, 4, 0, 0 }, 84 | { 0, 0, 0, 0 }, 85 | } }, 86 | } }, 87 | { 2, { 88 | { 2, 3, { 89 | { 8, 8, 0, 0 }, 90 | { 0, 8, 8, 0 }, 91 | { 0, 0, 0, 0 }, 92 | { 0, 0, 0, 0 }, 93 | } }, 94 | { 3, 2, { 95 | { 0, 8, 0, 0 }, 96 | { 8, 8, 0, 0 }, 97 | { 8, 0, 0, 0 }, 98 | { 0, 0, 0, 0 }, 99 | } }, 100 | } }, 101 | { 4, { 102 | { 2, 3, { 103 | { 5, 5, 5, 0 }, 104 | { 5, 0, 0, 0 }, 105 | { 0, 0, 0, 0 }, 106 | { 0, 0, 0, 0 }, 107 | } }, 108 | { 3, 2, { 109 | { 5, 5, 0, 0 }, 110 | { 0, 5, 0, 0 }, 111 | { 0, 5, 0, 0 }, 112 | { 0, 0, 0, 0 }, 113 | } }, 114 | { 2, 3, { 115 | { 0, 0, 5, 0 }, 116 | { 5, 5, 5, 0 }, 117 | { 0, 0, 0, 0 }, 118 | { 0, 0, 0, 0 }, 119 | } }, 120 | { 3, 2, { 121 | { 5, 0, 0, 0 }, 122 | { 5, 0, 0, 0 }, 123 | { 5, 5, 0, 0 }, 124 | { 0, 0, 0, 0 }, 125 | } }, 126 | } }, 127 | { 4, { 128 | { 2, 3, { 129 | { 6, 6, 6, 0 }, 130 | { 0, 0, 6, 0 }, 131 | { 0, 0, 0, 0 }, 132 | { 0, 0, 0, 0 }, 133 | } }, 134 | { 3, 2, { 135 | { 0, 6, 0, 0 }, 136 | { 0, 6, 0, 0 }, 137 | { 6, 6, 0, 0 }, 138 | { 0, 0, 0, 0 }, 139 | } }, 140 | { 2, 3, { 141 | { 6, 0, 0, 0 }, 142 | { 6, 6, 6, 0 }, 143 | { 0, 0, 0, 0 }, 144 | { 0, 0, 0, 0 }, 145 | } }, 146 | { 3, 2, { 147 | { 6, 6, 0, 0 }, 148 | { 6, 0, 0, 0 }, 149 | { 6, 0, 0, 0 }, 150 | { 0, 0, 0, 0 }, 151 | } }, 152 | } }, 153 | { 4, { 154 | { 2, 3, { 155 | { 7, 7, 7, 0 }, 156 | { 0, 7, 0, 0 }, 157 | { 0, 0, 0, 0 }, 158 | { 0, 0, 0, 0 }, 159 | } }, 160 | { 3, 2, { 161 | { 0, 7, 0, 0 }, 162 | { 7, 7, 0, 0 }, 163 | { 0, 7, 0, 0 }, 164 | { 0, 0, 0, 0 }, 165 | } }, 166 | { 2, 3, { 167 | { 0, 7, 0, 0 }, 168 | { 7, 7, 7, 0 }, 169 | { 0, 0, 0, 0 }, 170 | { 0, 0, 0, 0 }, 171 | } }, 172 | { 3, 2, { 173 | { 7, 0, 0, 0 }, 174 | { 7, 7, 0, 0 }, 175 | { 7, 0, 0, 0 }, 176 | { 0, 0, 0, 0 }, 177 | } }, 178 | } }, 179 | /* }}} */ 180 | }; 181 | 182 | #define FBLOCKS_SCREEN_AREA_X (5 * 12) 183 | #define FBLOCKS_SCREEN_AREA_Y (0 * 12) 184 | #define FBLOCKS_SCREEN_AREA_W (FBLOCKS_COLS * 12) 185 | #define FBLOCKS_SCREEN_AREA_H (FBLOCKS_VISIBLE_ROWS * 12) 186 | #define FBLOCKS_SCREEN_PREVIEW_X (16 * 12) 187 | #define FBLOCKS_SCREEN_PREVIEW_Y (1 * 12) 188 | #define FBLOCKS_SCREEN_PREVIEW_W (5 * 12) 189 | #define FBLOCKS_SCREEN_PREVIEW_H (3 * 12) 190 | #define FBLOCKS_SCREEN_SCORE_X (16 * 12) 191 | #define FBLOCKS_SCREEN_SCORE_Y (5 * 12) 192 | #define FBLOCKS_SCREEN_SCORE_W (7 * 12) 193 | #define FBLOCKS_SCREEN_SCORE_H (2 * 12) 194 | 195 | static const uint8_t fblocks_screen[LCD_HEIGHT / 12][LCD_WIDTH / 12 + 1] = { 196 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 197 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }, 198 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }, 199 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 }, 200 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 201 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, 202 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, 203 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 204 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 205 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 206 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 207 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 208 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 209 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 210 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 211 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 212 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 213 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 214 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 215 | { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 216 | }; 217 | 218 | #define FBLOCKS_START_FALL_SPEED 800 219 | #define FBLOCKS_AUTO_REPEAT_SPEED 100 220 | #define FBLOCKS_PREVIEW_COUNT 1 221 | 222 | struct fblocks_game_t; 223 | 224 | typedef bool (*fblocks_animation_t)(struct fblocks_game_t *game, 225 | gfx_pixslice *slice, int millis); 226 | 227 | struct fblocks_game_t { 228 | /* Playing area, row 0 is at bottom of screen. */ 229 | uint8_t area[FBLOCKS_ROWS][FBLOCKS_COLS]; 230 | /* Current score. */ 231 | int score; 232 | /* Score to obtain to reach the next level. */ 233 | int next_level_score; 234 | /* Current level. */ 235 | int level; 236 | /* Current piece and shape. */ 237 | const struct fblocks_piece_t *piece; 238 | const struct fblocks_shape_t *shape; 239 | /* Base of current piece position. */ 240 | int row, col; 241 | /* Speed of fall. */ 242 | int fall_speed; 243 | /* Date of last fall action. */ 244 | uint32_t last_fall_millis; 245 | /* Date of last move action. */ 246 | uint32_t last_move_millis; 247 | /* Previous gamepad state. */ 248 | uint16_t last_gamepad; 249 | /* Animation. */ 250 | fblocks_animation_t animation; 251 | uint32_t animation_start_millis; 252 | /* Bag of random pieces. */ 253 | unsigned int bag; 254 | /* Future pieces. */ 255 | const struct fblocks_piece_t *preview[FBLOCKS_PREVIEW_COUNT]; 256 | /* Full row being removed or -1. */ 257 | int full_row; 258 | /* You lose. */ 259 | bool over; 260 | }; 261 | 262 | static struct fblocks_game_t game; 263 | 264 | /* Initialise/reset game. */ 265 | void fblocks_init(void) { 266 | memset(game.area, 0, sizeof(game.area)); 267 | game.score = 0; 268 | game.next_level_score = 0; 269 | game.level = 1; 270 | game.piece = NULL; 271 | game.fall_speed = FBLOCKS_START_FALL_SPEED; 272 | game.last_fall_millis = system_millis; 273 | game.last_move_millis = system_millis; 274 | game.last_gamepad = 0; 275 | game.animation = NULL; 276 | game.animation_start_millis = 0; 277 | game.bag = 0; 278 | game.full_row = -1; 279 | game.over = true; 280 | } 281 | 282 | /* Undraw shape in area. */ 283 | static void fblocks_unblit(struct fblocks_game_t *game) { 284 | const struct fblocks_shape_t *shape = game->shape; 285 | int row = game->row, col = game->col; 286 | for (int r = 0; r < shape->rows; r++) { 287 | for (int c = 0; c < shape->cols; c++) { 288 | if (shape->grid[r][c]) { 289 | game->area[row + r][col + c] = 0; 290 | } 291 | } 292 | } 293 | } 294 | 295 | /* Draw shape in area. */ 296 | static void fblocks_blit(struct fblocks_game_t *game) { 297 | const struct fblocks_shape_t *shape = game->shape; 298 | int row = game->row, col = game->col; 299 | for (int r = 0; r < shape->rows; r++) { 300 | for (int c = 0; c < shape->cols; c++) { 301 | int s = shape->grid[r][c]; 302 | if (s) { 303 | game->area[row + r][col + c] = s; 304 | } 305 | } 306 | } 307 | } 308 | 309 | /* Return true if there is a collision between play area and shape. */ 310 | static bool fblocks_test(struct fblocks_game_t *game, 311 | const struct fblocks_shape_t *shape, int row, int col) { 312 | for (int r = 0; r < shape->rows; r++) { 313 | for (int c = 0; c < shape->cols; c++) { 314 | int s = shape->grid[r][c]; 315 | if (s && game->area[row + r][col + c]) { 316 | return true; 317 | } 318 | } 319 | } 320 | return false; 321 | } 322 | 323 | /* Remove a row. */ 324 | static void fblocks_remove_row(struct fblocks_game_t *game, int row) { 325 | for (int r = row; r < FBLOCKS_ROWS - 1; r++) { 326 | for (int c = 0; c < FBLOCKS_COLS; c++) { 327 | game->area[r][c] = game->area[r + 1][c]; 328 | } 329 | } 330 | for (int c = 0; c < FBLOCKS_COLS; c++) { 331 | game->area[FBLOCKS_ROWS - 1][c] = 0; 332 | } 333 | } 334 | 335 | /* Find first full row or return -1. */ 336 | static int fblocks_full_row(struct fblocks_game_t *game) { 337 | for (int r = 0; r < FBLOCKS_ROWS; r++) { 338 | bool full = true; 339 | for (int c = 0; full && c < FBLOCKS_COLS; c++) { 340 | if (!game->area[r][c]) { 341 | full = false; 342 | } 343 | } 344 | if (full) { 345 | return r; 346 | } 347 | } 348 | return -1; 349 | } 350 | 351 | /* Choose a random piece from the bag. */ 352 | static int fblocks_random(struct fblocks_game_t *game) { 353 | if (!game->bag) { 354 | game->bag = (1 << FBLOCKS_PIECES) - 1; 355 | } 356 | int piece = rand() % FBLOCKS_PIECES; 357 | while (!(game->bag & (1 << piece))) { 358 | piece = (piece + 1) % FBLOCKS_PIECES; 359 | } 360 | game->bag &= ~(1 << piece); 361 | return piece; 362 | } 363 | 364 | static bool fblocks_animation_full_row(struct fblocks_game_t *game, 365 | gfx_pixslice *slice, int millis); 366 | 367 | static bool fblocks_animation_game_over(struct fblocks_game_t *game, 368 | gfx_pixslice *slice, int millis); 369 | 370 | /* Apply rules. */ 371 | static void fblocks_rules(struct fblocks_game_t *game) { 372 | /* Restart? */ 373 | if (game->over) { 374 | fblocks_init(); 375 | for (int i = 0; i < FBLOCKS_PREVIEW_COUNT; i++) { 376 | game->preview[i] = &fblocks_pieces[fblocks_random(game)]; 377 | } 378 | game->next_level_score = 10; 379 | game->over = false; 380 | } 381 | /* Remove full row after animation. */ 382 | if (game->full_row != -1) { 383 | game->score++; 384 | if (game->score >= game->next_level_score) { 385 | game->level++; 386 | game->next_level_score += game->level * 10; 387 | game->fall_speed = game->fall_speed * 7 / 10; 388 | } 389 | fblocks_remove_row(game, game->full_row); 390 | game->full_row = -1; 391 | } 392 | /* New piece? */ 393 | if (!game->piece) { 394 | /* Test for full rows. */ 395 | game->full_row = fblocks_full_row(game); 396 | if (game->full_row != -1) { 397 | game->animation = fblocks_animation_full_row; 398 | game->animation_start_millis = system_millis; 399 | } else { 400 | /* New piece. */ 401 | game->piece = game->preview[0]; 402 | for (int i = 0; i < FBLOCKS_PREVIEW_COUNT - 1; i++) { 403 | game->preview[i] = game->preview[i + 1]; 404 | } 405 | game->preview[FBLOCKS_PREVIEW_COUNT - 1] = 406 | &fblocks_pieces[fblocks_random(game)]; 407 | game->shape = &game->piece->shapes[0]; 408 | game->row = FBLOCKS_VISIBLE_ROWS - game->shape->rows; 409 | game->col = (FBLOCKS_COLS - game->shape->cols) / 2; 410 | game->last_fall_millis = system_millis; 411 | /* Game over? */ 412 | if (fblocks_test(game, game->shape, game->row, game->col)) { 413 | game->over = true; 414 | game->animation = fblocks_animation_game_over; 415 | game->animation_start_millis = system_millis; 416 | } 417 | fblocks_blit(game); 418 | } 419 | } 420 | } 421 | 422 | /* Game & control logic. */ 423 | void fblocks_animate(void) { 424 | /* Animation running? */ 425 | if (game.animation) { 426 | return; 427 | } 428 | /* Apply rules. */ 429 | fblocks_rules(&game); 430 | if (!game.piece) { 431 | return; 432 | } 433 | /* Key? */ 434 | uint16_t gamepad = gamepad_get(); 435 | uint16_t gamepad_new = gamepad & (gamepad ^ game.last_gamepad); 436 | uint16_t gamepad_old = gamepad & game.last_gamepad; 437 | bool repeat_move = (int) (system_millis - game.last_move_millis 438 | - FBLOCKS_AUTO_REPEAT_SPEED) > 0; 439 | int new_col = game.col; 440 | int rotate = 0; 441 | if ((gamepad_new & GAMEPAD_BLEFT) 442 | || ((gamepad_old & GAMEPAD_BLEFT) && repeat_move)) { 443 | new_col--; 444 | } 445 | if ((gamepad_new & GAMEPAD_BRIGHT) 446 | || ((gamepad_old & GAMEPAD_BRIGHT) && repeat_move)) { 447 | new_col++; 448 | } 449 | if (gamepad_new & GAMEPAD_BA) { 450 | rotate--; 451 | } 452 | if (gamepad_new & GAMEPAD_BB) { 453 | rotate++; 454 | } 455 | game.last_gamepad = gamepad; 456 | /* Rotate. */ 457 | if (rotate) { 458 | /* Compute rotation. */ 459 | const struct fblocks_shape_t *new_shape = game.shape + rotate; 460 | if (new_shape == &game.piece->shapes[-1]) { 461 | new_shape = &game.piece->shapes[game.piece->shape_count - 1]; 462 | } else if (new_shape == &game.piece->shapes[game.piece->shape_count]) { 463 | new_shape = &game.piece->shapes[0]; 464 | } 465 | /* Compute new position. */ 466 | int new_row = game.row; 467 | new_row -= (new_shape->rows - game.shape->rows) / 2; 468 | new_row = CLAMP(0, FBLOCKS_ROWS - new_shape->rows, new_row); 469 | int new_col = game.col; 470 | new_col -= (new_shape->cols - game.shape->cols) / 2; 471 | new_col = CLAMP(0, FBLOCKS_COLS - new_shape->cols, new_col); 472 | /* Is there room to rotate. */ 473 | fblocks_unblit(&game); 474 | if (!fblocks_test(&game, new_shape, new_row, new_col)) { 475 | /* OK, there is room. */ 476 | game.shape = new_shape; 477 | game.row = new_row; 478 | game.col = new_col; 479 | } 480 | fblocks_blit(&game); 481 | /* Move. */ 482 | } else if (new_col != game.col && new_col >= 0 483 | && new_col + game.shape->cols <= FBLOCKS_COLS) { 484 | /* Is there room to move? */ 485 | fblocks_unblit(&game); 486 | if (!fblocks_test(&game, game.shape, game.row, new_col)) { 487 | /* OK, there is room. */ 488 | game.col = new_col; 489 | game.last_move_millis = system_millis; 490 | } 491 | fblocks_blit(&game); 492 | } 493 | /* Faster down? */ 494 | bool drop = gamepad & GAMEPAD_BDOWN; 495 | int speed = game.fall_speed; 496 | if (drop) { 497 | speed /= 20; 498 | } 499 | /* Fall? */ 500 | if ((int) (system_millis - game.last_fall_millis - speed) > 0) { 501 | /* Erase previous position, test new one... */ 502 | fblocks_unblit(&game); 503 | if (game.row == 0 504 | || fblocks_test(&game, game.shape, game.row - 1, game.col)) { 505 | /* Revert, there is no room! */ 506 | fblocks_blit(&game); 507 | game.piece = NULL; 508 | } else { 509 | /* OK use new position. */ 510 | game.row--; 511 | fblocks_blit(&game); 512 | } 513 | game.last_fall_millis = system_millis; 514 | } 515 | } 516 | 517 | /* Draw one tile from the pixmap. */ 518 | static void fblocks_draw_tile(gfx_pixslice *slice, int id, size_t x, size_t y) { 519 | gfx_pixslice tile; 520 | gfx_init_pixslice(&tile, (void *) &fblocks_pixmap[id * 12][0], 521 | 0, 0, 12, 12, 12); 522 | gfx_ipoint p = { .x = x, .y = y }; 523 | gfx_copy_pixslice(slice, &tile, p); 524 | } 525 | 526 | /* Default area drawing. */ 527 | static bool fblocks_animation_default(struct fblocks_game_t *game, 528 | gfx_pixslice *slice, int millis) { 529 | for (int r = 0; r < FBLOCKS_VISIBLE_ROWS; r++) { 530 | int y = FBLOCKS_SCREEN_AREA_Y + (FBLOCKS_VISIBLE_ROWS - r - 1) * 12; 531 | if (y >= slice->y - 12 && y < slice->y + slice->h) { 532 | for (int c = 0; c < FBLOCKS_COLS; c++) { 533 | int x = FBLOCKS_SCREEN_AREA_X + c * 12; 534 | int s = game->area[r][c]; 535 | if (s) { 536 | fblocks_draw_tile(slice, s, x, y); 537 | } 538 | } 539 | } 540 | } 541 | return false; 542 | } 543 | 544 | /* Drawing when a full row is being removed. */ 545 | static bool fblocks_animation_full_row(struct fblocks_game_t *game, 546 | gfx_pixslice *slice, int millis) { 547 | int collapse = millis < 500 ? millis * 12 / 500 : 12; 548 | for (int r = 0; r < FBLOCKS_VISIBLE_ROWS; r++) { 549 | int y = FBLOCKS_SCREEN_AREA_Y + (FBLOCKS_VISIBLE_ROWS - r - 1) * 12; 550 | if (r > game->full_row) 551 | y += collapse; 552 | if (y >= slice->y - 12 && y < slice->y + slice->h) { 553 | for (int c = 0; c < FBLOCKS_COLS; c++) { 554 | int x = FBLOCKS_SCREEN_AREA_X + c * 12; 555 | int s = game->area[r][c]; 556 | fblocks_draw_tile(slice, s, x, y); 557 | } 558 | } 559 | } 560 | return millis >= 800; 561 | } 562 | 563 | /* Game over drawing. */ 564 | static bool fblocks_animation_game_over(struct fblocks_game_t *game, 565 | gfx_pixslice *slice, int millis) { 566 | float anim = millis / 3000.0f; 567 | if (anim < 1.0f) { 568 | float radius = (1.0f - anim); 569 | float angle = anim * 6.0f * M_PI; 570 | float ca = cos(angle); 571 | float sa = sin(angle); 572 | const int cy = FBLOCKS_SCREEN_AREA_Y + FBLOCKS_SCREEN_AREA_H / 2; 573 | const int cx = FBLOCKS_SCREEN_AREA_X + FBLOCKS_SCREEN_AREA_W / 2; 574 | for (int r = 0; r < FBLOCKS_ROWS; r++) { 575 | int y = FBLOCKS_SCREEN_AREA_Y + (FBLOCKS_VISIBLE_ROWS - r - 1) * 12; 576 | for (int c = 0; c < FBLOCKS_COLS; c++) { 577 | int s = game->area[r][c]; 578 | if (s) { 579 | int x = FBLOCKS_SCREEN_AREA_X + c * 12; 580 | int dx = x + 6 - cx; 581 | int dy = y + 6 - cy; 582 | int rx = cx + radius * (dx * ca - dy * sa) - 6; 583 | int ry = cy + radius * (dx * sa + dy * ca) - 6; 584 | fblocks_draw_tile(slice, s, rx, ry); 585 | } 586 | } 587 | } 588 | } else { 589 | text_draw_str16(slice, "Game Over", 590 | (FBLOCKS_SCREEN_AREA_X + FBLOCKS_SCREEN_AREA_W / 2) / 8 - 5, 591 | (FBLOCKS_SCREEN_AREA_Y + FBLOCKS_SCREEN_AREA_H / 2) / 16, 0x0000); 592 | } 593 | return anim > 2.0f; 594 | } 595 | 596 | static bool fblocks_render_slice(gfx_pixslice *slice) { 597 | /* Background. */ 598 | for (size_t y = slice->y / 12; y <= (slice->y + slice->h) / 12; y++) { 599 | for (size_t x = 0; x <= slice->w / 12 + 1; x++) { 600 | fblocks_draw_tile(slice, fblocks_screen[y][x], x * 12, y * 12); 601 | } 602 | } 603 | /* Preview. */ 604 | if (slice->y < FBLOCKS_SCREEN_PREVIEW_Y + FBLOCKS_SCREEN_PREVIEW_H && game.preview[0]) { 605 | const struct fblocks_shape_t *shape = &game.preview[0]->shapes[0]; 606 | int sx = FBLOCKS_SCREEN_PREVIEW_X + FBLOCKS_SCREEN_PREVIEW_W / 2 607 | - shape->cols * 12 / 2; 608 | int sy = FBLOCKS_SCREEN_PREVIEW_Y + FBLOCKS_SCREEN_PREVIEW_H / 2 609 | - shape->rows * 12 / 2; 610 | for (int r = 0; r < shape->rows; r++) { 611 | int dy = (shape->rows - r - 1) * 12; 612 | for (int c = 0; c < shape->cols; c++) { 613 | int s = shape->grid[r][c]; 614 | if (s) { 615 | fblocks_draw_tile(slice, s, sx + c * 12, sy + dy); 616 | } 617 | } 618 | } 619 | } 620 | /* Score. */ 621 | if (slice->y < FBLOCKS_SCREEN_SCORE_Y + FBLOCKS_SCREEN_SCORE_H) { 622 | char score[11]; 623 | sprintf(score, "%d", game.score); 624 | int score_len = strlen(score); 625 | text_draw_str16(slice, score, 626 | (FBLOCKS_SCREEN_SCORE_X + FBLOCKS_SCREEN_SCORE_W) / 8 - score_len - 1, 627 | (FBLOCKS_SCREEN_SCORE_Y + FBLOCKS_SCREEN_SCORE_H / 2) / 16, 0x0000); 628 | } 629 | /* Area. */ 630 | fblocks_animation_t animation = game.animation ? game.animation 631 | : fblocks_animation_default; 632 | return animation(&game, slice, 633 | system_millis - game.animation_start_millis); 634 | } 635 | 636 | void fblocks_render(void) { 637 | size_t h; 638 | bool animation_stop = false; 639 | for (size_t y = 0; y < LCD_HEIGHT; y += h) { 640 | h = MIN(LCD_MAX_SLICE_ROWS, LCD_HEIGHT - y); 641 | gfx_pixslice *slice = lcd_alloc_pixslice(0, y, LCD_WIDTH, h); 642 | animation_stop = fblocks_render_slice(slice); 643 | lcd_send_pixslice(slice); 644 | } 645 | if (animation_stop) { 646 | game.animation = NULL; 647 | } 648 | } 649 | -------------------------------------------------------------------------------- /firmware/src/fblocks_app.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Nicolas Schodet 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef FBLOCKS_APP_H 21 | #define FBLOCKS_APP_H 22 | 23 | void fblocks_init(void); 24 | void fblocks_animate(void); 25 | void fblocks_render(void); 26 | 27 | #endif /* FBLOCKS_APP_H */ 28 | -------------------------------------------------------------------------------- /firmware/src/gamepad.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Piotr Esden-Tempski 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include "gamepad.h" 23 | 24 | void gamepad_init(void) 25 | { 26 | /* LATCH */ 27 | gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4); 28 | gpio_clear(GPIOC, GPIO4); 29 | /* CLOCK */ 30 | gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7); 31 | gpio_clear(GPIOA, GPIO4); 32 | /* DATA */ 33 | gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO6); 34 | } 35 | 36 | bool gamepad_present(void) 37 | { 38 | return (gamepad_get() != 0xFFFFF ); 39 | } 40 | 41 | uint16_t gamepad_get(void) 42 | { 43 | uint16_t ret = 0; 44 | 45 | /* assert latch */ 46 | gpio_clear(GPIOC, GPIO4); 47 | for (int i = 0; i < 30; i++) asm("nop"); 48 | gpio_set(GPIOC, GPIO4); 49 | for (int i = 0; i < 30; i++) asm("nop"); 50 | 51 | /* read bit 1 */ 52 | if (gpio_get(GPIOA, GPIO6) != 0) { 53 | ret <<= 1; 54 | ret |= 1; 55 | } else { 56 | ret <<= 1; 57 | } 58 | 59 | /* Read another 16 bit */ 60 | for (int i = 0; i < 15; i++) { 61 | gpio_set(GPIOA, GPIO7); 62 | for (int d = 0; d < 30; d++) asm("nop"); 63 | gpio_clear(GPIOA, GPIO7); 64 | for (int d = 0; d < 30; d++) asm("nop"); 65 | if (gpio_get(GPIOA, GPIO6) != 0) { 66 | ret <<= 1; 67 | ret |= 1; 68 | } else { 69 | ret <<= 1; 70 | } 71 | } 72 | 73 | return (ret ^ 0xFFFFF); 74 | } -------------------------------------------------------------------------------- /firmware/src/gamepad.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Piotr Esden-Tempski 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef GAMEPAD_H 21 | #define GAMEPAD_H 22 | 23 | #include 24 | #include 25 | 26 | /* SNES Controller buttons */ 27 | #define GAMEPAD_BB_BIT 15 28 | #define GAMEPAD_BY_BIT 14 29 | #define GAMEPAD_BSELECT_BIT 13 30 | #define GAMEPAD_BSTART_BIT 12 31 | #define GAMEPAD_BUP_BIT 11 32 | #define GAMEPAD_BDOWN_BIT 10 33 | #define GAMEPAD_BLEFT_BIT 9 34 | #define GAMEPAD_BRIGHT_BIT 8 35 | #define GAMEPAD_BA_BIT 7 36 | #define GAMEPAD_BX_BIT 6 37 | #define GAMEPAD_BL_BIT 5 38 | #define GAMEPAD_BR_BIT 4 39 | #define GAMEPAD_BRES1_BIT 3 40 | #define GAMEPAD_BRES2_BIT 2 41 | #define GAMEPAD_BVOLM_BIT 1 42 | #define GAMEPAD_BVOLP_BIT 0 43 | 44 | #define GAMEPAD_BB (1 << GAMEPAD_BB_BIT) 45 | #define GAMEPAD_BY (1 << GAMEPAD_BY_BIT) 46 | #define GAMEPAD_BSELECT (1 << GAMEPAD_BSELECT_BIT) 47 | #define GAMEPAD_BSTART (1 << GAMEPAD_BSTART_BIT) 48 | #define GAMEPAD_BUP (1 << GAMEPAD_BUP_BIT) 49 | #define GAMEPAD_BDOWN (1 << GAMEPAD_BDOWN_BIT) 50 | #define GAMEPAD_BLEFT (1 << GAMEPAD_BLEFT_BIT) 51 | #define GAMEPAD_BRIGHT (1 << GAMEPAD_BRIGHT_BIT) 52 | #define GAMEPAD_BA (1 << GAMEPAD_BA_BIT) 53 | #define GAMEPAD_BX (1 << GAMEPAD_BX_BIT) 54 | #define GAMEPAD_BL (1 << GAMEPAD_BL_BIT) 55 | #define GAMEPAD_BR (1 << GAMEPAD_BR_BIT) 56 | #define GAMEPAD_BRES1 (1 << GAMEPAD_BRES1_BIT) 57 | #define GAMEPAD_BRES2 (1 << GAMEPAD_BRES2_BIT) 58 | #define GAMEPAD_BVOLM (1 << GAMEPAD_BVOLM_BIT) 59 | #define GAMEPAD_BVOLP (1 << GAMEPAD_BVOLP_BIT) 60 | 61 | void gamepad_init(void); 62 | bool gamepad_present(void); 63 | uint16_t gamepad_get(void); 64 | 65 | #endif /* GAMEPAD_H */ 66 | -------------------------------------------------------------------------------- /firmware/src/gfx-pixslice.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #include "gfx-pixslice.h" 21 | 22 | #include 23 | 24 | #include "math-util.h" 25 | 26 | extern void gfx_init_pixslice(gfx_pixslice *slice, 27 | void *buffer, 28 | int x, int y, 29 | size_t w, size_t h, 30 | size_t stride) 31 | { 32 | slice->pixels = (gfx_rgb565 *)buffer - y * stride - x; 33 | slice->x = x; 34 | slice->y = y; 35 | slice->w = w; 36 | slice->h = h; 37 | slice->stride = stride; 38 | } 39 | 40 | extern gfx_rgb565 *gfx_pixel_address(gfx_pixslice *slice, int x, int y) 41 | { 42 | if (x < slice->x || x >= (ssize_t)(slice->x + slice->w)) 43 | return NULL; 44 | if (y < slice->y || y >= (ssize_t)(slice->y + slice->h)) 45 | return NULL; 46 | return gfx_pixel_address_unchecked(slice, x, y); 47 | } 48 | 49 | void gfx_copy_pixslice(gfx_pixslice *dest, 50 | gfx_pixslice const *src, 51 | gfx_ipoint offset) 52 | { 53 | int x0s = MAX(src->x, dest->x - offset.x); 54 | int x1s = MIN(src->x + (int)src->w, dest->x + (int)dest->w - offset.x); 55 | if (x0s >= x1s) 56 | return; 57 | int x0d = x0s + offset.x; 58 | int nx = x1s - x0s; 59 | int y0s = MAX(src->y, dest->y - offset.y); 60 | int y1s = MIN(src->y + (int)src->h, dest->y + (int)dest->h - offset.y); 61 | if (y0s >= y1s) 62 | return; 63 | int y0d = y0s + offset.y; 64 | for (int ys = y0s, yd = y0d; ys < y1s; ys++, yd++) { 65 | const gfx_rgb565 *ps = 66 | gfx_pixel_address_unchecked((gfx_pixslice *)src, x0s, ys); 67 | gfx_rgb565 *pd = gfx_pixel_address_unchecked(dest, x0d, yd); 68 | memcpy(pd, ps, nx * sizeof *pd); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /firmware/src/gfx-pixslice.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef GFX_PIXSLICE_H 21 | #define GFX_PIXSLICE_H 22 | 23 | #include 24 | 25 | #include "gfx-types.h" 26 | 27 | struct gfx_pixslice { 28 | gfx_rgb565 *pixels; // N.B., points to (0, 0) which may not exist. 29 | int x, y; // origin 30 | size_t w, h; // size 31 | ssize_t stride; // row stride in pixels 32 | }; 33 | 34 | void gfx_init_pixslice(gfx_pixslice *slice, 35 | void *buffer, 36 | int x, int y, 37 | size_t w, size_t h, 38 | size_t stride); 39 | 40 | static inline gfx_rgb565 *gfx_pixel_address_unchecked(gfx_pixslice *slice, 41 | int x, int y) 42 | { 43 | return slice->pixels + y * slice->stride + x; 44 | } 45 | 46 | gfx_rgb565 *gfx_pixel_address(gfx_pixslice *slice, int x, int y); 47 | 48 | // Copy source pixmap into destination. 49 | // offset translates src coordinates to dest. 50 | // dest coord = src coord + offset. 51 | void gfx_copy_pixslice(gfx_pixslice *dest, 52 | gfx_pixslice const *src, 53 | gfx_ipoint offset); 54 | 55 | #endif /* GFX_PIXSLICE_H */ 56 | -------------------------------------------------------------------------------- /firmware/src/gfx-types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef GFX_TYPES_H 21 | #define GFX_TYPES_H 22 | 23 | #include 24 | #include 25 | 26 | typedef uint16_t gfx_rgb565; 27 | typedef uint32_t gfx_rgb888; 28 | typedef uint8_t gfx_alpha8; 29 | 30 | typedef struct gfx_pixslice gfx_pixslice; 31 | 32 | typedef union gfx_point { 33 | struct { 34 | float x, y; // use p.x, p.y 35 | }; 36 | float c[2]; // use p.c[i] 37 | } gfx_point; 38 | 39 | typedef union gfx_ipoint { 40 | struct { 41 | int x, y; // use p.x, p.y 42 | }; 43 | int c[2]; // use p.c[i] 44 | } gfx_ipoint; 45 | 46 | typedef struct gfx_trapezoid { 47 | float xl0, xr0, y0; 48 | float xl1, xr1, y1; 49 | } gfx_trapezoid; 50 | 51 | typedef struct gfx_triangle { 52 | gfx_point v[3]; 53 | } gfx_triangle; 54 | 55 | #endif /* GFX_TYPES_H */ 56 | -------------------------------------------------------------------------------- /firmware/src/gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #include "gpio.h" 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #define GPIO_PORT_COUNT 11 28 | 29 | static uint16_t gpio_pins_used[GPIO_PORT_COUNT]; 30 | 31 | void gpio_init_pin(const gpio_pin *pin) 32 | { 33 | uint32_t port = pin->gp_port; 34 | uint16_t pinmask = pin->gp_pin; 35 | uint32_t index = ((uint32_t)port - (uint32_t)PERIPH_BASE_AHB1) >> 10; 36 | assert(index < GPIO_PORT_COUNT); 37 | 38 | if (!gpio_pins_used[index]) 39 | rcc_periph_clock_enable((0x30 << 5) | index); 40 | 41 | assert(!(gpio_pins_used[index] & pinmask)); 42 | gpio_pins_used[index] |= pinmask; 43 | 44 | gpio_config_pin(pin); 45 | } 46 | 47 | void gpio_config_pin(const gpio_pin *pin) 48 | { 49 | uint32_t port = pin->gp_port; 50 | uint16_t pinmask = pin->gp_pin; 51 | 52 | gpio_mode_setup(port, 53 | pin->gp_mode, 54 | pin->gp_pupd, 55 | pinmask); 56 | 57 | if (pin->gp_mode == GPIO_MODE_OUTPUT) { 58 | if (pin->gp_level) 59 | gpio_set(port, pinmask); 60 | else 61 | gpio_clear(port, pinmask); 62 | } 63 | 64 | if (pin->gp_mode == GPIO_MODE_OUTPUT || pin->gp_mode == GPIO_MODE_AF) 65 | gpio_set_output_options(port, 66 | pin->gp_otype, 67 | pin->gp_ospeed, 68 | pinmask); 69 | 70 | if (pin->gp_mode == GPIO_MODE_AF) 71 | gpio_set_af(port, 72 | pin->gp_af, 73 | pinmask); 74 | } 75 | 76 | void gpio_init_pins(const gpio_pin *pins, size_t count) 77 | { 78 | for (size_t i = 0; i < count; i++) 79 | gpio_init_pin(&pins[i]); 80 | } 81 | 82 | void gpio_config_pins(const gpio_pin *pins, size_t count) 83 | { 84 | for (size_t i = 0; i < count; i++) 85 | gpio_config_pin(&pins[i]); 86 | } 87 | -------------------------------------------------------------------------------- /firmware/src/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef GPIO_H 21 | #define GPIO_H 22 | 23 | #include 24 | 25 | #include 26 | 27 | typedef struct gpio_pin { 28 | uint32_t gp_port; // GPIOA .. GPIOF 29 | uint16_t gp_pin; // GPIO0 .. GPIO15 (may OR pins) 30 | uint8_t gp_mode : 2; // GPIO_MODE_INPUT/OUTPUT/AF/ANALOG 31 | uint8_t gp_pupd : 2; // GPIO_PUPD_NONE/PULLUP/PULLDOWN 32 | uint8_t gp_af : 4; // GPIO_AF0 .. GPIO_AF15 33 | uint8_t gp_ospeed : 2; // GPIO_OSPEED_2/25/60/100MHZ 34 | uint8_t gp_otype : 1; // GPIO_OTYPE_PP/OD (push-pull, open drain) 35 | uint8_t gp_level : 1; // 0 or 1 36 | } gpio_pin; 37 | 38 | // Initialization asserts that each pin is not yet used and 39 | // enables RCC peripheral clocks as needed before configuring 40 | // the pin(s). 41 | // 42 | // Configuration just sets the mode and other attributes. 43 | // Does not init the clock or check for uniqueness. 44 | 45 | void gpio_init_pin(const gpio_pin *); 46 | void gpio_config_pin(const gpio_pin *); 47 | 48 | 49 | // Convenience functions to init/config several pins at once. 50 | void gpio_init_pins(const gpio_pin *, size_t count); 51 | void gpio_config_pins(const gpio_pin *, size_t count); 52 | 53 | #endif /* GPIO_H */ 54 | -------------------------------------------------------------------------------- /firmware/src/i2c.c: -------------------------------------------------------------------------------- 1 | #include "i2c.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "systick.h" 11 | 12 | #define I2C_BAUD 100000 13 | #define TIMEOUT_MSEC 25 14 | 15 | void i2c_init(i2c_config const *ip) 16 | { 17 | // Enable periph clock. 18 | // Configure GPIO. 19 | // Reset I²C. 20 | 21 | uint32_t base = ip->i_base_address; 22 | 23 | enum rcc_periph_clken clken; 24 | switch (base) { 25 | case I2C1: 26 | clken = RCC_I2C1; 27 | break; 28 | case I2C2: 29 | clken = RCC_I2C2; 30 | break; 31 | default: 32 | assert(false && "unknown I2C base address"); 33 | } 34 | rcc_periph_clock_enable(clken); 35 | 36 | gpio_init_pins(ip->i_pins, (&ip->i_pins)[1] - ip->i_pins); 37 | 38 | uint32_t i2c_freq_mhz = rcc_apb1_frequency / 1000000; 39 | uint32_t ccr = rcc_apb1_frequency / I2C_BAUD / 2 + 1; 40 | if (ccr < 4) 41 | ccr = 4; 42 | 43 | i2c_peripheral_disable(base); 44 | i2c_set_clock_frequency(base, i2c_freq_mhz); 45 | i2c_set_trise(base, i2c_freq_mhz + 1); 46 | i2c_set_ccr(base, ccr); 47 | I2C_CR1(base) = 0; 48 | I2C_OAR1(base) = ip->i_own_address; 49 | i2c_peripheral_enable(base); 50 | } 51 | 52 | void i2c_transmit(const i2c_channel *cp, const uint8_t *data, size_t count) 53 | { 54 | uint32_t base = cp->i_base_address; 55 | 56 | if (cp->i_is_master) { 57 | 58 | // Send start condition. 59 | I2C_CR1(base) |= I2C_CR1_START; 60 | uint32_t t0 = system_millis; 61 | while (!(I2C_SR1(base) & I2C_SR1_SB)) { 62 | if (system_millis >= t0 + TIMEOUT_MSEC) { 63 | fprintf(stderr, "i2c: timeout on SB\n"); 64 | return; 65 | } 66 | } 67 | 68 | // Send slave address. 69 | I2C_DR(base) = cp->i_address & ~0x01; 70 | t0 = system_millis; 71 | while (!(I2C_SR1(base) & I2C_SR1_ADDR)) { 72 | if (I2C_SR1(base) & I2C_SR1_AF) { 73 | I2C_CR1(base) |= I2C_CR1_STOP; 74 | I2C_SR1(base) = ~I2C_SR1_AF; 75 | fprintf(stderr, 76 | "i2c @ %ld: ack failure on addr\n", 77 | system_millis / 1000); 78 | return; 79 | } 80 | if (system_millis >= t0 + TIMEOUT_MSEC) { 81 | fprintf(stderr, "i2c: timeout on ADDR\n"); 82 | return; 83 | } 84 | } 85 | 86 | // Clear ADDR flag by reading SR1 and SR2 registers. 87 | uint16_t unused; 88 | unused = I2C_SR1(base); 89 | unused = I2C_SR2(base); 90 | unused = unused; 91 | 92 | // Write each data byte; wait for BTF. 93 | for (size_t i = 0; i < count; i++) { 94 | I2C_DR(base) = data[i]; 95 | t0 = system_millis; 96 | while (!(I2C_SR1(base) & I2C_SR1_BTF)) { 97 | if (system_millis >= t0 + TIMEOUT_MSEC) { 98 | fprintf(stderr, "i2c: timeout on BTF\n"); 99 | return; 100 | } 101 | } 102 | } 103 | I2C_CR1(base) |= I2C_CR1_STOP; 104 | fprintf(stderr, "i2c @ %lu: transmit complete\n", system_millis / 1000); 105 | } else { 106 | assert(false && "slave transmission not implemented"); 107 | } 108 | } 109 | 110 | void i2c_receive(const i2c_channel *cp, uint8_t *data, size_t count) 111 | { 112 | uint32_t base = cp->i_base_address; 113 | 114 | if (cp->i_is_master) { 115 | 116 | I2C_CR1(base) |= I2C_CR1_ACK; 117 | 118 | // Send start condition. 119 | I2C_CR1(base) |= I2C_CR1_START; 120 | uint32_t t0 = system_millis; 121 | while (!(I2C_SR1(base) & I2C_SR1_SB)) { 122 | if (system_millis >= t0 + TIMEOUT_MSEC) { 123 | fprintf(stderr, "i2c: timeout on SB\n"); 124 | printf("SR1 = %#lx\n", I2C_SR1(base)); 125 | return; 126 | } 127 | } 128 | 129 | // Send slave address. 130 | I2C_DR(base) = cp->i_address | 0x01; 131 | t0 = system_millis; 132 | while (!(I2C_SR1(base) & I2C_SR1_ADDR)) { 133 | if (I2C_SR1(base) & I2C_SR1_AF) { 134 | I2C_CR1(base) |= I2C_CR1_STOP; 135 | I2C_SR1(base) = ~I2C_SR1_AF; 136 | fprintf(stderr, 137 | "i2c @ %ld: ack failure on addr\n", 138 | system_millis / 1000); 139 | return; 140 | } 141 | if (system_millis >= t0 + TIMEOUT_MSEC) { 142 | fprintf(stderr, "i2c: timeout on ADDR\n"); 143 | return; 144 | } 145 | } 146 | 147 | // Clear ADDR flag by reading SR1 and SR2 registers. 148 | uint16_t unused; 149 | unused = I2C_SR1(base); 150 | unused = I2C_SR2(base); 151 | unused = unused; 152 | 153 | // Read each data byte; wait for BTF. 154 | for (size_t i = 0; i < count; i++) { 155 | if (i + 1 == count) 156 | I2C_CR1(base) &= ~I2C_CR1_ACK; 157 | t0 = system_millis; 158 | while (true) { 159 | uint32_t sr1 = I2C_SR1(base); 160 | if (sr1 & (I2C_SR1_OVR | I2C_SR1_BERR)) { 161 | fprintf(stderr, "i2c: receive error\n"); 162 | break; 163 | } 164 | if (sr1 & I2C_SR1_RxNE) 165 | break; 166 | if (system_millis >= t0 + TIMEOUT_MSEC) { 167 | fprintf(stderr, "i2c: timeout on receive\n"); 168 | } 169 | } 170 | data[i] = I2C_DR(base); 171 | I2C_DR(base) = data[i]; 172 | } 173 | printf("%lu: I2C receive complete\n", system_millis / 1000); 174 | } else { 175 | assert(false && "slave reception not implemented"); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /firmware/src/i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef I2C_included 2 | #define I2C_included 3 | 4 | #include 5 | #include 6 | 7 | #include "gpio.h" 8 | 9 | typedef struct i2c_config { 10 | uint32_t i_base_address; 11 | uint16_t i_own_address; 12 | gpio_pin i_pins[2]; 13 | } i2c_config; 14 | 15 | typedef struct i2c_channel { 16 | uint32_t i_base_address; 17 | bool i_is_master; 18 | bool i_stop; 19 | uint16_t i_address; 20 | } i2c_channel; 21 | 22 | extern void i2c_init (i2c_config const *ip); 23 | 24 | extern void i2c_transmit (i2c_channel const *ip, 25 | uint8_t const *data, 26 | size_t count); 27 | extern void i2c_receive (i2c_channel const *ip, 28 | uint8_t *data, 29 | size_t count); 30 | 31 | #endif /* !I2C_included */ 32 | -------------------------------------------------------------------------------- /firmware/src/intr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef INTR_H 21 | #define INTR_H 22 | 23 | #include 24 | 25 | #define WITH_INTERRUPTS_MASKED \ 26 | for (bool wim_interrupts_are_masked = cm_is_masked_interrupts(), \ 27 | wim_first_time = (cm_disable_interrupts(), true); \ 28 | wim_first_time; \ 29 | wim_interrupts_are_masked ? (void)0 : cm_enable_interrupts(), \ 30 | wim_first_time = false) 31 | 32 | #endif /* INTR_H */ 33 | -------------------------------------------------------------------------------- /firmware/src/lcd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef LCD_H 21 | #define LCD_H 22 | 23 | #include 24 | 25 | #include "gfx-pixslice.h" 26 | 27 | #define LCD_WIDTH 320 28 | #define LCD_HEIGHT 240 29 | #define LCD_MAX_SLICE_ROWS (LCD_HEIGHT / 5) 30 | #define LCD_MAX_SLICE_PIXELS (LCD_MAX_SLICE_ROWS * LCD_WIDTH) 31 | #define LCD_MAX_SLICE_BYTES (LCD_MAX_SLICE_PIXELS * sizeof (gfx_rgb565)) 32 | 33 | // Init the clocks, GPIO pins, timer, DMA controller, ILI9341 chip, 34 | // and pixslice DMA buffers. 35 | void lcd_init(void); 36 | 37 | // Use alloc_pixslice to get DMA-capable slices. 38 | // Maximum size is 64 KB (32 Kpixels). 39 | // Slices are pre-cleared to the background color. 40 | gfx_pixslice *lcd_alloc_pixslice(int x, int y, size_t w, size_t h); 41 | 42 | // Send pixels to screen and deallocate slice. 43 | void lcd_send_pixslice(gfx_pixslice *); 44 | 45 | // Set the background pixel color. 46 | // 47 | // If immediate, the next slice allocated will have the new color. 48 | // Otherwise, color change will take effect after 0-2 allocations. 49 | void lcd_set_bg_color(gfx_rgb565 color, bool immediate); 50 | 51 | // Get the background pixel color. 52 | gfx_rgb565 lcd_bg_color(void); 53 | 54 | // Backlight control 55 | void lcd_bl_on(void); 56 | void lcd_bl_off(void); 57 | void lcd_bl_toggle(void); 58 | 59 | #endif /* !LCD_H */ 60 | -------------------------------------------------------------------------------- /firmware/src/led.c: -------------------------------------------------------------------------------- 1 | #include "led.h" 2 | 3 | #include "gpio.h" 4 | 5 | static const gpio_pin led_pin = { 6 | .gp_port = GPIOA, 7 | .gp_pin = GPIO8, 8 | .gp_mode = GPIO_MODE_OUTPUT, 9 | .gp_level = 1, 10 | }; 11 | 12 | void led_init(void) 13 | { 14 | gpio_init_pin(&led_pin); 15 | } 16 | 17 | bool led_get(void) 18 | { 19 | return !gpio_get(led_pin.gp_port, led_pin.gp_pin); 20 | } 21 | 22 | void led_set(bool on_off) 23 | { 24 | if (on_off) { 25 | led_on(); 26 | } else { 27 | led_off(); 28 | } 29 | } 30 | 31 | void led_on(void) 32 | { 33 | gpio_clear(led_pin.gp_port, led_pin.gp_pin); 34 | } 35 | 36 | void led_off(void) 37 | { 38 | gpio_set(led_pin.gp_port, led_pin.gp_pin); 39 | } 40 | 41 | void led_toggle(void) 42 | { 43 | gpio_toggle(led_pin.gp_port, led_pin.gp_pin); 44 | } 45 | -------------------------------------------------------------------------------- /firmware/src/led.h: -------------------------------------------------------------------------------- 1 | #ifndef LED_included 2 | #define LED_included 3 | 4 | // Control the LED on the 1Bitsy board. 5 | 6 | #include 7 | 8 | extern void led_init(void); 9 | 10 | extern bool led_get(void); 11 | 12 | extern void led_set(bool); 13 | extern void led_on(void); 14 | extern void led_off(void); 15 | extern void led_toggle(void); 16 | 17 | #endif /* ! LED_included */ 18 | -------------------------------------------------------------------------------- /firmware/src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * Copyright (C) 2017 Piotr Esden-Tempski 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "button_boot.h" 29 | #include "gamepad.h" 30 | #include "touch.h" 31 | #include "i2c.h" 32 | #include "lcd.h" 33 | #include "led.h" 34 | #include "math-util.h" 35 | #include "pam8019.h" 36 | #include "volume.h" 37 | #include "systick.h" 38 | #include "text.h" 39 | 40 | /* "Apps" */ 41 | #include "munch_app.h" 42 | #include "tile_app.h" 43 | #include "audio_app.h" 44 | #include "fblocks_app.h" 45 | 46 | #define MY_CLOCK (rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_168MHZ]) 47 | #define BG_COLOR 0x0000 // black 48 | 49 | uint32_t fps; 50 | 51 | enum app_ids { 52 | munch_app, 53 | tile_app, 54 | audio_app, 55 | fblocks_app, 56 | end_app 57 | } active_app = munch_app; 58 | 59 | /* Function pointers to available apps. The first one executes by default. 60 | * Do not forget to adjust the enum if you are messing around with this list. 61 | */ 62 | struct app { 63 | void (*init)(void); 64 | void (*animate)(void); 65 | void (*render)(void); 66 | void (*end)(void); 67 | } apps[] = { 68 | [munch_app] = { 69 | .init = munch_init, 70 | .animate = munch_animate, 71 | .render = munch_render, 72 | .end = NULL, 73 | }, 74 | [tile_app] = { 75 | .init = tile_init, 76 | .animate = tile_animate, 77 | .render = tile_render, 78 | .end = NULL, 79 | }, 80 | [audio_app] = { 81 | .init = audio_app_init, 82 | .animate = audio_animate, 83 | .render = audio_render, 84 | .end = audio_app_end, 85 | }, 86 | [fblocks_app] = { 87 | .init = fblocks_init, 88 | .animate = fblocks_animate, 89 | .render = fblocks_render, 90 | .end = NULL, 91 | }, 92 | }; 93 | 94 | static void handle_systick(uint32_t millis) 95 | { 96 | button_pressed_debounce(); 97 | } 98 | 99 | static void setup(void) 100 | { 101 | rcc_clock_setup_hse_3v3(&MY_CLOCK); 102 | flash_prefetch_enable(); 103 | flash_icache_enable(); 104 | flash_dcache_enable(); 105 | 106 | setup_systick(MY_CLOCK.ahb_frequency); 107 | register_systick_handler(handle_systick); 108 | 109 | led_init(); 110 | 111 | lcd_set_bg_color(BG_COLOR, false); 112 | lcd_init(); 113 | 114 | pam8019_init(); 115 | 116 | text_init(); 117 | 118 | gamepad_init(); 119 | touch_init(); 120 | 121 | /* Disabling debug outputs, as the audio repair board uses these pins. 122 | * At present (11/2017), the pins PC5 and PC13 are available for debug. 123 | */ 124 | 125 | /* Raise ~SHUTDOWN to enable audio output. */ 126 | pam8019_set_mode(PM_SHUTDOWN); 127 | // gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3); 128 | // gpio_set(GPIOA, GPIO3); 129 | // gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO0); 130 | } 131 | 132 | static void calc_fps(void) 133 | { 134 | static uint32_t next_time; 135 | static uint32_t frame_count; 136 | frame_count++; 137 | /* gpio_toggle(GPIOA, GPIO1); */ 138 | if (system_millis >= next_time) { 139 | fps = frame_count; 140 | frame_count = 0; 141 | next_time += 1000; 142 | } 143 | } 144 | 145 | static void check_app_switch(void) 146 | { 147 | static bool state = false; 148 | 149 | if (!state) { 150 | if (button_pressed_debounce()) { 151 | if (apps[active_app].end) { 152 | apps[active_app].end(); 153 | } 154 | active_app++; 155 | if (active_app == end_app) { 156 | active_app = 0; 157 | } 158 | if (apps[active_app].init) { 159 | apps[active_app].init(); 160 | } 161 | state = true; 162 | gpio_clear(GPIOA, GPIO8); 163 | } 164 | } else { 165 | if (button_released_debounce()) { 166 | state = false; 167 | gpio_set(GPIOA, GPIO8); 168 | } 169 | } 170 | } 171 | 172 | static void run(void) 173 | { 174 | if (apps[active_app].init) { 175 | apps[active_app].init(); 176 | } 177 | while (true) { 178 | apps[active_app].animate(); 179 | apps[active_app].render(); 180 | check_app_switch(); 181 | calc_fps(); 182 | } 183 | } 184 | 185 | int main(void) 186 | { 187 | /* Launch the ROM DFU bootloader if the user button is pressed just after 188 | * reset. 189 | */ 190 | button_boot(); 191 | 192 | setup(); 193 | run(); 194 | } 195 | 196 | -------------------------------------------------------------------------------- /firmware/src/math-util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | #define CAT2_H(a, b) a##b 5 | #define CAT_H(a, b) CAT2_H(a, b) 6 | #define TMPVAR_H() CAT_H(tmp__, __COUNTER__) 7 | 8 | 9 | #define MIN(a, b) MIN_H(a, b, TMPVAR_H(), TMPVAR_H()) 10 | #define MIN_H(a, b, t1, t2) ({ \ 11 | __typeof__ (a) t1 = (a); \ 12 | __typeof__ (b) t2 = (b); \ 13 | t1 < t2 ? t1 : t2; \ 14 | }) 15 | 16 | #define MAX(a, b) MAX_H(a, b, TMPVAR_H(), TMPVAR_H()) 17 | #define MAX_H(a, b, t1, t2) ({ \ 18 | __typeof__ (a) t1 = (a); \ 19 | __typeof__ (b) t2 = (b); \ 20 | t1 > t2 ? t1 : t2; \ 21 | }) 22 | 23 | #define CLAMP(min, max, x) MAX(min, MIN(max, x)) 24 | 25 | // SIGN(x) * ABS(x) == x 26 | 27 | #define ABS(a) ABS_H(a, TMPVAR_H()) 28 | #define ABS_H(a, t) ({ \ 29 | __typeof__ (a) t = (a); \ 30 | t >= 0 ? t: -t; \ 31 | }) 32 | 33 | #define SIGN(x) SIGN_H(x, TMPVAR_H()) 34 | #define SIGN_H(x, t) ({ \ 35 | __typeof__ (x) t = (x); \ 36 | t < 0 ? -1 : t > 0 ? +1 : 0; \ 37 | }) 38 | 39 | // FLOOR(x) + FRAC(x) == x 40 | 41 | #define FLOOR(x) FLOOR_H(x, TMPVAR_H()) 42 | #define FLOOR_H(x, t) ({ \ 43 | __typeof__ (x) t = (x); \ 44 | t >= 0 ? (int)t : -(int)-t; \ 45 | }) 46 | 47 | #define CEIL(x) CEIL_H(x, TMPVAR_H()) 48 | #define CEIL_H(x, t) ({ \ 49 | __typeof__ (x) t = (x); \ 50 | t >= 0 ? -(int)-t : (int)t; \ 51 | }) 52 | 53 | #define FRAC(x) FRAC_H(x, TMPVAR_H()) 54 | #define FRAC_H(x, t) ({ \ 55 | __typeof__ (x) t = (x); \ 56 | t >= 0 ? t - (int)t : t + (int)-t; \ 57 | }) 58 | 59 | // FRAC(x) + RFRAC(x) == 1 60 | #define RFRAC(x) (1 - FRAC(x)) 61 | 62 | #define ROUND(x) FLOOR(x + 0.5) 63 | 64 | #endif /* UTIL_H */ 65 | -------------------------------------------------------------------------------- /firmware/src/munch_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include "munch_app.h" 23 | 24 | #include "lcd.h" 25 | #include "math-util.h" 26 | 27 | /* The classic Munching Square eye candy app. */ 28 | 29 | gfx_rgb565 munch_base_color; 30 | 31 | // uint16_t munch_magic = 27; // try different values 32 | uint16_t munch_magic = 20 << 11 | 27; // This is more colorful. 33 | 34 | 35 | void munch_init(void) 36 | { 37 | 38 | } 39 | 40 | void munch_animate(void) 41 | { 42 | /* We want to change the magic number on every color overflow. */ 43 | // #pragma GCC diagnostic push 44 | // #pragma GCC diagnostic ignored "-Wstrict-overflow" 45 | // if (munch_base_color > (munch_base_color + 0x0021)) { 46 | // #pragma GCC diagnostic pop 47 | // munch_magic+=10; 48 | // if (munch_magic > 100) { 49 | // munch_magic = 10; 50 | // } 51 | // } 52 | munch_base_color += 0x0021; 53 | } 54 | 55 | /* Borrow the framerate function from tile app. */ 56 | extern void tile_draw_fps(gfx_pixslice *slice); 57 | 58 | static void munch_render_slice(gfx_pixslice *slice) 59 | { 60 | const int y_off = -8; 61 | const int x_off = 32; 62 | 63 | gpio_set(GPIOA, GPIO3); 64 | 65 | int y0 = MAX(0, slice->y - y_off); 66 | int y1 = MIN(256, slice->y + (int)slice->h - y_off); 67 | int x0 = MAX(0, slice->x - x_off); 68 | int x1 = MIN(256, x0 + slice->w - x_off); 69 | gfx_rgb565 base = munch_base_color; 70 | for (int y = y0; y < y1; y++) { 71 | gfx_rgb565 *p = 72 | gfx_pixel_address_unchecked(slice, x0 + x_off, y + y_off); 73 | for (int x = x0; x < x1; x++) 74 | *p++ = base + munch_magic * (x ^ y); 75 | } 76 | 77 | if (slice->y == 0) { 78 | tile_draw_fps(slice); 79 | } 80 | 81 | gpio_clear(GPIOA, GPIO3); 82 | } 83 | 84 | void munch_render(void) 85 | { 86 | size_t h; 87 | 88 | for (size_t y = 0; y < LCD_HEIGHT; y += h) { 89 | h = MIN(LCD_MAX_SLICE_ROWS, LCD_HEIGHT - y); 90 | gfx_pixslice *slice = lcd_alloc_pixslice(0, y, LCD_WIDTH, h); 91 | munch_render_slice(slice); 92 | lcd_send_pixslice(slice); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /firmware/src/munch_app.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef MUNCH_APP_H 21 | #define MUNCH_APP_H 22 | 23 | void munch_init(void); 24 | void munch_animate(void); 25 | void munch_render(void); 26 | 27 | #endif /* MUNCH_APP_H */ -------------------------------------------------------------------------------- /firmware/src/pam8019.c: -------------------------------------------------------------------------------- 1 | #include "pam8019.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "gpio.h" 9 | 10 | #define HP_SENSE_PORT GPIOA 11 | #define HP_SENSE_PIN GPIO0 12 | #define VOL_PORT GPIOA 13 | #define VOL_PIN GPIO1 14 | #define VOL_ADC_CHAN 1 15 | #define MUTE_PORT GPIOA 16 | #define MUTE_PIN GPIO2 17 | #define SHUTDOWN_PORT GPIOA 18 | #define SHUTDOWN_PIN GPIO3 19 | 20 | 21 | static const gpio_pin pam8019_pins[] = { 22 | { // HP SENSE (bidirectional, initially input) 23 | .gp_port = HP_SENSE_PORT, 24 | .gp_pin = HP_SENSE_PIN, 25 | .gp_mode = GPIO_MODE_INPUT, 26 | }, 27 | { // VOL_ADC 28 | .gp_port = VOL_PORT, 29 | .gp_pin = VOL_PIN, 30 | .gp_mode = GPIO_MODE_ANALOG, 31 | }, 32 | { // MUTE 33 | .gp_port = MUTE_PORT, 34 | .gp_pin = MUTE_PIN, 35 | .gp_mode = GPIO_MODE_OUTPUT, 36 | .gp_level = 0, 37 | }, 38 | { // SHUTDOWN 39 | .gp_port = SHUTDOWN_PORT, 40 | .gp_pin = SHUTDOWN_PIN, 41 | .gp_mode = GPIO_MODE_OUTPUT, 42 | .gp_level = 0, // default is shut down. 43 | }, 44 | }; 45 | 46 | static const size_t pam8019_pin_count = (&pam8019_pins)[1] - pam8019_pins; 47 | 48 | static void enable_override(void) 49 | { 50 | #if 0 51 | gpio_mode_setup(HP_SENSE_PORT, 52 | GPIO_MODE_OUTPUT, 53 | GPIO_PUPD_NONE, 54 | HP_SENSE_PIN); 55 | #else 56 | static const gpio_pin sense_output = { 57 | .gp_port = HP_SENSE_PORT, 58 | .gp_pin = HP_SENSE_PIN, 59 | .gp_mode = GPIO_MODE_OUTPUT, 60 | .gp_otype = GPIO_OTYPE_PP, 61 | }; 62 | gpio_config_pin(&sense_output); 63 | #endif 64 | } 65 | 66 | static void disable_override(void) 67 | { 68 | #if 0 69 | gpio_mode_setup(HP_SENSE_PORT, 70 | GPIO_MODE_INPUT, 71 | GPIO_PUPD_NONE, 72 | HP_SENSE_PIN); 73 | #else 74 | static const gpio_pin sense_input = { 75 | .gp_port = HP_SENSE_PORT, 76 | .gp_pin = HP_SENSE_PIN, 77 | .gp_mode = GPIO_MODE_INPUT, 78 | }; 79 | gpio_config_pin(&sense_input); 80 | #endif 81 | } 82 | 83 | void pam8019_init(void) 84 | { 85 | gpio_init_pins(pam8019_pins, pam8019_pin_count); 86 | 87 | rcc_periph_clock_enable(RCC_ADC1); 88 | 89 | adc_power_off(ADC1); 90 | adc_disable_scan_mode(ADC1); 91 | adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_3CYC); 92 | adc_power_on(ADC1); 93 | } 94 | 95 | pam8019_mode pam8019_get_mode(void) 96 | { 97 | if (!gpio_get(SHUTDOWN_PORT, SHUTDOWN_PIN)) 98 | return PM_SHUTDOWN; 99 | 100 | if (gpio_get(MUTE_PORT, MUTE_PIN)) 101 | return PM_MUTED; 102 | 103 | uint32_t mode = GPIO_MODER(HP_SENSE_PORT); 104 | mode /= HP_SENSE_PIN * HP_SENSE_PIN; 105 | if ((mode & 0x03) == GPIO_MODE_INPUT) 106 | return PM_NORMAL; 107 | 108 | if (gpio_get(HP_SENSE_PORT, HP_SENSE_PIN)) 109 | return PM_OVERRIDE_HP; 110 | else 111 | return PM_OVERRIDE_SPKR; 112 | } 113 | 114 | void pam8019_set_mode(pam8019_mode new_mode) 115 | { 116 | // N.B., SHUTDOWN is active low. MUTE is active high. 117 | 118 | switch (new_mode) { 119 | 120 | case PM_NORMAL: 121 | gpio_set(SHUTDOWN_PORT, SHUTDOWN_PIN); 122 | gpio_clear(MUTE_PORT, MUTE_PIN); 123 | disable_override(); 124 | break; 125 | 126 | case PM_SHUTDOWN: 127 | gpio_clear(SHUTDOWN_PORT, SHUTDOWN_PIN); 128 | break; 129 | 130 | case PM_MUTED: 131 | gpio_set(SHUTDOWN_PORT, SHUTDOWN_PIN); 132 | gpio_set(MUTE_PORT, MUTE_PIN); 133 | break; 134 | 135 | case PM_OVERRIDE_HP: 136 | gpio_set(SHUTDOWN_PORT, SHUTDOWN_PIN); 137 | gpio_clear(MUTE_PORT, MUTE_PIN); 138 | enable_override(); 139 | gpio_set(HP_SENSE_PORT, HP_SENSE_PIN); 140 | break; 141 | 142 | case PM_OVERRIDE_SPKR: 143 | gpio_set(SHUTDOWN_PORT, SHUTDOWN_PIN); 144 | gpio_clear(MUTE_PORT, MUTE_PIN); 145 | enable_override(); 146 | gpio_clear(HP_SENSE_PORT, HP_SENSE_PIN); 147 | break; 148 | 149 | default: 150 | assert(false); 151 | } 152 | } 153 | 154 | bool pam8019_output_is_headphones(void) 155 | { 156 | return (bool)gpio_get(HP_SENSE_PORT, HP_SENSE_PIN); 157 | } 158 | 159 | uint16_t pam8019_get_raw_volume(void) 160 | { 161 | uint8_t channel_array[16] = { VOL_ADC_CHAN }; 162 | adc_set_regular_sequence(ADC1, 1, channel_array); 163 | adc_start_conversion_regular(ADC1); 164 | while (!adc_eoc(ADC1)) 165 | continue; 166 | return 4095 - adc_read_regular(ADC1); 167 | } 168 | -------------------------------------------------------------------------------- /firmware/src/pam8019.h: -------------------------------------------------------------------------------- 1 | #ifndef PAM8019_included 2 | #define PAM8019_included 3 | 4 | // Driver for PAM8019 audio and headphone amplifier by Diodes 5 | // Incorporated, as found on the 1UP audio repair board. 6 | 7 | #include 8 | #include 9 | 10 | typedef enum pam8019_mode { 11 | PM_SHUTDOWN, 12 | PM_MUTED, 13 | PM_NORMAL, 14 | PM_OVERRIDE_HP, // force output to headphones. 15 | PM_OVERRIDE_SPKR, // force output to speakers 16 | PM_END, 17 | PM_START = PM_SHUTDOWN, 18 | } pam8019_mode; 19 | 20 | extern void pam8019_init (void); 21 | 22 | // N.B., You will get no souond until you set the mode 23 | // to NORMAL or OVERRIDE_*. 24 | 25 | extern pam8019_mode pam8019_get_mode (void); 26 | extern void pam8019_set_mode (pam8019_mode); 27 | 28 | extern bool pam8019_output_is_headphones (void); 29 | 30 | extern uint16_t pam8019_get_raw_volume (void); 31 | 32 | #endif /* !PAM8019_included */ 33 | -------------------------------------------------------------------------------- /firmware/src/systick.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #include "systick.h" 21 | 22 | #include 23 | 24 | #include 25 | 26 | volatile uint32_t system_millis; 27 | static systick_handler *current_handler; 28 | 29 | // This is the systick ISR. 30 | void sys_tick_handler(void); 31 | void sys_tick_handler(void) 32 | { 33 | system_millis++; 34 | if (current_handler) 35 | (*current_handler)(system_millis); 36 | } 37 | 38 | void setup_systick(uint32_t cpu_freq) 39 | { 40 | // set tick rate to 1 KHz. 41 | systick_set_reload(cpu_freq / 1000); 42 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); 43 | systick_counter_enable(); 44 | systick_interrupt_enable(); 45 | } 46 | 47 | void register_systick_handler(systick_handler *handler) 48 | { 49 | assert(!current_handler); 50 | current_handler = handler; 51 | } 52 | 53 | void delay_msec(uint32_t msec) 54 | { 55 | uint32_t t0 = system_millis; 56 | while ((system_millis - t0) < msec) 57 | continue; 58 | } 59 | -------------------------------------------------------------------------------- /firmware/src/systick.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy lcd graphics library. 3 | * 4 | * Copyright (C) 2017 Bob Miller 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #ifndef SYSTICK_H 21 | #define SYSTICK_H 22 | 23 | #include 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | typedef void systick_handler(uint32_t millis); 30 | 31 | extern volatile uint32_t system_millis; 32 | 33 | 34 | void setup_systick(uint32_t cpu_freq); 35 | 36 | void register_systick_handler(systick_handler *); 37 | 38 | void delay_msec(uint32_t msec); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif /* SYSTICK_H */ 45 | -------------------------------------------------------------------------------- /firmware/src/text.c: -------------------------------------------------------------------------------- 1 | #include "text.h" 2 | 3 | #include "assets/assets.h" 4 | 5 | void text_init(void) 6 | { 7 | } 8 | 9 | int text_draw_str16(gfx_pixslice *slice, 10 | const char *str, 11 | int x, int y, 12 | gfx_rgb565 color) 13 | { 14 | while (*str) { 15 | text_draw_char16(slice, *str, x, y, color); 16 | x++; 17 | str++; 18 | } 19 | return x; 20 | } 21 | 22 | void text_draw_char16(gfx_pixslice *slice, 23 | char ch, 24 | int x, int y, 25 | gfx_rgb565 color) 26 | { 27 | int xoff = x * 8; 28 | int yoff = y * 16; 29 | 30 | if ((ch < MINIWI_FONT_OFFSET) || 31 | (ch >= MINIWI_FONT_OFFSET + MINIWI_FONT_GLYPH_COUNT)) { 32 | return; 33 | } 34 | 35 | for (int py = 0; py < MINIWI_FONT_HEIGHT; py++) { 36 | gfx_rgb565 *px0 = gfx_pixel_address(slice, xoff, yoff + (py * 2)); 37 | gfx_rgb565 *px1 = gfx_pixel_address(slice, xoff, yoff + (py * 2) + 1); 38 | for (int px = 0; px < MINIWI_FONT_WIDTH; px++) { 39 | if (miniwi_font[ch - MINIWI_FONT_OFFSET][px] & (1 << py)) { 40 | if (px0) { 41 | px0[0] = color; 42 | px0[1] = color; 43 | } 44 | if (px1) { 45 | px1[0] = color; 46 | px1[1] = color; 47 | } 48 | } 49 | if (px0) { 50 | px0 += 2; 51 | } 52 | if (px1) { 53 | px1 += 2; 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /firmware/src/text.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXT_included 2 | #define TEXT_included 3 | 4 | #include "gfx-types.h" 5 | #include "gfx-pixslice.h" 6 | 7 | extern void text_init(void); 8 | 9 | extern int text_draw_str16 (gfx_pixslice *, 10 | const char *str, 11 | int x, int y, 12 | gfx_rgb565 color); 13 | 14 | 15 | extern void text_draw_char16(gfx_pixslice *, 16 | char, 17 | int x, int y, 18 | gfx_rgb565 color); 19 | 20 | #endif /* !TEXT_included */ 21 | -------------------------------------------------------------------------------- /firmware/src/tile_app.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Piotr Esden-Tempski 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "tile_app.h" 25 | 26 | #include "gamepad.h" 27 | #include "touch.h" 28 | #include "lcd.h" 29 | #include "math-util.h" 30 | #include "text.h" 31 | 32 | #include "assets/assets.h" 33 | 34 | gfx_rgb565 color = 0; 35 | 36 | static int16_t map_x_off = 0; 37 | static int16_t map_x_dir = +1; 38 | static int16_t map_y_off = 3 * 8; 39 | 40 | static int16_t spr_x = 10; 41 | static int16_t spr_y = 10; 42 | static int16_t spr_x_dir = +1; 43 | static int16_t spr_y_dir = +1; 44 | 45 | static struct tile_video_state { 46 | uint16_t const *tilemap; 47 | uint16_t tilemap_w; 48 | uint16_t tilemap_h; 49 | uint16_t const *tilesheet; 50 | uint16_t tilesheet_w; 51 | uint16_t tilesheet_h; 52 | uint16_t x_off; 53 | uint16_t y_off; 54 | uint32_t frames; /* just a counter of frames since time began. */ 55 | uint32_t idle; /* time since no gamepad input */ 56 | } tile_video_state; 57 | 58 | /* Selects type of the sprite including fully disabled. */ 59 | enum sprite_type { 60 | S_off, 61 | S_8x8, 62 | S_8x16, 63 | S_16x8, 64 | S_16x16, 65 | }; 66 | 67 | /* Sprite attributes. */ 68 | /* We are using up to 4 tiles from the sprite sheet to represent a single 69 | * sprite object. */ 70 | struct sprite { 71 | uint16_t tiles[4]; 72 | enum sprite_type type; 73 | uint16_t x; 74 | uint16_t y; 75 | }; 76 | 77 | #define SPRITE_MAX_COUNT 16 78 | 79 | struct sprite sprites[SPRITE_MAX_COUNT]; 80 | 81 | void tile_init(void) 82 | { 83 | tile_video_state.tilemap = &tml1_tilemap[0][0][0]; 84 | tile_video_state.tilemap_w = TML1_TILEMAP_WIDTH; 85 | tile_video_state.tilemap_h = TML1_TILEMAP_HEIGHT; 86 | 87 | tile_video_state.tilesheet = &ts_pixmap[0][0]; 88 | tile_video_state.tilesheet_w = TS_PIXMAP_WIDTH; 89 | tile_video_state.tilesheet_h = TS_PIXMAP_HEIGHT; 90 | 91 | tile_video_state.x_off = 0; 92 | tile_video_state.y_off = 0; 93 | 94 | tile_video_state.frames = 0; /* reset time */ 95 | 96 | for(int i = 0; i < SPRITE_MAX_COUNT; i++) { 97 | sprites[i].type = S_off; 98 | } 99 | 100 | sprites[0].type = S_8x16; 101 | sprites[0].tiles[0] = 22; 102 | sprites[0].tiles[1] = 64; 103 | sprites[0].x = 10; 104 | sprites[0].y = 10; 105 | } 106 | 107 | void tile_draw_tile(gfx_pixslice *slice, uint16_t tile_id, int px, int py) 108 | { 109 | int tile_x = (tile_id * 8) % TS_PIXMAP_WIDTH; 110 | int tile_y = ((tile_id * 8) / TS_PIXMAP_WIDTH) * 8; 111 | 112 | if (tile_x >= TS_PIXMAP_WIDTH) 113 | { 114 | return; 115 | } 116 | 117 | if (tile_y >= TS_PIXMAP_HEIGHT) 118 | { 119 | return; 120 | } 121 | 122 | int tile_x0 = 0; 123 | int tile_w = 8; 124 | if (px < 0) { 125 | tile_x0 += -px / 2; 126 | px = 0; 127 | } 128 | else if (px + 16 > LCD_WIDTH) { 129 | tile_w -= (px + 16 - LCD_WIDTH) / 2; 130 | } 131 | 132 | int tile_y0 = 0; 133 | int tile_h = 8; 134 | if (py < 0) { 135 | tile_y0 += -py / 2; 136 | py = 0; 137 | } 138 | else if (py + 16 > LCD_HEIGHT) { 139 | tile_h -= (py + 16 - LCD_HEIGHT) / 2; 140 | } 141 | 142 | 143 | for (int y = tile_y0; y < tile_h; y++) { 144 | gfx_rgb565 *px0 = 145 | gfx_pixel_address(slice, px, py + ((y - tile_y0) * 2)); 146 | gfx_rgb565 *px1 = 147 | gfx_pixel_address(slice, px, py + ((y - tile_y0) * 2) + 1); 148 | 149 | for (int x = tile_x0; x < tile_w; x++) { 150 | uint16_t c = ts_pixmap[tile_y + y][tile_x + x]; 151 | 152 | if (c != 0xF81F) { 153 | if (px0) { 154 | *px0++ = c; 155 | *px0++ = c; 156 | } 157 | if (px1) { 158 | *px1++ = c; 159 | *px1++ = c; 160 | } 161 | } else { 162 | if (px0) px0+=2; 163 | if (px1) px1+=2; 164 | } 165 | } 166 | } 167 | 168 | #if 0 169 | int tile_x = (tile_id * 8) % tile_video_state.tilesheet_w; 170 | int tile_y = ((tile_id * 8) / tile_video_state.tilesheet_w) * 8; 171 | 172 | for (int y = 0; y < 8; y++) { 173 | gfx_rgb565 *px0 = 174 | gfx_pixel_address_unchecked(slice, px, py + (y * 2)); 175 | gfx_rgb565 *px1 = 176 | gfx_pixel_address_unchecked(slice, px, py + (y * 2) + 1); 177 | for (int x = 0; x < 8; x++) { 178 | int tile_pix = 179 | ((tile_y + y) * tile_video_state.tilesheet_w) + 180 | (tile_x + x); 181 | *px0++ = tile_video_state.tilesheet[tile_pix]; 182 | *px0++ = tile_video_state.tilesheet[tile_pix]; 183 | *px1++ = tile_video_state.tilesheet[tile_pix]; 184 | *px1++ = tile_video_state.tilesheet[tile_pix]; 185 | } 186 | } 187 | #endif 188 | } 189 | 190 | void tile_draw_sprite_tile(gfx_pixslice *slice, uint16_t tile_id, int px, int py) 191 | { 192 | int tile_x = (tile_id * 8) % SS_PIXMAP_WIDTH; 193 | int tile_y = ((tile_id * 8) / SS_PIXMAP_WIDTH) * 8; 194 | 195 | /* Check if the tile exists. */ 196 | if (tile_x >= SS_PIXMAP_WIDTH) 197 | { 198 | return; 199 | } 200 | 201 | if (tile_y >= SS_PIXMAP_HEIGHT) 202 | { 203 | return; 204 | } 205 | 206 | /* Trying to draw out of bounds. */ 207 | if ((px < -16) || 208 | (px >= LCD_WIDTH) || 209 | (py < (slice->y - 16)) || 210 | (py >= (slice->y + slice->h))) { 211 | return; 212 | } 213 | 214 | /* Trim draw bounds. */ 215 | int tile_x0 = 0; 216 | int tile_w = 8; 217 | if (px < 0) { 218 | tile_x0 += -px / 2; 219 | px = 0; 220 | } 221 | else if (px + 16 > LCD_WIDTH) { 222 | tile_w -= (px + 16 - LCD_WIDTH) / 2; 223 | } 224 | 225 | int tile_y0 = 0; 226 | int tile_h = 8; 227 | if (py < 0) { 228 | tile_y0 += -py / 2; 229 | py = 0; 230 | } 231 | else if (py + 16 > LCD_HEIGHT) { 232 | tile_h -= (py + 16 - LCD_HEIGHT) / 2; 233 | } 234 | 235 | /* Draw tile. */ 236 | for (int y = tile_y0; y < tile_h; y++) { 237 | gfx_rgb565 *px0 = 238 | gfx_pixel_address(slice, px, py + ((y - tile_y0) * 2)); 239 | gfx_rgb565 *px1 = 240 | gfx_pixel_address(slice, px, py + ((y - tile_y0) * 2) + 1); 241 | 242 | for (int x = tile_x0; x < tile_w; x++) { 243 | uint16_t c = ss_pixmap[tile_y + y][tile_x + x]; 244 | 245 | if (c != 0xF81F) { 246 | if (px0) { 247 | *px0++ = c; 248 | *px0++ = c; 249 | } 250 | if (px1) { 251 | *px1++ = c; 252 | *px1++ = c; 253 | } 254 | } else { 255 | if (px0) px0+=2; 256 | if (px1) px1+=2; 257 | } 258 | } 259 | } 260 | } 261 | 262 | void tile_draw_sprite(gfx_pixslice *slice, struct sprite *sprite) 263 | { 264 | switch(sprite->type) { 265 | case S_off: 266 | return; 267 | case S_8x8: 268 | tile_draw_sprite_tile(slice, sprite->tiles[0], 269 | sprite->x, sprite->y); 270 | break; 271 | case S_8x16: 272 | tile_draw_sprite_tile(slice, sprite->tiles[0], 273 | sprite->x, sprite->y); 274 | tile_draw_sprite_tile(slice, sprite->tiles[1], 275 | sprite->x, sprite->y + 16); 276 | break; 277 | case S_16x8: 278 | tile_draw_sprite_tile(slice, sprite->tiles[0], 279 | sprite->x, sprite->y); 280 | tile_draw_sprite_tile(slice, sprite->tiles[1], 281 | sprite->x + 16, sprite->y); 282 | break; 283 | case S_16x16: 284 | tile_draw_sprite_tile(slice, sprite->tiles[0], 285 | sprite->x, sprite->y); 286 | tile_draw_sprite_tile(slice, sprite->tiles[1], 287 | sprite->x + 16, sprite->y); 288 | tile_draw_sprite_tile(slice, sprite->tiles[2], 289 | sprite->x, sprite->y + 16); 290 | tile_draw_sprite_tile(slice, sprite->tiles[3], 291 | sprite->x + 16, sprite->y + 16); 292 | break; 293 | } 294 | } 295 | 296 | void tile_draw_sprites(gfx_pixslice *slice) 297 | { 298 | for(int i=SPRITE_MAX_COUNT; i > 0; i--) { 299 | tile_draw_sprite(slice, &sprites[i-1]); 300 | } 301 | } 302 | 303 | void tile_draw_char8(gfx_pixslice *slice, char ch, int x, int y, gfx_rgb565 color) 304 | { 305 | int xoff = x * 4; 306 | int yoff = y * 8; 307 | 308 | if ((ch < MINIWI_FONT_OFFSET) || (ch >= (MINIWI_FONT_OFFSET + MINIWI_FONT_GLYPH_COUNT))) { 309 | return; 310 | } 311 | 312 | for (int py = 0; py < 8; py++) { 313 | gfx_rgb565 *px0 = 314 | gfx_pixel_address_unchecked(slice, xoff, yoff + py); 315 | for (int px = 0; px < 4; px++) { 316 | if ((miniwi_font[(int)ch - MINIWI_FONT_OFFSET][px] & (1 << py)) != 0) { 317 | *px0++ = color; 318 | } else { 319 | px0++; 320 | } 321 | } 322 | } 323 | } 324 | 325 | extern uint32_t fps; 326 | 327 | void tile_draw_fps(gfx_pixslice *slice) 328 | { 329 | if (slice->y >= 16) 330 | return; 331 | 332 | uint32_t lfps = fps; 333 | int pos = 0; 334 | char *prefix = "fps: "; 335 | 336 | for (; lfps > 0; lfps /= 10) { 337 | //tile_draw_char8(slice, (lfps % 10) + '0', LCD_WIDTH / 4 - (pos + 1), 0, 0x0000); 338 | text_draw_char16(slice, (lfps % 10) + '0', LCD_WIDTH / 8 - (pos + 1), 0, 0x0000); 339 | pos++; 340 | } 341 | 342 | for (int i = 0; i < 5; i++) { 343 | //tile_draw_char8(slice, prefix[4 - i], LCD_WIDTH / 4 - (pos + 1), 0, 0x0000); 344 | text_draw_char16(slice, prefix[4 - i], LCD_WIDTH / 8 - (pos + 1), 0, 0x0000); 345 | pos++; 346 | } 347 | } 348 | 349 | void tile_draw_gamepad(gfx_pixslice *slice) 350 | { 351 | if (slice->y >= 32) 352 | return; 353 | 354 | char *prefix = "gamepad: "; 355 | uint16_t gamepad = gamepad_get(); 356 | 357 | for (int i = 0; i < 16; i++) { 358 | if ((gamepad & (1 << i)) != 0) { 359 | //tile_draw_char8(slice, '1', LCD_WIDTH / 4 - (i + 1), 1, 0x0000); 360 | text_draw_char16(slice, '1', LCD_WIDTH / 8 - (i + 1), 1, 0x0000); 361 | } else { 362 | //tile_draw_char8(slice, '0', LCD_WIDTH / 4 - (i + 1), 1, 0x0000); 363 | text_draw_char16(slice, '0', LCD_WIDTH / 8 - (i + 1), 1, 0x0000); 364 | } 365 | } 366 | 367 | for (int i = 0; prefix[i] != 0; i++) { 368 | //tile_draw_char8(slice, prefix[i], 369 | // LCD_WIDTH / 4 - (16 + strlen(prefix)) + i, 1, 0x0000); 370 | text_draw_char16(slice, prefix[i], 371 | LCD_WIDTH / 8 - (16 + strlen(prefix)) + i, 1, 0x0000); 372 | } 373 | } 374 | 375 | void tile_draw_touch(gfx_pixslice *slice) 376 | { 377 | if (slice->y >= 48) 378 | return; 379 | 380 | int tx, ty; 381 | bool touched = touch_get(&tx, &ty); 382 | if (!touched) 383 | return; 384 | 385 | char text[16]; 386 | sprintf(text, "touch: %3d, %3d", tx, ty); 387 | 388 | for (int i = 0; text[i] != 0; i++) { 389 | text_draw_char16(slice, text[i], 390 | LCD_WIDTH / 8 - (strlen(text)) + i, 2, 0x0000); 391 | } 392 | } 393 | 394 | void tile_animate(void) 395 | { 396 | #if 0 397 | tile_y += tile_y_inc; 398 | if (tile_y + (TS_PIXMAP_HEIGHT*2) > LCD_HEIGHT) { 399 | tile_y_inc = -1; 400 | tile_y -= 2; 401 | } else if (tile_y < 0) { 402 | tile_y_inc = +1; 403 | tile_y += 1; 404 | } 405 | #endif 406 | static uint16_t delay = 0; 407 | static uint16_t stay = 0; 408 | uint16_t gamepad = gamepad_get(); 409 | int tx, ty; 410 | bool touched = touch_get(&tx, &ty); 411 | 412 | if (gamepad != 0x0000 || touched) { 413 | tile_video_state.idle = 0; 414 | } 415 | 416 | if (touched) { 417 | spr_x = tx - 4; 418 | spr_y = ty - 4; 419 | if (spr_x < 0) { 420 | spr_x = 0; 421 | } else if (spr_x > (19 * 8 * 2)) { 422 | spr_x = 19 * 8 * 2; 423 | } 424 | if (spr_y < 0) { 425 | spr_y = 0; 426 | } else if (spr_y > (19 * 8 * 2)) { 427 | spr_y = 13 * 8 * 2; 428 | } 429 | } 430 | 431 | if ((gamepad != 0xFFFF) && (tile_video_state.idle < (80 * 10))) { 432 | if ((gamepad & GAMEPAD_BLEFT) != 0) { 433 | if (map_x_off > 0) { 434 | map_x_off--; 435 | } 436 | } else if ((gamepad & GAMEPAD_BRIGHT) != 0) { 437 | if (map_x_off < (108 * 8)) { 438 | map_x_off++; 439 | } 440 | } 441 | if ((gamepad & GAMEPAD_BUP) != 0) { 442 | if (map_y_off > 0) { 443 | map_y_off--; 444 | } 445 | } else if ((gamepad & GAMEPAD_BDOWN) != 0) { 446 | if (map_y_off < (3 * 8)) { 447 | map_y_off++; 448 | } 449 | } 450 | 451 | if ((gamepad & GAMEPAD_BY) != 0) { 452 | if (spr_x > 0) { 453 | spr_x--; 454 | } 455 | } else if ((gamepad & GAMEPAD_BA) != 0) { 456 | if (spr_x < (19 * 8 * 2)) { 457 | spr_x++; 458 | } 459 | } 460 | if ((gamepad & GAMEPAD_BX) != 0) { 461 | if (spr_y > 0) { 462 | spr_y--; 463 | } 464 | } else if ((gamepad & GAMEPAD_BB) != 0) { 465 | if (spr_y < (13 * 8 * 2)) { 466 | spr_y++; 467 | } 468 | } 469 | } else { 470 | if (delay == 1) { 471 | delay = 0; 472 | map_x_off += map_x_dir; 473 | if (map_x_off == 108*8) { 474 | map_x_dir = 0; 475 | stay++; 476 | if (stay == 10) { 477 | stay = 0; 478 | map_x_dir = -1; 479 | } 480 | } 481 | if (map_x_off == 0) { 482 | map_x_dir = 0; 483 | stay++; 484 | if (stay == 10) { 485 | stay = 0; 486 | map_x_dir = +1; 487 | } 488 | } 489 | } else { 490 | delay++; 491 | } 492 | 493 | spr_x += spr_x_dir; 494 | spr_y += spr_y_dir; 495 | 496 | if ((spr_x + 14) == (LCD_WIDTH-1)) { 497 | spr_x_dir = -1; 498 | } 499 | 500 | if (spr_x == 0) { 501 | spr_x_dir = 1; 502 | } 503 | 504 | if ((spr_y + 22) == (LCD_HEIGHT-1)) { 505 | spr_y_dir = -1; 506 | } 507 | 508 | if (spr_y == 0) { 509 | spr_y_dir = 1; 510 | } 511 | } 512 | 513 | if ((tile_video_state.frames / 40) % 2) { /* every 80 frames */ 514 | sprites[0].tiles[0] = 43; 515 | sprites[0].tiles[1] = 64; 516 | } else { 517 | sprites[0].tiles[0] = 21; 518 | sprites[0].tiles[1] = 63; 519 | } 520 | 521 | sprites[0].x = spr_x; 522 | sprites[0].y = spr_y; 523 | } 524 | 525 | static void tile_render_slice(gfx_pixslice *slice) 526 | { 527 | 528 | #if 0 529 | /* Draw some lines to indicate drawing direction and pixslice start/end */ 530 | XXX must check pixel address. NULL is out of bounds. 531 | gfx_rgb565 *px = 532 | gfx_pixel_address_unchecked(slice, 0, slice->y); 533 | for (size_t x = 0; x < 10; x++) { 534 | *px++ = 0xFFFF; 535 | } 536 | XXX must check pixel address. NULL is out of bounds. 537 | px = 538 | gfx_pixel_address_unchecked(slice, 0, slice->y + slice->h - 2); 539 | for (size_t x = 0; x < 10; x++) { 540 | *px++ = 0xF800; 541 | } 542 | #endif 543 | 544 | #if 0 545 | for (size_t y = slice->y; y < (slice->y + slice->h); y++ ) { 546 | int32_t yy = (int32_t)y - tile_y; 547 | if (yy < 0 || yy >= (TS_PIXMAP_HEIGHT*2)) 548 | continue; 549 | XXX must check pixel address. NULL is out of bounds. 550 | gfx_rgb565 *px = 551 | gfx_pixel_address_unchecked(slice, 0, y); 552 | for (size_t x = 0; x < slice->w; x++) { 553 | if (x < (TS_PIXMAP_WIDTH*2)) { 554 | if(ts_pixmap[yy/2][x/2]!=0xF81F) { 555 | *px++ = ts_pixmap[yy/2][x/2]; 556 | } else { 557 | px++; 558 | } 559 | } 560 | } 561 | } 562 | #endif 563 | 564 | // if(slice->y == 0) { 565 | // tile_draw_tile(slice, 1, 10, 10); 566 | // } 567 | 568 | /* gpio_set(GPIOA, GPIO3); */ 569 | 570 | /* Tilemap */ 571 | for (size_t y = slice->y / 16; y <= (slice->y + slice->h)/16; y++) { 572 | for (size_t x = 0; x <= slice->w / 16; x++) { 573 | const uint16_t tid = 574 | tml1_tilemap[0][y + map_y_off / 8][x + map_x_off / 8]; 575 | if (tid) { 576 | tile_draw_tile(slice, 577 | tid - 1, 578 | x * 16 - (map_x_off % 8) * 2, 579 | y * 16 - (map_y_off % 8) * 2); 580 | } 581 | } 582 | } 583 | 584 | /* Sprites */ 585 | tile_draw_sprites(slice); 586 | 587 | /* Text */ 588 | if(slice->y == 0) { 589 | tile_draw_fps(slice); 590 | tile_draw_gamepad(slice); 591 | tile_draw_touch(slice); 592 | } 593 | 594 | /* gpio_clear(GPIOA, GPIO3); */ 595 | } 596 | 597 | void tile_render(void) 598 | { 599 | size_t h; 600 | size_t slice_max_h = LCD_MAX_SLICE_ROWS; 601 | color = 0; 602 | 603 | if (lcd_bg_color() != TML1_TILEMAP_BG_COLOR) { 604 | lcd_set_bg_color(TML1_TILEMAP_BG_COLOR, true); 605 | } 606 | 607 | for (size_t y = 0; y < LCD_HEIGHT; y += h) { 608 | h = MIN(slice_max_h, LCD_HEIGHT - y); 609 | gfx_pixslice *slice = lcd_alloc_pixslice(0, y, LCD_WIDTH, h); 610 | tile_render_slice(slice); 611 | lcd_send_pixslice(slice); 612 | } 613 | 614 | tile_video_state.frames++; /* increment time */ 615 | tile_video_state.idle++; /* increment idle time */ 616 | } 617 | -------------------------------------------------------------------------------- /firmware/src/tile_app.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Piotr Esden-Tempski 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef TILE_APP_H 21 | #define TILE_APP_H 22 | 23 | void tile_init(void); 24 | void tile_animate(void); 25 | void tile_render(void); 26 | 27 | #endif /* TILE_APP_H */ -------------------------------------------------------------------------------- /firmware/src/touch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Nicolas Schodet 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "i2c.h" 27 | #include "lcd.h" 28 | 29 | #include "touch.h" 30 | 31 | static const i2c_channel touch_i2c = { 32 | .i_base_address = I2C1, 33 | .i_is_master = true, 34 | .i_stop = true, 35 | .i_address = 0b01110000, 36 | }; 37 | 38 | static volatile bool touch_event = true; 39 | 40 | static bool touch_touched = false; 41 | static int touch_x = 0; 42 | static int touch_y = 0; 43 | 44 | void exti9_5_isr(void) 45 | { 46 | touch_event = true; 47 | exti_reset_request(EXTI5); 48 | } 49 | 50 | void touch_init(void) 51 | { 52 | rcc_periph_clock_enable(RCC_SYSCFG); 53 | 54 | gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO5); 55 | exti_select_source(EXTI5, GPIOB); 56 | exti_set_trigger(EXTI5, EXTI_TRIGGER_FALLING); 57 | exti_enable_request(EXTI5); 58 | exti_reset_request(EXTI5); 59 | nvic_enable_irq(NVIC_EXTI9_5_IRQ); 60 | } 61 | 62 | static void touch_update(void) 63 | { 64 | static const uint8_t req[] = { 0x02 }; 65 | i2c_transmit(&touch_i2c, req, sizeof(req)); 66 | uint8_t rsp[5] = { 0 }; 67 | i2c_receive(&touch_i2c, rsp, sizeof(rsp)); 68 | int count = rsp[0] & 0xf; 69 | if (count && count <= 5) { 70 | touch_touched = true; 71 | touch_y = LCD_HEIGHT - ((rsp[1] & 0xf) << 8 | rsp[2]); 72 | touch_x = ((rsp[3] & 0xf) << 8 | rsp[4]); 73 | } else { 74 | touch_touched = false; 75 | } 76 | } 77 | 78 | bool touch_get(int *x, int *y) 79 | { 80 | if (touch_event) { 81 | touch_event = false; 82 | touch_update (); 83 | } 84 | *x = touch_x; 85 | *y = touch_y; 86 | return touch_touched; 87 | } 88 | -------------------------------------------------------------------------------- /firmware/src/touch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the 1Bitsy 1UP retro inspired game console project. 3 | * 4 | * Copyright (C) 2017 Nicolas Schodet 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef TOUCH_H 21 | #define TOUCH_H 22 | 23 | #include 24 | 25 | // Install touch IRQ. 26 | void touch_init(void); 27 | 28 | // Return current state of touch screen, touched (true) or not (false), and 29 | // if touched, fill coordinates. 30 | bool touch_get(int *x, int *y); 31 | 32 | #endif /* TOUCH_H */ 33 | -------------------------------------------------------------------------------- /firmware/src/volume.c: -------------------------------------------------------------------------------- 1 | #include "volume.h" 2 | 3 | #include "pam8019.h" 4 | 5 | static uint16_t volume_raw_min = 600; // raw volume doesn't go below 570-ish. 6 | 7 | static uint16_t smooth(uint32_t numer, uint32_t denom, uint16_t expected) 8 | { 9 | if (numer + denom / 2 >= expected * denom && 10 | numer - denom / 2 <= (expected + 1) * denom) 11 | return expected; 12 | return numer / denom; 13 | } 14 | 15 | void volume_init(void) 16 | { 17 | } 18 | 19 | uint8_t volume_get(void) 20 | { 21 | uint16_t raw = volume_get_raw(); 22 | 23 | if (volume_raw_min > raw) 24 | volume_raw_min = raw; 25 | uint32_t numerator = raw - volume_raw_min; 26 | uint32_t denominator = VOLUME_RAW_MAX - volume_raw_min; 27 | numerator *= VOLUME_MAX - VOLUME_MIN + 1; 28 | 29 | static uint16_t smoothed_vol = UINT16_MAX; 30 | smoothed_vol = smooth(numerator, denominator, smoothed_vol); 31 | // smoothed_vol = numerator / denominator; 32 | 33 | 34 | return smoothed_vol; 35 | } 36 | 37 | uint16_t volume_get_raw(void) 38 | { 39 | return pam8019_get_raw_volume(); 40 | } 41 | -------------------------------------------------------------------------------- /firmware/src/volume.h: -------------------------------------------------------------------------------- 1 | #ifndef VOLUME_included 2 | #define VOLUME_included 3 | 4 | #include 5 | 6 | #define VOLUME_MIN 0 7 | #define VOLUME_MAX 64 8 | #define VOLUME_RAW_MAX 4095 9 | 10 | extern void volume_init (void); 11 | extern uint8_t volume_get (void); 12 | 13 | extern uint16_t volume_get_raw (void); 14 | 15 | #endif /* !VOLUME_included */ 16 | -------------------------------------------------------------------------------- /hardware/NOTES.md: -------------------------------------------------------------------------------- 1 | # Other Projects 2 | * [Circuit Sword (RPi)](https://github.com/kiteretro/Circuit-Sword/wiki/GB-Original-Case-Mod-Guide) 3 | * [uGame (ATSAMD21)](https://hackaday.io/project/27629-game) 4 | * [Lameboy (ESP8266)](https://hackaday.io/project/26823-lameboy-another-esp12-handheld) 5 | 6 | # Possible tact switch options 7 | * If we use an existing industrial design we should consider using the original membrane switches 8 | * If we work on a micro tiny board we should look into SKPMAPE010 from ALPS used also by uGame 9 | -------------------------------------------------------------------------------- /hardware/V0.1/1bitsy-1up-cache.lib: -------------------------------------------------------------------------------- 1 | EESchema-LIBRARY Version 2.3 2 | #encoding utf-8 3 | # 4 | # +3V3 5 | # 6 | DEF +3V3 #PWR 0 0 Y Y 1 F P 7 | F0 "#PWR" 0 -150 50 H I C CNN 8 | F1 "+3V3" 0 140 50 H V C CNN 9 | F2 "" 0 0 50 H I C CNN 10 | F3 "" 0 0 50 H I C CNN 11 | ALIAS +3.3V 12 | DRAW 13 | P 2 0 1 0 -30 50 0 100 N 14 | P 2 0 1 0 0 0 0 100 N 15 | P 2 0 1 0 0 100 30 50 N 16 | X +3V3 1 0 0 0 U 50 50 1 1 W N 17 | ENDDRAW 18 | ENDDEF 19 | # 20 | # +5V 21 | # 22 | DEF +5V #PWR 0 0 Y Y 1 F P 23 | F0 "#PWR" 0 -150 50 H I C CNN 24 | F1 "+5V" 0 140 50 H V C CNN 25 | F2 "" 0 0 50 H I C CNN 26 | F3 "" 0 0 50 H I C CNN 27 | DRAW 28 | P 2 0 1 0 -30 50 0 100 N 29 | P 2 0 1 0 0 0 0 100 N 30 | P 2 0 1 0 0 100 30 50 N 31 | X +5V 1 0 0 0 U 50 50 1 1 W N 32 | ENDDRAW 33 | ENDDEF 34 | # 35 | # +BATT 36 | # 37 | DEF +BATT #PWR 0 0 Y Y 1 F P 38 | F0 "#PWR" 0 -150 50 H I C CNN 39 | F1 "+BATT" 0 140 50 H V C CNN 40 | F2 "" 0 0 50 H I C CNN 41 | F3 "" 0 0 50 H I C CNN 42 | DRAW 43 | P 2 0 1 0 -30 50 0 100 N 44 | P 2 0 1 0 0 0 0 100 N 45 | P 2 0 1 0 0 100 30 50 N 46 | X +BATT 1 0 0 0 U 50 50 1 1 W N 47 | ENDDRAW 48 | ENDDEF 49 | # 50 | # 1bitsy-complete-concise 51 | # 52 | DEF 1bitsy-complete-concise U 0 40 Y Y 1 F N 53 | F0 "U" 0 100 60 H V C CNN 54 | F1 "1bitsy-complete-concise" 0 0 60 H V C CNN 55 | F2 "" 0 100 60 H I C CNN 56 | F3 "" 0 100 60 H I C CNN 57 | DRAW 58 | S -2400 1300 2400 -1300 0 1 0 N 59 | X GND 1 -2600 1200 200 R 50 50 1 1 P 60 | X PC10/SPI3SCK/I2S3CK/USART3&4_TX/SDIOD2 2 -2600 1100 200 R 50 50 1 1 P 61 | X PC11/ADCEXTI11/I2S3EXTSD/SPI3MISO/USART3&4_RX/SDIOD3 3 -2600 1000 200 R 50 50 1 1 P 62 | X PC12/SPI3MOSI/I2S3SD/USART3CK/UART5TX/SDIOCK 4 -2600 900 200 R 50 50 1 1 P 63 | X PD2/T2ETR/UART5RX/SDIOCMD 5 -2600 800 200 R 50 50 1 1 P 64 | X PB4/~JTRST~/T3C1/SPI1&3_MISO/I2S3EXTSD 6 -2600 700 200 R 50 50 1 1 P 65 | X PB5/T3C2/I2C1SMBA/SPI1&3_MOSI/I2S3SD/CAN2RX/ULPID7 7 -2600 600 200 R 50 50 1 1 P 66 | X PB6/T4C1/I2C1SCL/USART1TX/CAN2TX 8 -2600 500 200 R 50 50 1 1 P 67 | X PB7/T4C2/I2C1SDA/USART1RX 9 -2600 400 200 R 50 50 1 1 P 68 | X PB8/T4C3/TI0C1/I2C1SCL/CAN2RX/SDIOD4 10 -2600 300 200 R 50 50 1 1 P 69 | X PB11/T2C4/I2C2SDA/USART3RX/ULPID4 20 2600 200 200 L 50 50 1 1 P 70 | X VIN 30 2600 1200 200 L 50 50 1 1 P 71 | X PC5/ADC15 40 2600 -400 200 L 50 50 1 1 P 72 | X PB9/T4C4/T1C1/I2C1SDA/SPI2NSS/I2S2WS/CAN2TX/SDIOD5 11 -2600 200 200 R 50 50 1 1 P 73 | X PB12/T1BK/I2C2SMBA/SPI2NSS/I2S2WS/USART3CK/CAN2RX/ULPID5/HSID 21 2600 300 200 L 50 50 1 1 P 74 | X PA0-WKUP/ADC0/T2C1ETR/T5C1/T8ETR/USART2CTS/UART4TX 31 -2600 -400 200 R 50 50 1 1 P 75 | X LED|PA8-MCO1/T1C1/I2C3SCL/USART1CK/OTGFSSOF 41 -2600 -1000 200 R 50 50 1 1 P 76 | X PC2/ADC12/SPI2MISO/I2S2EXTSD/ULPIDIR 12 -2600 100 200 R 50 50 1 1 P 77 | X PB13/T1C1N/SPI2SCK/12S2CK/USART3CTS/CAN2TX/ULPID6 22 2600 400 200 L 50 50 1 1 P 78 | X PA1/ADC1/T2C2/T5C2/USART2RTS/UART4RX 32 -2600 -500 200 R 50 50 1 1 P 79 | X PC13 42 -2600 -1100 200 R 50 50 1 1 P 80 | X PC3/ADC13/SPI2MOSI/I2S2SD/ULPINXT 13 -2600 0 200 R 50 50 1 1 P 81 | X PB14/T1&8C2N/SPI2MISO/I2S2EXTSD/USART3RTS/T12C1/HSDM 23 2600 500 200 L 50 50 1 1 P 82 | X PA2/ADC2/T2C3/T5C3/T9C1/USART2TX 33 -2600 -600 200 R 50 50 1 1 P 83 | X PC0/ADC10/ULPISTP 43 -2600 -1200 200 R 50 50 1 1 P 84 | X VBAT 14 -2600 -100 200 R 50 50 1 1 P 85 | X PB15/T1&8C3N/SPI2MOSI/I2S2SD/T12C2/HSDP 24 2600 600 200 L 50 50 1 1 P 86 | X PA3/ADC3/T2C4/T5C4/T9C2/USART2RX/ULPID0 34 -2600 -700 200 R 50 50 1 1 P 87 | X PB2 44 2600 -1000 200 L 50 50 1 1 P 88 | X +3V3 15 -2600 -200 200 R 50 50 1 1 P 89 | X PC6/T3&8C1/I2S2MCK/USART6TX/SDIOD6 25 2600 700 200 L 50 50 1 1 P 90 | X PA4/ADC4/DAC1/SPI1NSS/SPI3NSS/I2S3WS/USART2CK 35 -2600 -800 200 R 50 50 1 1 P 91 | X GND 16 2600 -200 200 L 50 50 1 1 P 92 | X PC7/T3&8C2/I2S3MCK/USART6RX/SDIOD7 26 2600 800 200 L 50 50 1 1 P 93 | X PA5/ADC5/DAC2/T2C1ETR/T8C1N/SPI1SCK/ULPICK 36 2600 -800 200 L 50 50 1 1 P 94 | X PB0/ADC8/T1C2N/T3C3/T8C2N/ULPID1 17 2600 -100 200 L 50 50 1 1 P 95 | X PC8/T3&8C3/USART6CK/SDIOD0 27 2600 900 200 L 50 50 1 1 P 96 | X PA6/ADC6/T1BK/T3C1/T8BK/SPI1MISO/T13C1 37 2600 -700 200 L 50 50 1 1 P 97 | X PB1/ADC9/T1C3N/T3C4/T8C3N 18 2600 0 200 L 50 50 1 1 P 98 | X PC9-MCO2/DACEXTI9/T3&8C4/I2C3SDA/I2S2CHIN/SDIOD1 28 2600 1000 200 L 50 50 1 1 P 99 | X PA7/ADC7/T1C1N/T3C2/T8C1N/SPI1MOSI/T12C2 38 2600 -600 200 L 50 50 1 1 P 100 | X PB10/T2C3/I2C2SCL/SPI2SCK/I2S2CK/USART3TX/ULPID3 19 2600 100 200 L 50 50 1 1 P 101 | X +3V3 29 2600 1100 200 L 50 50 1 1 P 102 | X PC4/ADC14 39 2600 -500 200 L 50 50 1 1 P 103 | ENDDRAW 104 | ENDDEF 105 | # 106 | # 74HC165 107 | # 108 | DEF 74HC165 U 0 40 Y Y 1 F N 109 | F0 "U" 0 -800 60 H V C CNN 110 | F1 "74HC165" 0 750 60 H V C CNN 111 | F2 "" 2190 -1220 60 H I C CNN 112 | F3 "" 2190 -1220 60 H I C CNN 113 | DRAW 114 | S -400 700 400 -700 0 1 0 N 115 | X SH/~LD 1 -600 -600 200 R 50 50 1 1 P 116 | X CLK 2 -600 -400 200 R 50 50 1 1 P 117 | X D4 3 -600 100 200 R 50 50 1 1 P 118 | X D5 4 -600 0 200 R 50 50 1 1 P 119 | X D6 5 -600 -100 200 R 50 50 1 1 P 120 | X D7 6 -600 -200 200 R 50 50 1 1 P 121 | X ~QH 7 600 -400 200 L 50 50 1 1 P 122 | X GND 8 600 -650 200 L 50 50 1 1 P 123 | X QH 9 600 -200 200 L 50 50 1 1 P 124 | X SER 10 -600 600 200 R 50 50 1 1 P 125 | X D0 11 -600 500 200 R 50 50 1 1 P 126 | X D1 12 -600 400 200 R 50 50 1 1 P 127 | X D2 13 -600 300 200 R 50 50 1 1 P 128 | X D3 14 -600 200 200 R 50 50 1 1 P 129 | X CLK_INH 15 -600 -500 200 R 50 50 1 1 P 130 | X VCC 16 600 650 200 L 50 50 1 1 P 131 | ENDDRAW 132 | ENDDEF 133 | # 134 | # BQ24075 135 | # 136 | DEF BQ24075 U 0 40 Y Y 1 F N 137 | F0 "U" 0 -650 60 H V C CNN 138 | F1 "BQ24075" 0 750 60 H V C CNN 139 | F2 "" 2150 -1050 60 H I C CNN 140 | F3 "" 2150 -1050 60 H I C CNN 141 | F4 "ANY" 0 0 60 H I C CNN "Source" 142 | DRAW 143 | S -400 700 400 -600 0 0 0 N 144 | X TS 1 -600 200 200 R 50 50 1 1 P 145 | X BAT 2 -600 400 200 R 50 50 1 1 P 146 | X BAT 3 -600 300 200 R 50 50 1 1 P 147 | X ~CE 4 600 -100 200 L 50 50 1 1 P 148 | X EN2 5 600 200 200 L 50 50 1 1 P 149 | X EN1 6 600 100 200 L 50 50 1 1 P 150 | X ~PGOOD 7 600 -500 200 L 50 50 1 1 P 151 | X VSS 8 -600 -400 200 R 50 50 1 1 P 152 | X ~CHG 9 600 -400 200 L 50 50 1 1 P 153 | X OUT 10 600 500 200 L 50 50 1 1 P 154 | X OUT 11 600 600 200 L 50 50 1 1 P 155 | X ILIM 12 -600 -200 200 R 50 50 1 1 P 156 | X IN 13 -600 600 200 R 50 50 1 1 P 157 | X TMR 14 -600 0 200 R 50 50 1 1 P 158 | X SYSOFF 15 600 0 200 L 50 50 1 1 P 159 | X ISET 16 -600 -100 200 R 50 50 1 1 P 160 | X PAD 17 -600 -500 200 R 50 50 1 1 P 161 | ENDDRAW 162 | ENDDEF 163 | # 164 | # Battery_Cell 165 | # 166 | DEF Battery_Cell BT 0 0 N N 1 F N 167 | F0 "BT" 100 100 50 H V L CNN 168 | F1 "Battery_Cell" 100 0 50 H V L CNN 169 | F2 "" 0 60 50 V I C CNN 170 | F3 "" 0 60 50 V I C CNN 171 | DRAW 172 | S -90 70 90 60 0 1 0 F 173 | S -62 47 58 27 0 1 0 F 174 | P 2 0 1 0 0 30 0 0 N 175 | P 2 0 1 0 0 70 0 100 N 176 | P 2 0 1 10 20 135 60 135 N 177 | P 2 0 1 10 40 155 40 115 N 178 | X + 1 0 200 100 D 50 50 1 1 P 179 | X - 2 0 -100 100 U 50 50 1 1 P 180 | ENDDRAW 181 | ENDDEF 182 | # 183 | # CONN_01X02 184 | # 185 | DEF CONN_01X02 J 0 40 Y N 1 F N 186 | F0 "J" 0 150 50 H V C CNN 187 | F1 "CONN_01X02" 100 0 50 V V C CNN 188 | F2 "" 0 0 50 H I C CNN 189 | F3 "" 0 0 50 H I C CNN 190 | $FPLIST 191 | Pin_Header_Straight_1X* 192 | Pin_Header_Angled_1X* 193 | Socket_Strip_Straight_1X* 194 | Socket_Strip_Angled_1X* 195 | $ENDFPLIST 196 | DRAW 197 | S -50 -45 10 -55 0 1 0 N 198 | S -50 55 10 45 0 1 0 N 199 | S -50 100 50 -100 0 1 0 N 200 | X P1 1 -200 50 150 R 50 50 1 1 P 201 | X P2 2 -200 -50 150 R 50 50 1 1 P 202 | ENDDRAW 203 | ENDDEF 204 | # 205 | # GND 206 | # 207 | DEF GND #PWR 0 0 Y Y 1 F P 208 | F0 "#PWR" 0 -250 50 H I C CNN 209 | F1 "GND" 0 -150 50 H V C CNN 210 | F2 "" 0 0 50 H I C CNN 211 | F3 "" 0 0 50 H I C CNN 212 | DRAW 213 | P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N 214 | X GND 1 0 0 0 D 50 50 1 1 W N 215 | ENDDRAW 216 | ENDDEF 217 | # 218 | # Jumper_Dual 219 | # 220 | DEF Jumper_Dual J 0 40 Y Y 1 F N 221 | F0 "J" 100 -100 60 H V C CNN 222 | F1 "Jumper_Dual" 0 150 60 H V C CNN 223 | F2 "" 0 0 60 H V C CNN 224 | F3 "" 0 0 60 H V C CNN 225 | DRAW 226 | S -100 50 -50 -50 0 1 0 N 227 | S -25 50 25 -50 0 1 0 N 228 | S 50 50 100 -50 0 1 0 N 229 | X ~ 1 -200 0 100 R 50 50 1 1 P 230 | X ~ 2 0 -100 50 U 50 50 1 1 P 231 | X ~ 3 200 0 100 L 50 50 1 1 P 232 | ENDDRAW 233 | ENDDEF 234 | # 235 | # LCD_CAP_TOUCH 236 | # 237 | DEF LCD_CAP_TOUCH U 0 40 Y Y 1 F N 238 | F0 "U" 0 250 60 H V C CNN 239 | F1 "LCD_CAP_TOUCH" 0 -350 60 H V C CNN 240 | F2 "" 0 0 60 H I C CNN 241 | F3 "" 0 0 60 H I C CNN 242 | DRAW 243 | S -300 200 300 -300 0 1 0 N 244 | X GND 1 500 -200 200 L 50 50 1 1 I 245 | X SDA 2 -500 -200 200 R 50 50 1 1 I 246 | X SCL 3 -500 -100 200 R 50 50 1 1 I 247 | X ~RESET 4 -500 0 200 R 50 50 1 1 I 248 | X ~INT 5 -500 100 200 R 50 50 1 1 I 249 | X VDD 6 500 100 200 L 50 50 1 1 I 250 | ENDDRAW 251 | ENDDEF 252 | # 253 | # MCP4661-ML 254 | # 255 | DEF MCP4661-ML U 0 40 Y Y 1 F N 256 | F0 "U" 0 -650 60 H V C CNN 257 | F1 "MCP4661-ML" 0 650 60 H V C CNN 258 | F2 "" 1900 -500 60 H I C CNN 259 | F3 "" 1900 -500 60 H I C CNN 260 | DRAW 261 | S -400 600 400 -600 0 1 0 N 262 | X SCL 1 -600 0 200 R 50 50 1 1 P 263 | X SDA 2 -600 -100 200 R 50 50 1 1 P 264 | X VSS 3 -600 -400 200 R 50 50 1 1 P 265 | X VSS 4 -600 -500 200 R 50 50 1 1 P 266 | X P1B 5 600 -100 200 L 50 50 1 1 P 267 | X P1W 6 600 0 200 L 50 50 1 1 P 268 | X P1A 7 600 100 200 L 50 50 1 1 P 269 | X P0A 8 600 500 200 L 50 50 1 1 P 270 | X P0W 9 600 400 200 L 50 50 1 1 P 271 | X P0B 10 600 300 200 L 50 50 1 1 P 272 | X NC 11 600 -400 200 L 50 50 1 1 P 273 | X ~WP 12 -600 -200 200 R 50 50 1 1 P 274 | X A2 13 -600 300 200 R 50 50 1 1 P 275 | X A1 14 -600 200 200 R 50 50 1 1 P 276 | X VDD 15 -600 500 200 R 50 50 1 1 P 277 | X HVC/A0 16 -600 100 200 R 50 50 1 1 P 278 | X PAD 17 600 -500 200 L 50 50 1 1 P 279 | ENDDRAW 280 | ENDDEF 281 | # 282 | # PAD_SMD 283 | # 284 | DEF PAD_SMD P 0 40 Y N 1 F N 285 | F0 "P" 0 -150 60 H V C CNN 286 | F1 "PAD_SMD" 0 150 60 H V C CNN 287 | F2 "" 0 -250 60 H V C CNN 288 | F3 "" 0 -150 60 H V C CNN 289 | DRAW 290 | S -50 50 50 -50 0 1 0 N 291 | X PAD 1 -200 0 150 R 50 50 1 1 I 292 | ENDDRAW 293 | ENDDEF 294 | # 295 | # PWR_FLAG 296 | # 297 | DEF PWR_FLAG #FLG 0 0 N N 1 F P 298 | F0 "#FLG" 0 75 50 H I C CNN 299 | F1 "PWR_FLAG" 0 150 50 H V C CNN 300 | F2 "" 0 0 50 H I C CNN 301 | F3 "" 0 0 50 H I C CNN 302 | DRAW 303 | X pwr 1 0 0 0 U 50 50 0 0 w 304 | P 6 0 1 0 0 0 0 50 -40 75 0 100 40 75 0 50 N 305 | ENDDRAW 306 | ENDDEF 307 | # 308 | # TACT 309 | # 310 | DEF TACT SW 0 40 N N 1 F N 311 | F0 "SW" 150 -75 60 H V L CNN 312 | F1 "TACT" 150 75 60 H V L CNN 313 | F2 "" 0 -25 60 H V C CNN 314 | F3 "" 0 -25 60 H V C CNN 315 | DRAW 316 | C 0 0 150 0 1 10 N 317 | P 2 0 1 10 -75 200 75 200 N 318 | P 2 0 1 10 0 25 0 50 N 319 | P 2 0 1 10 0 75 0 125 N 320 | P 2 0 1 10 0 150 0 200 N 321 | P 2 0 1 10 100 0 75 0 N 322 | P 3 0 1 10 -100 0 -75 0 75 50 N 323 | X ~ 1 -200 0 100 R 50 50 1 1 P 324 | X ~ 2 200 0 100 L 50 50 1 1 P 325 | ENDDRAW 326 | ENDDEF 327 | # 328 | # TPA6135A2 329 | # 330 | DEF TPA6135A2 U 0 40 Y Y 1 F N 331 | F0 "U" 0 -750 60 H V C CNN 332 | F1 "TPA6135A2" 0 550 60 H V C CNN 333 | F2 "" 1750 -850 60 H I C CNN 334 | F3 "" 1750 -850 60 H I C CNN 335 | DRAW 336 | S -400 500 400 -700 0 0 0 N 337 | X INL- 1 -600 200 200 R 50 50 1 1 P 338 | X INL+ 2 -600 100 200 R 50 50 1 1 P 339 | X INR+ 3 -600 300 200 R 50 50 1 1 P 340 | X INR- 4 -600 400 200 R 50 50 1 1 P 341 | X OUTR 5 600 300 200 L 50 50 1 1 P 342 | X HI-Z 6 -600 -200 200 R 50 50 1 1 P 343 | X GAIN 7 -600 -300 200 R 50 50 1 1 P 344 | X HPVSS 8 -600 -600 200 R 50 50 1 1 P 345 | X CPN 9 600 -300 200 L 50 50 1 1 P 346 | X PGND 10 600 -100 200 L 50 50 1 1 P 347 | X CPP 11 600 -400 200 L 50 50 1 1 P 348 | X HPVDD 12 -600 -500 200 R 50 50 1 1 P 349 | X EN 13 -600 -100 200 R 50 50 1 1 P 350 | X VDD 14 -600 -400 200 R 50 50 1 1 P 351 | X SGND 15 600 0 200 L 50 50 1 1 P 352 | X OUTL 16 600 200 200 L 50 50 1 1 P 353 | X PAD 17 600 -600 200 L 50 50 1 1 P 354 | ENDDRAW 355 | ENDDEF 356 | # 357 | # lcd_50pin_logic 358 | # 359 | DEF lcd_50pin_logic U 0 40 Y Y 1 F N 360 | F0 "U" 0 -1650 60 H V C CNN 361 | F1 "lcd_50pin_logic" 0 1700 60 H V C CNN 362 | F2 "" 0 900 60 H I C CNN 363 | F3 "" 0 900 60 H I C CNN 364 | DRAW 365 | T 900 -100 -1150 60 0 0 0 POWER Normal 0 C C 366 | S 500 -800 50 -1550 0 0 0 N 367 | S 500 -300 50 -800 0 0 0 N 368 | S 500 1550 50 -300 0 0 0 N 369 | P 2 0 0 0 -500 -700 -500 -200 N 370 | P 2 0 0 0 -50 1550 50 1550 N 371 | P 2 0 0 0 50 -1550 -50 -1550 N 372 | T 900 -100 100 60 0 1 0 BACKLIGHT Normal 0 C C 373 | T 900 -100 1350 60 0 1 0 BUS~SEL Normal 0 C C 374 | T 900 100 650 60 0 1 0 DATA~BUS Normal 0 C C 375 | T 900 100 -550 60 0 1 0 RGB Normal 0 C C 376 | T 900 -100 1000 60 0 1 0 RST Normal 0 C C 377 | T 900 100 -1200 60 0 1 0 SERIAL~LOGIC Normal 0 C C 378 | T 900 -100 650 60 0 1 0 TOUCH Normal 0 C C 379 | S -700 900 -50 400 0 1 0 N 380 | S -500 -700 -50 -1550 0 1 0 N 381 | S -500 400 -50 -200 0 1 0 N 382 | S -500 1100 -50 900 0 1 0 N 383 | S -500 1550 -50 1100 0 1 0 N 384 | X LEDK 1 -700 300 200 R 50 50 1 1 P 385 | X LEDA 2 -700 200 200 R 50 50 1 1 P 386 | X LEDA 3 -700 100 200 R 50 50 1 1 P 387 | X LEDA 4 -700 0 200 R 50 50 1 1 P 388 | X LEDA 5 -700 -100 200 R 50 50 1 1 P 389 | X IM0 6 -700 1500 200 R 50 50 1 1 P 390 | X IM1 7 -700 1400 200 R 50 50 1 1 P 391 | X IM2 8 -700 1300 200 R 50 50 1 1 P 392 | X IM3 9 -700 1200 200 R 50 50 1 1 P 393 | X ~RESET 10 -700 1000 200 R 50 50 1 1 P 394 | X DB12 20 700 300 200 L 50 50 1 1 P 395 | X DB2 30 700 1300 200 L 50 50 1 1 P 396 | X IOVCC 40 -700 -800 200 R 50 50 1 1 P 397 | X GND 50 -700 -1500 200 R 50 50 1 1 P 398 | X VSYNC 11 700 -700 200 L 50 50 1 1 P 399 | X DB11 21 700 400 200 L 50 50 1 1 P 400 | X DB1 31 700 1400 200 L 50 50 1 1 P 401 | X IOVCC 41 -700 -900 200 R 50 50 1 1 P 402 | X HSYNC 12 700 -600 200 L 50 50 1 1 P 403 | X DB10 22 700 500 200 L 50 50 1 1 P 404 | X DB0 32 700 1500 200 L 50 50 1 1 P 405 | X VCI 42 -700 -1000 200 R 50 50 1 1 P 406 | X DOTCLK 13 700 -500 200 L 50 50 1 1 P 407 | X DB9 23 700 600 200 L 50 50 1 1 P 408 | X SDO 33 700 -1500 200 L 50 50 1 1 P 409 | X GND 43 -700 -1200 200 R 50 50 1 1 P 410 | X DE 14 700 -400 200 L 50 50 1 1 P 411 | X DB8 24 700 700 200 L 50 50 1 1 P 412 | X SDI 34 700 -1400 200 L 50 50 1 1 P 413 | X X+(XR)/SCK 44 -900 800 200 R 50 50 1 1 P 414 | X DB17 15 700 -200 200 L 50 50 1 1 P 415 | X DB7 25 700 800 200 L 50 50 1 1 P 416 | X ~RD 35 700 -1300 200 L 50 50 1 1 P 417 | X Y+(YD)/SDA 45 -900 700 200 R 50 50 1 1 P 418 | X DB16 16 700 -100 200 L 50 50 1 1 P 419 | X DB6 26 700 900 200 L 50 50 1 1 P 420 | X ~WR_RS 36 700 -1200 200 L 50 50 1 1 P 421 | X X-(XL)/IRQ 46 -900 600 200 R 50 50 1 1 P 422 | X DB15 17 700 0 200 L 50 50 1 1 P 423 | X DB5 27 700 1000 200 L 50 50 1 1 P 424 | X RS_SCL 37 700 -1100 200 L 50 50 1 1 P 425 | X Y-(YU)/RES 47 -900 500 200 R 50 50 1 1 P 426 | X DB14 18 700 100 200 L 50 50 1 1 P 427 | X DB4 28 700 1100 200 L 50 50 1 1 P 428 | X ~CS 38 700 -1000 200 L 50 50 1 1 P 429 | X GND 48 -700 -1300 200 R 50 50 1 1 P 430 | X DB13 19 700 200 200 L 50 50 1 1 P 431 | X DB3 29 700 1200 200 L 50 50 1 1 P 432 | X TE 39 700 -900 200 L 50 50 1 1 P 433 | X GND 49 -700 -1400 200 R 50 50 1 1 P 434 | ENDDRAW 435 | ENDDEF 436 | # 437 | # pkl_C 438 | # 439 | DEF pkl_C C 0 10 N Y 1 F N 440 | F0 "C" 25 100 50 H V L CNN 441 | F1 "pkl_C" 25 -100 50 H V L CNN 442 | F2 "" 38 -150 30 H V C CNN 443 | F3 "" 0 0 60 H V C CNN 444 | $FPLIST 445 | C? 446 | C_????_* 447 | C_???? 448 | SMD*_c 449 | Capacitor* 450 | $ENDFPLIST 451 | DRAW 452 | P 2 0 1 20 -80 -30 80 -30 N 453 | P 2 0 1 20 -80 30 80 30 N 454 | X ~ 1 0 100 60 D 40 40 1 1 P 455 | X ~ 2 0 -100 60 U 40 40 1 1 P 456 | ENDDRAW 457 | ENDDEF 458 | # 459 | # pkl_C_Small 460 | # 461 | DEF pkl_C_Small C 0 10 N N 1 F N 462 | F0 "C" 10 70 50 H V L CNN 463 | F1 "pkl_C_Small" 10 -80 50 H V L CNN 464 | F2 "" 0 0 60 H V C CNN 465 | F3 "" 0 0 60 H V C CNN 466 | $FPLIST 467 | C? 468 | C_????_* 469 | C_???? 470 | SMD*_c 471 | Capacitor* 472 | $ENDFPLIST 473 | DRAW 474 | P 2 0 1 13 -60 -20 60 -20 N 475 | P 2 0 1 12 -60 20 60 20 N 476 | X ~ 1 0 100 75 D 40 40 1 1 P 477 | X ~ 2 0 -100 80 U 40 40 1 1 P 478 | ENDDRAW 479 | ENDDEF 480 | # 481 | # pkl_JACK_3C1S 482 | # 483 | DEF pkl_JACK_3C1S J 0 40 Y Y 1 F N 484 | F0 "J" -350 -300 50 H V C CNN 485 | F1 "pkl_JACK_3C1S" -150 350 50 H V C CNN 486 | F2 "" 0 0 50 H I C CNN 487 | F3 "" 0 0 50 H I C CNN 488 | DRAW 489 | S -450 200 -400 -100 0 1 0 F 490 | S -325 175 -275 -75 0 1 10 F 491 | S 300 -150 -400 250 0 1 10 N 492 | P 3 0 1 0 150 0 300 0 300 0 N 493 | P 3 0 1 10 300 200 -300 200 -300 175 N 494 | P 4 0 1 0 0 -100 -50 -50 -100 -100 -100 -100 N 495 | P 4 0 1 0 0 -100 300 -100 300 -100 300 -100 N 496 | P 4 0 1 0 50 -50 100 -100 150 -50 150 -50 N 497 | P 4 0 1 0 150 0 100 0 100 -100 100 -100 N 498 | P 4 0 1 10 300 100 -100 100 -150 50 -200 100 N 499 | X ~ 1 450 200 150 L 50 50 1 1 P 500 | X ~ 2 450 -100 150 L 50 50 1 1 P 501 | X ~ 3 450 100 150 L 50 50 1 1 P 502 | X ~ 4 450 0 150 L 50 50 1 1 P 503 | ENDDRAW 504 | ENDDEF 505 | # 506 | # pkl_LED 507 | # 508 | DEF pkl_LED D 0 40 Y N 1 F N 509 | F0 "D" 0 100 50 H V C CNN 510 | F1 "pkl_LED" 0 -100 50 H V C CNN 511 | F2 "" 0 0 60 H V C CNN 512 | F3 "" 0 0 60 H V C CNN 513 | $FPLIST 514 | LED-3MM 515 | LED-5MM 516 | LED-10MM 517 | LED-0603 518 | LED-0805 519 | LED-1206 520 | LEDV 521 | $ENDFPLIST 522 | DRAW 523 | P 2 0 1 0 50 50 50 -50 N 524 | P 3 0 1 0 -50 50 50 0 -50 -50 F 525 | P 3 0 1 0 65 -40 110 -80 105 -55 N 526 | P 3 0 1 0 80 -25 125 -65 120 -40 N 527 | X A A -200 0 150 R 40 40 1 1 P 528 | X C C 200 0 150 L 40 40 1 1 P 529 | ENDDRAW 530 | ENDDEF 531 | # 532 | # pkl_Micro_SD 533 | # 534 | DEF pkl_Micro_SD CON 0 40 Y Y 1 F N 535 | F0 "CON" -650 550 50 H V C CNN 536 | F1 "pkl_Micro_SD" 600 -550 50 H V C CNN 537 | F2 "" 150 300 50 H V C CNN 538 | F3 "" 0 0 60 H V C CNN 539 | $FPLIST 540 | Micro_SD_Card_Receptacle 541 | $ENDFPLIST 542 | DRAW 543 | S -350 -375 -250 -425 0 1 0 F 544 | S -350 -275 -250 -325 0 1 0 F 545 | S -350 -175 -250 -225 0 1 0 F 546 | S -350 -75 -250 -125 0 1 0 F 547 | S -350 25 -250 -25 0 1 0 F 548 | S -350 125 -250 75 0 1 0 F 549 | S -350 225 -250 175 0 1 0 F 550 | S -350 325 -250 275 0 1 0 F 551 | P 6 0 1 0 650 450 650 500 -800 500 -800 -500 650 -500 650 -450 N 552 | P 11 0 1 0 -400 350 -100 350 0 450 150 450 150 400 250 400 300 450 800 450 800 -450 -400 -450 -400 350 f 553 | X DAT2 1 -900 300 100 R 50 50 1 1 I 554 | X CD/DAT3 2 -900 200 100 R 50 50 1 1 I 555 | X CMD 3 -900 100 100 R 50 50 1 1 I 556 | X VDD 4 -900 0 100 R 50 50 1 1 I 557 | X CLK 5 -900 -100 100 R 50 50 1 1 I 558 | X VSS 6 -900 -200 100 R 50 50 1 1 I 559 | X DAT0 7 -900 -300 100 R 50 50 1 1 I 560 | X DAT1 8 -900 -400 100 R 50 50 1 1 I 561 | X CARD_DETECT 9 900 200 100 L 50 50 1 1 I 562 | X CARD_DETECT_GND 10 900 100 100 L 50 50 1 1 I 563 | X SHELL 11 900 -200 100 L 50 50 1 1 I 564 | ENDDRAW 565 | ENDDEF 566 | # 567 | # pkl_Q_NMOS_BD_GSD 568 | # 569 | DEF pkl_Q_NMOS_BD_GSD Q 0 0 Y N 1 F N 570 | F0 "Q" 200 50 50 H V L CNN 571 | F1 "pkl_Q_NMOS_BD_GSD" 200 -50 50 H V L CNN 572 | F2 "" 200 100 29 H V C CNN 573 | F3 "" 0 0 60 H V C CNN 574 | $FPLIST 575 | LFPAK* 576 | SO* 577 | SOT669* 578 | $ENDFPLIST 579 | DRAW 580 | C 50 0 111 0 1 10 N 581 | C 100 -70 4 0 1 0 N 582 | C 100 70 4 0 1 0 N 583 | P 2 0 1 0 30 -70 100 -70 N 584 | P 2 0 1 10 30 -50 30 -90 N 585 | P 2 0 1 0 30 0 100 0 N 586 | P 2 0 1 10 30 20 30 -20 N 587 | P 2 0 1 0 30 70 100 70 N 588 | P 2 0 1 10 30 90 30 50 N 589 | P 2 0 1 0 100 -70 100 -100 N 590 | P 2 0 1 0 100 -70 100 0 N 591 | P 2 0 1 0 100 100 100 70 N 592 | P 2 0 1 0 108 12 132 12 N 593 | P 3 0 1 10 10 75 10 -75 10 -75 N 594 | P 4 0 1 0 40 0 80 15 80 -15 40 0 F 595 | P 4 0 1 0 100 -70 120 -70 120 70 100 70 N 596 | P 4 0 1 0 110 -16 130 -16 120 14 110 -16 F 597 | X G 1 -200 0 210 R 50 50 1 1 I 598 | X S 2 100 -200 100 U 50 50 1 1 E 599 | X D 3 100 200 100 D 50 50 1 1 C 600 | ENDDRAW 601 | ENDDEF 602 | # 603 | # pkl_R4_Small 604 | # 605 | DEF pkl_R4_Small R 0 10 N N 4 F N 606 | F0 "R" 30 20 50 H V L CNN 607 | F1 "pkl_R4_Small" 30 -40 50 H V L CNN 608 | F2 "" 0 0 60 H V C CNN 609 | F3 "" 0 0 60 H V C CNN 610 | $FPLIST 611 | Resistor_* 612 | R_* 613 | $ENDFPLIST 614 | DRAW 615 | S -30 70 30 -70 0 1 8 N 616 | X ~ 1 0 100 30 D 40 40 1 1 P 617 | X ~ 2 0 -100 30 U 40 40 1 1 P 618 | X ~ 3 0 100 30 D 40 40 2 1 P 619 | X ~ 4 0 -100 30 U 40 40 2 1 P 620 | X ~ 5 0 100 30 D 40 40 3 1 P 621 | X ~ 6 0 -100 30 U 40 40 3 1 P 622 | X ~ 7 0 100 30 D 40 40 4 1 P 623 | X ~ 8 0 -100 30 U 40 40 4 1 P 624 | ENDDRAW 625 | ENDDEF 626 | # 627 | # pkl_R_Small 628 | # 629 | DEF pkl_R_Small R 0 10 N N 1 F N 630 | F0 "R" 30 20 50 H V L CNN 631 | F1 "pkl_R_Small" 30 -40 50 H V L CNN 632 | F2 "" 0 0 60 H V C CNN 633 | F3 "" 0 0 60 H V C CNN 634 | $FPLIST 635 | Resistor_* 636 | R_* 637 | $ENDFPLIST 638 | DRAW 639 | S -30 70 30 -70 0 1 8 N 640 | X ~ 1 0 100 30 D 40 40 1 1 P 641 | X ~ 2 0 -100 30 U 40 40 1 1 P 642 | ENDDRAW 643 | ENDDEF 644 | # 645 | # pkl_SWITCH-SPDT 646 | # 647 | DEF pkl_SWITCH-SPDT SW 0 40 N N 1 F N 648 | F0 "SW" 150 -75 60 H V L CNN 649 | F1 "pkl_SWITCH-SPDT" 150 75 60 H V L CNN 650 | F2 "" 0 -25 60 H V C CNN 651 | F3 "" 0 -25 60 H V C CNN 652 | DRAW 653 | C -100 0 10 0 0 0 N 654 | C 0 -100 10 0 0 0 N 655 | C 0 100 10 0 0 0 N 656 | P 2 0 0 0 -100 0 0 75 N 657 | C 0 0 150 0 1 10 N 658 | X ~ 1 0 200 100 D 50 50 1 1 P 659 | X ~ 2 -200 0 100 R 50 50 1 1 P 660 | X ~ 3 0 -200 100 U 50 50 1 1 P 661 | ENDDRAW 662 | ENDDEF 663 | # 664 | # pkl_jumper 665 | # 666 | DEF pkl_jumper J 0 40 Y Y 1 F N 667 | F0 "J" 100 -100 60 H V C CNN 668 | F1 "pkl_jumper" 0 150 60 H V C CNN 669 | F2 "" 0 0 60 H V C CNN 670 | F3 "" 0 0 60 H V C CNN 671 | DRAW 672 | S -50 30 -10 -30 0 1 0 N 673 | S 10 30 50 -30 0 1 0 N 674 | X ~ 1 -100 0 50 R 50 50 1 1 P 675 | X ~ 2 100 0 50 L 50 50 1 1 P 676 | ENDDRAW 677 | ENDDEF 678 | # 679 | #End Library 680 | -------------------------------------------------------------------------------- /hardware/V0.1/1bitsy-1up.pro: -------------------------------------------------------------------------------- 1 | update=Fri 23 Jun 2017 02:45:08 PM PDT 2 | version=1 3 | last_client=kicad 4 | [pcbnew] 5 | version=1 6 | LastNetListRead= 7 | UseCmpFile=1 8 | PadDrill=0.600000000000 9 | PadDrillOvalY=0.600000000000 10 | PadSizeH=1.500000000000 11 | PadSizeV=1.500000000000 12 | PcbTextSizeV=1.500000000000 13 | PcbTextSizeH=1.500000000000 14 | PcbTextThickness=0.300000000000 15 | ModuleTextSizeV=1.000000000000 16 | ModuleTextSizeH=1.000000000000 17 | ModuleTextSizeThickness=0.150000000000 18 | SolderMaskClearance=0.000000000000 19 | SolderMaskMinWidth=0.000000000000 20 | DrawSegmentWidth=0.200000000000 21 | BoardOutlineThickness=0.100000000000 22 | ModuleOutlineThickness=0.150000000000 23 | [cvpcb] 24 | version=1 25 | NetIExt=net 26 | [general] 27 | version=1 28 | [eeschema] 29 | version=1 30 | LibDir=../lib/pkl;../lib/1bitsy/kicad 31 | [eeschema/libraries] 32 | LibName1=power 33 | LibName2=device 34 | LibName3=transistors 35 | LibName4=conn 36 | LibName5=linear 37 | LibName6=regul 38 | LibName7=74xx 39 | LibName8=cmos4000 40 | LibName9=adc-dac 41 | LibName10=memory 42 | LibName11=xilinx 43 | LibName12=microcontrollers 44 | LibName13=dsp 45 | LibName14=microchip 46 | LibName15=analog_switches 47 | LibName16=motorola 48 | LibName17=texas 49 | LibName18=intel 50 | LibName19=audio 51 | LibName20=interface 52 | LibName21=digital-audio 53 | LibName22=philips 54 | LibName23=display 55 | LibName24=cypress 56 | LibName25=siliconi 57 | LibName26=opto 58 | LibName27=atmel 59 | LibName28=contrib 60 | LibName29=valves 61 | LibName30=pkl_conn 62 | LibName31=pkl_device 63 | LibName32=pkl_ftdi 64 | LibName33=pkl_linear 65 | LibName34=pkl_logos 66 | LibName35=pkl_maxim 67 | LibName36=pkl_misc 68 | LibName37=pkl_molex 69 | LibName38=pkl_power 70 | LibName39=pkl_sensor 71 | LibName40=pkl_tag_connect 72 | LibName41=pkl_texas 73 | LibName42=1bitsy 74 | LibName43=pkl_lattice 75 | LibName44=pkl_memory 76 | [schematic_editor] 77 | version=1 78 | PageLayoutDescrFile= 79 | PlotDirectoryName= 80 | SubpartIdSeparator=0 81 | SubpartFirstId=65 82 | NetFmtName= 83 | SpiceForceRefPrefix=0 84 | SpiceUseNetNumbers=0 85 | LabSize=60 86 | -------------------------------------------------------------------------------- /hardware/contrib/1up-mini/1up-mini-cache.lib: -------------------------------------------------------------------------------- 1 | EESchema-LIBRARY Version 2.3 2 | #encoding utf-8 3 | # 4 | # +3V3 5 | # 6 | DEF +3V3 #PWR 0 0 Y Y 1 F P 7 | F0 "#PWR" 0 -150 50 H I C CNN 8 | F1 "+3V3" 0 140 50 H V C CNN 9 | F2 "" 0 0 50 H V C CNN 10 | F3 "" 0 0 50 H V C CNN 11 | ALIAS +3.3V 12 | DRAW 13 | P 2 0 1 0 -30 50 0 100 N 14 | P 2 0 1 0 0 0 0 100 N 15 | P 2 0 1 0 0 100 30 50 N 16 | X +3V3 1 0 0 0 U 50 50 1 1 W N 17 | ENDDRAW 18 | ENDDEF 19 | # 20 | # +5V 21 | # 22 | DEF +5V #PWR 0 0 Y Y 1 F P 23 | F0 "#PWR" 0 -150 50 H I C CNN 24 | F1 "+5V" 0 140 50 H V C CNN 25 | F2 "" 0 0 50 H V C CNN 26 | F3 "" 0 0 50 H V C CNN 27 | DRAW 28 | P 2 0 1 0 -30 50 0 100 N 29 | P 2 0 1 0 0 0 0 100 N 30 | P 2 0 1 0 0 100 30 50 N 31 | X +5V 1 0 0 0 U 50 50 1 1 W N 32 | ENDDRAW 33 | ENDDEF 34 | # 35 | # +BATT 36 | # 37 | DEF +BATT #PWR 0 0 Y Y 1 F P 38 | F0 "#PWR" 0 -150 50 H I C CNN 39 | F1 "+BATT" 0 140 50 H V C CNN 40 | F2 "" 0 0 50 H V C CNN 41 | F3 "" 0 0 50 H V C CNN 42 | DRAW 43 | P 2 0 1 0 -30 50 0 100 N 44 | P 2 0 1 0 0 0 0 100 N 45 | P 2 0 1 0 0 100 30 50 N 46 | X +BATT 1 0 0 0 U 50 50 1 1 W N 47 | ENDDRAW 48 | ENDDEF 49 | # 50 | # 1bitsy-complete-concise 51 | # 52 | DEF 1bitsy-complete-concise U 0 40 Y Y 1 F N 53 | F0 "U" 0 100 60 H V C CNN 54 | F1 "1bitsy-complete-concise" 0 0 60 H V C CNN 55 | F2 "" 0 100 60 H I C CNN 56 | F3 "" 0 100 60 H I C CNN 57 | DRAW 58 | S -2400 1300 2400 -1300 0 1 0 N 59 | X GND 1 -2600 1200 200 R 50 50 1 1 P 60 | X PC10/SPI3SCK/I2S3CK/USART3&4_TX/SDIOD2 2 -2600 1100 200 R 50 50 1 1 P 61 | X PC11/ADCEXTI11/I2S3EXTSD/SPI3MISO/USART3&4_RX/SDIOD3 3 -2600 1000 200 R 50 50 1 1 P 62 | X PC12/SPI3MOSI/I2S3SD/USART3CK/UART5TX/SDIOCK 4 -2600 900 200 R 50 50 1 1 P 63 | X PD2/T2ETR/UART5RX/SDIOCMD 5 -2600 800 200 R 50 50 1 1 P 64 | X PB4/~JTRST~/T3C1/SPI1&3_MISO/I2S3EXTSD 6 -2600 700 200 R 50 50 1 1 P 65 | X PB5/T3C2/I2C1SMBA/SPI1&3_MOSI/I2S3SD/CAN2RX/ULPID7 7 -2600 600 200 R 50 50 1 1 P 66 | X PB6/T4C1/I2C1SCL/USART1TX/CAN2TX 8 -2600 500 200 R 50 50 1 1 P 67 | X PB7/T4C2/I2C1SDA/USART1RX 9 -2600 400 200 R 50 50 1 1 P 68 | X PB8/T4C3/TI0C1/I2C1SCL/CAN2RX/SDIOD4 10 -2600 300 200 R 50 50 1 1 P 69 | X PB11/T2C4/I2C2SDA/USART3RX/ULPID4 20 2600 200 200 L 50 50 1 1 P 70 | X VIN 30 2600 1200 200 L 50 50 1 1 P 71 | X PC5/ADC15 40 2600 -400 200 L 50 50 1 1 P 72 | X PB9/T4C4/T1C1/I2C1SDA/SPI2NSS/I2S2WS/CAN2TX/SDIOD5 11 -2600 200 200 R 50 50 1 1 P 73 | X PB12/T1BK/I2C2SMBA/SPI2NSS/I2S2WS/USART3CK/CAN2RX/ULPID5/HSID 21 2600 300 200 L 50 50 1 1 P 74 | X PA0-WKUP/ADC0/T2C1ETR/T5C1/T8ETR/USART2CTS/UART4TX 31 -2600 -400 200 R 50 50 1 1 P 75 | X LED|PA8-MCO1/T1C1/I2C3SCL/USART1CK/OTGFSSOF 41 -2600 -1000 200 R 50 50 1 1 P 76 | X PC2/ADC12/SPI2MISO/I2S2EXTSD/ULPIDIR 12 -2600 100 200 R 50 50 1 1 P 77 | X PB13/T1C1N/SPI2SCK/12S2CK/USART3CTS/CAN2TX/ULPID6 22 2600 400 200 L 50 50 1 1 P 78 | X PA1/ADC1/T2C2/T5C2/USART2RTS/UART4RX 32 -2600 -500 200 R 50 50 1 1 P 79 | X PC13 42 -2600 -1100 200 R 50 50 1 1 P 80 | X PC3/ADC13/SPI2MOSI/I2S2SD/ULPINXT 13 -2600 0 200 R 50 50 1 1 P 81 | X PB14/T1&8C2N/SPI2MISO/I2S2EXTSD/USART3RTS/T12C1/HSDM 23 2600 500 200 L 50 50 1 1 P 82 | X PA2/ADC2/T2C3/T5C3/T9C1/USART2TX 33 -2600 -600 200 R 50 50 1 1 P 83 | X PC0/ADC10/ULPISTP 43 -2600 -1200 200 R 50 50 1 1 P 84 | X VBAT 14 -2600 -100 200 R 50 50 1 1 P 85 | X PB15/T1&8C3N/SPI2MOSI/I2S2SD/T12C2/HSDP 24 2600 600 200 L 50 50 1 1 P 86 | X PA3/ADC3/T2C4/T5C4/T9C2/USART2RX/ULPID0 34 -2600 -700 200 R 50 50 1 1 P 87 | X PB2 44 2600 -1000 200 L 50 50 1 1 P 88 | X +3V3 15 -2600 -200 200 R 50 50 1 1 P 89 | X PC6/T3&8C1/I2S2MCK/USART6TX/SDIOD6 25 2600 700 200 L 50 50 1 1 P 90 | X PA4/ADC4/DAC1/SPI1NSS/SPI3NSS/I2S3WS/USART2CK 35 -2600 -800 200 R 50 50 1 1 P 91 | X GND 16 2600 -200 200 L 50 50 1 1 P 92 | X PC7/T3&8C2/I2S3MCK/USART6RX/SDIOD7 26 2600 800 200 L 50 50 1 1 P 93 | X PA5/ADC5/DAC2/T2C1ETR/T8C1N/SPI1SCK/ULPICK 36 2600 -800 200 L 50 50 1 1 P 94 | X PB0/ADC8/T1C2N/T3C3/T8C2N/ULPID1 17 2600 -100 200 L 50 50 1 1 P 95 | X PC8/T3&8C3/USART6CK/SDIOD0 27 2600 900 200 L 50 50 1 1 P 96 | X PA6/ADC6/T1BK/T3C1/T8BK/SPI1MISO/T13C1 37 2600 -700 200 L 50 50 1 1 P 97 | X PB1/ADC9/T1C3N/T3C4/T8C3N 18 2600 0 200 L 50 50 1 1 P 98 | X PC9-MCO2/DACEXTI9/T3&8C4/I2C3SDA/I2S2CHIN/SDIOD1 28 2600 1000 200 L 50 50 1 1 P 99 | X PA7/ADC7/T1C1N/T3C2/T8C1N/SPI1MOSI/T12C2 38 2600 -600 200 L 50 50 1 1 P 100 | X PB10/T2C3/I2C2SCL/SPI2SCK/I2S2CK/USART3TX/ULPID3 19 2600 100 200 L 50 50 1 1 P 101 | X +3V3 29 2600 1100 200 L 50 50 1 1 P 102 | X PC4/ADC14 39 2600 -500 200 L 50 50 1 1 P 103 | ENDDRAW 104 | ENDDEF 105 | # 106 | # 74HC165 107 | # 108 | DEF 74HC165 U 0 40 Y Y 1 F N 109 | F0 "U" 0 -800 60 H V C CNN 110 | F1 "74HC165" 0 750 60 H V C CNN 111 | F2 "" 2190 -1220 60 H I C CNN 112 | F3 "" 2190 -1220 60 H I C CNN 113 | DRAW 114 | S -400 700 400 -700 0 1 0 N 115 | X SH/~LD 1 -600 -600 200 R 50 50 1 1 P 116 | X CLK 2 -600 -400 200 R 50 50 1 1 P 117 | X D4 3 -600 100 200 R 50 50 1 1 P 118 | X D5 4 -600 0 200 R 50 50 1 1 P 119 | X D6 5 -600 -100 200 R 50 50 1 1 P 120 | X D7 6 -600 -200 200 R 50 50 1 1 P 121 | X ~QH 7 600 -400 200 L 50 50 1 1 P 122 | X GND 8 600 -650 200 L 50 50 1 1 P 123 | X QH 9 600 -200 200 L 50 50 1 1 P 124 | X SER 10 -600 600 200 R 50 50 1 1 P 125 | X D0 11 -600 500 200 R 50 50 1 1 P 126 | X D1 12 -600 400 200 R 50 50 1 1 P 127 | X D2 13 -600 300 200 R 50 50 1 1 P 128 | X D3 14 -600 200 200 R 50 50 1 1 P 129 | X CLK_INH 15 -600 -500 200 R 50 50 1 1 P 130 | X VCC 16 600 650 200 L 50 50 1 1 P 131 | ENDDRAW 132 | ENDDEF 133 | # 134 | # BQ21040 135 | # 136 | DEF BQ21040 U 0 40 Y Y 1 F N 137 | F0 "U" 0 -300 60 H V C CNN 138 | F1 "BQ21040" 0 300 60 H V C CNN 139 | F2 "" 2150 -1050 60 H I C CNN 140 | F3 "" 2150 -1050 60 H I C CNN 141 | F4 "ANY" 0 0 60 H I C CNN "Source" 142 | DRAW 143 | S -400 250 400 -250 0 0 0 N 144 | X TS 1 -600 50 200 R 50 50 1 1 P 145 | X OUT 2 600 150 200 L 50 50 1 1 P 146 | X ~CHG 3 600 -150 200 L 50 50 1 1 P 147 | X ISET 4 -600 -50 200 R 50 50 1 1 P 148 | X GND 5 -600 -150 200 R 50 50 1 1 P 149 | X VIN 6 -600 150 200 R 50 50 1 1 P 150 | ENDDRAW 151 | ENDDEF 152 | # 153 | # CONN_01X01 154 | # 155 | DEF CONN_01X01 P 0 40 Y N 1 F N 156 | F0 "P" 0 100 50 H V C CNN 157 | F1 "CONN_01X01" 100 0 50 V V C CNN 158 | F2 "" 0 0 50 H V C CNN 159 | F3 "" 0 0 50 H V C CNN 160 | $FPLIST 161 | Pin_Header_Straight_1X01 162 | Pin_Header_Angled_1X01 163 | Socket_Strip_Straight_1X01 164 | Socket_Strip_Angled_1X01 165 | $ENDFPLIST 166 | DRAW 167 | S -50 5 10 -5 0 1 0 N 168 | S -50 50 50 -50 0 1 0 N 169 | X P1 1 -200 0 150 R 50 50 1 1 P 170 | ENDDRAW 171 | ENDDEF 172 | # 173 | # GND 174 | # 175 | DEF GND #PWR 0 0 Y Y 1 F P 176 | F0 "#PWR" 0 -250 50 H I C CNN 177 | F1 "GND" 0 -150 50 H V C CNN 178 | F2 "" 0 0 50 H V C CNN 179 | F3 "" 0 0 50 H V C CNN 180 | DRAW 181 | P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N 182 | X GND 1 0 0 0 D 50 50 1 1 W N 183 | ENDDRAW 184 | ENDDEF 185 | # 186 | # LCD_CAP_TOUCH 187 | # 188 | DEF LCD_CAP_TOUCH U 0 40 Y Y 1 F N 189 | F0 "U" 0 250 60 H V C CNN 190 | F1 "LCD_CAP_TOUCH" 0 -350 60 H V C CNN 191 | F2 "" 0 0 60 H I C CNN 192 | F3 "" 0 0 60 H I C CNN 193 | DRAW 194 | S -300 200 300 -300 0 1 0 N 195 | X GND 1 500 -200 200 L 50 50 1 1 I 196 | X SDA 2 -500 -200 200 R 50 50 1 1 I 197 | X SCL 3 -500 -100 200 R 50 50 1 1 I 198 | X ~RESET 4 -500 0 200 R 50 50 1 1 I 199 | X ~INT 5 -500 100 200 R 50 50 1 1 I 200 | X VDD 6 500 100 200 L 50 50 1 1 I 201 | ENDDRAW 202 | ENDDEF 203 | # 204 | # MCP4661-ST 205 | # 206 | DEF MCP4661-ST U 0 40 Y Y 1 F N 207 | F0 "U" 0 -550 60 H V C CNN 208 | F1 "MCP4661-ST" 0 650 60 H V C CNN 209 | F2 "" 1900 -500 60 H I C CNN 210 | F3 "" 1900 -500 60 H I C CNN 211 | DRAW 212 | S -400 600 400 -500 0 1 0 N 213 | X HVC/A0 1 -600 100 200 R 50 50 1 1 P 214 | X SCL 2 -600 0 200 R 50 50 1 1 P 215 | X SDA 3 -600 -100 200 R 50 50 1 1 P 216 | X VSS 4 -600 -400 200 R 50 50 1 1 P 217 | X P1B 5 600 -100 200 L 50 50 1 1 P 218 | X P1W 6 600 0 200 L 50 50 1 1 P 219 | X P1A 7 600 100 200 L 50 50 1 1 P 220 | X P0A 8 600 500 200 L 50 50 1 1 P 221 | X P0W 9 600 400 200 L 50 50 1 1 P 222 | X P0B 10 600 300 200 L 50 50 1 1 P 223 | X ~WP 11 -600 -200 200 R 50 50 1 1 P 224 | X A2 12 -600 300 200 R 50 50 1 1 P 225 | X A1 13 -600 200 200 R 50 50 1 1 P 226 | X VDD 14 -600 500 200 R 50 50 1 1 P 227 | ENDDRAW 228 | ENDDEF 229 | # 230 | # PAD_SMD 231 | # 232 | DEF PAD_SMD P 0 40 Y N 1 F N 233 | F0 "P" 0 -150 60 H V C CNN 234 | F1 "PAD_SMD" 0 150 60 H V C CNN 235 | F2 "" 0 -250 60 H V C CNN 236 | F3 "" 0 -150 60 H V C CNN 237 | DRAW 238 | S -50 50 50 -50 0 1 0 N 239 | X PAD 1 -200 0 150 R 50 50 1 1 I 240 | ENDDRAW 241 | ENDDEF 242 | # 243 | # PWR_FLAG 244 | # 245 | DEF PWR_FLAG #FLG 0 0 N N 1 F P 246 | F0 "#FLG" 0 95 50 H I C CNN 247 | F1 "PWR_FLAG" 0 180 50 H V C CNN 248 | F2 "" 0 0 50 H V C CNN 249 | F3 "" 0 0 50 H V C CNN 250 | DRAW 251 | X pwr 1 0 0 0 U 50 50 0 0 w 252 | P 6 0 1 0 0 0 0 50 -75 100 0 150 75 100 0 50 N 253 | ENDDRAW 254 | ENDDEF 255 | # 256 | # TACT 257 | # 258 | DEF TACT SW 0 40 N N 1 F N 259 | F0 "SW" 150 -75 60 H V L CNN 260 | F1 "TACT" 150 75 60 H V L CNN 261 | F2 "" 0 -25 60 H V C CNN 262 | F3 "" 0 -25 60 H V C CNN 263 | DRAW 264 | C 0 0 150 0 1 10 N 265 | P 2 0 1 10 -75 200 75 200 N 266 | P 2 0 1 10 0 25 0 50 N 267 | P 2 0 1 10 0 75 0 125 N 268 | P 2 0 1 10 0 150 0 200 N 269 | P 2 0 1 10 100 0 75 0 N 270 | P 3 0 1 10 -100 0 -75 0 75 50 N 271 | X ~ 1 -200 0 100 R 50 50 1 1 P 272 | X ~ 2 200 0 100 L 50 50 1 1 P 273 | ENDDRAW 274 | ENDDEF 275 | # 276 | # TPA6139A2-PW 277 | # 278 | DEF TPA6139A2-PW U 0 40 Y Y 1 F N 279 | F0 "U" 0 -650 60 H V C CNN 280 | F1 "TPA6139A2-PW" 0 550 60 H V C CNN 281 | F2 "" 1750 -850 60 H I C CNN 282 | F3 "" 1750 -850 60 H I C CNN 283 | $FPLIST 284 | TSSOP-14 285 | $ENDFPLIST 286 | DRAW 287 | S -400 500 400 -600 0 0 0 N 288 | X INL- 1 -600 300 200 R 50 50 1 1 P 289 | X OUTL 2 600 300 200 L 50 50 1 1 P 290 | X GND 3 -600 -400 200 R 50 50 1 1 P 291 | X MUTE 4 -600 100 200 R 50 50 1 1 P 292 | X VSS 5 600 -500 200 L 50 50 1 1 P 293 | X CN 6 600 -200 200 L 50 50 1 1 P 294 | X NC 7 600 0 200 L 50 50 1 1 N 295 | X NC 8 600 100 200 L 50 50 1 1 N 296 | X CP 9 600 -300 200 L 50 50 1 1 P 297 | X VDD 10 -600 -200 200 R 50 50 1 1 P 298 | X GND 11 -600 -500 200 R 50 50 1 1 P 299 | X GAIN 12 -600 0 200 R 50 50 1 1 P 300 | X OUTR 13 600 400 200 L 50 50 1 1 P 301 | X INR- 14 -600 400 200 R 50 50 1 1 P 302 | ENDDRAW 303 | ENDDEF 304 | # 305 | # TPS2111A 306 | # 307 | DEF TPS2111A U 0 40 Y Y 1 F N 308 | F0 "U" 0 -550 60 H V C CNN 309 | F1 "TPS2111A" 0 550 60 H V C CNN 310 | F2 "" 2150 -1050 60 H I C CNN 311 | F3 "" 2150 -1050 60 H I C CNN 312 | F4 "ANY" 0 0 60 H I C CNN "Source" 313 | DRAW 314 | S -400 500 400 -500 0 0 0 N 315 | X D0 1 -600 -100 200 R 50 50 1 1 P 316 | X D1 2 -600 -200 200 R 50 50 1 1 P 317 | X VSNS 3 -600 100 200 R 50 50 1 1 P 318 | X ILIM 4 -600 0 200 R 50 50 1 1 P 319 | X GND 5 -600 -400 200 R 50 50 1 1 P 320 | X IN2 6 -600 300 200 R 50 50 1 1 P 321 | X OUT 7 600 400 200 L 50 50 1 1 P 322 | X IN1 8 -600 400 200 R 50 50 1 1 P 323 | ENDDRAW 324 | ENDDEF 325 | # 326 | # lcd_50pin_logic 327 | # 328 | DEF lcd_50pin_logic U 0 40 Y Y 1 F N 329 | F0 "U" 0 -1650 60 H V C CNN 330 | F1 "lcd_50pin_logic" 0 1700 60 H V C CNN 331 | F2 "" 0 900 60 H I C CNN 332 | F3 "" 0 900 60 H I C CNN 333 | DRAW 334 | T 900 -100 -1150 60 0 0 0 POWER Normal 0 C C 335 | S 500 -800 50 -1550 0 0 0 N 336 | S 500 -300 50 -800 0 0 0 N 337 | S 500 1550 50 -300 0 0 0 N 338 | P 2 0 0 0 -500 -700 -500 -200 N 339 | P 2 0 0 0 -50 1550 50 1550 N 340 | P 2 0 0 0 50 -1550 -50 -1550 N 341 | T 900 -100 100 60 0 1 0 BACKLIGHT Normal 0 C C 342 | T 900 -100 1350 60 0 1 0 BUS~SEL Normal 0 C C 343 | T 900 100 650 60 0 1 0 DATA~BUS Normal 0 C C 344 | T 900 100 -550 60 0 1 0 RGB Normal 0 C C 345 | T 900 -100 1000 60 0 1 0 RST Normal 0 C C 346 | T 900 100 -1200 60 0 1 0 SERIAL~LOGIC Normal 0 C C 347 | T 900 -100 650 60 0 1 0 TOUCH Normal 0 C C 348 | S -700 900 -50 400 0 1 0 N 349 | S -500 -700 -50 -1550 0 1 0 N 350 | S -500 400 -50 -200 0 1 0 N 351 | S -500 1100 -50 900 0 1 0 N 352 | S -500 1550 -50 1100 0 1 0 N 353 | X LEDK 1 -700 300 200 R 50 50 1 1 P 354 | X LEDA 2 -700 200 200 R 50 50 1 1 P 355 | X LEDA 3 -700 100 200 R 50 50 1 1 P 356 | X LEDA 4 -700 0 200 R 50 50 1 1 P 357 | X LEDA 5 -700 -100 200 R 50 50 1 1 P 358 | X IM0 6 -700 1500 200 R 50 50 1 1 P 359 | X IM1 7 -700 1400 200 R 50 50 1 1 P 360 | X IM2 8 -700 1300 200 R 50 50 1 1 P 361 | X IM3 9 -700 1200 200 R 50 50 1 1 P 362 | X ~RESET 10 -700 1000 200 R 50 50 1 1 P 363 | X DB12 20 700 300 200 L 50 50 1 1 P 364 | X DB2 30 700 1300 200 L 50 50 1 1 P 365 | X IOVCC 40 -700 -800 200 R 50 50 1 1 P 366 | X GND 50 -700 -1500 200 R 50 50 1 1 P 367 | X VSYNC 11 700 -700 200 L 50 50 1 1 P 368 | X DB11 21 700 400 200 L 50 50 1 1 P 369 | X DB1 31 700 1400 200 L 50 50 1 1 P 370 | X IOVCC 41 -700 -900 200 R 50 50 1 1 P 371 | X HSYNC 12 700 -600 200 L 50 50 1 1 P 372 | X DB10 22 700 500 200 L 50 50 1 1 P 373 | X DB0 32 700 1500 200 L 50 50 1 1 P 374 | X VCI 42 -700 -1000 200 R 50 50 1 1 P 375 | X DOTCLK 13 700 -500 200 L 50 50 1 1 P 376 | X DB9 23 700 600 200 L 50 50 1 1 P 377 | X SDO 33 700 -1500 200 L 50 50 1 1 P 378 | X GND 43 -700 -1200 200 R 50 50 1 1 P 379 | X DE 14 700 -400 200 L 50 50 1 1 P 380 | X DB8 24 700 700 200 L 50 50 1 1 P 381 | X SDI 34 700 -1400 200 L 50 50 1 1 P 382 | X X+(XR)/SCK 44 -900 800 200 R 50 50 1 1 P 383 | X DB17 15 700 -200 200 L 50 50 1 1 P 384 | X DB7 25 700 800 200 L 50 50 1 1 P 385 | X ~RD 35 700 -1300 200 L 50 50 1 1 P 386 | X Y+(YD)/SDA 45 -900 700 200 R 50 50 1 1 P 387 | X DB16 16 700 -100 200 L 50 50 1 1 P 388 | X DB6 26 700 900 200 L 50 50 1 1 P 389 | X ~WR_RS 36 700 -1200 200 L 50 50 1 1 P 390 | X X-(XL)/IRQ 46 -900 600 200 R 50 50 1 1 P 391 | X DB15 17 700 0 200 L 50 50 1 1 P 392 | X DB5 27 700 1000 200 L 50 50 1 1 P 393 | X RS_SCL 37 700 -1100 200 L 50 50 1 1 P 394 | X Y-(YU)/RES 47 -900 500 200 R 50 50 1 1 P 395 | X DB14 18 700 100 200 L 50 50 1 1 P 396 | X DB4 28 700 1100 200 L 50 50 1 1 P 397 | X ~CS 38 700 -1000 200 L 50 50 1 1 P 398 | X GND 48 -700 -1300 200 R 50 50 1 1 P 399 | X DB13 19 700 200 200 L 50 50 1 1 P 400 | X DB3 29 700 1200 200 L 50 50 1 1 P 401 | X TE 39 700 -900 200 L 50 50 1 1 P 402 | X GND 49 -700 -1400 200 R 50 50 1 1 P 403 | ENDDRAW 404 | ENDDEF 405 | # 406 | # pkl_C 407 | # 408 | DEF pkl_C C 0 10 N Y 1 F N 409 | F0 "C" 25 100 50 H V L CNN 410 | F1 "pkl_C" 25 -100 50 H V L CNN 411 | F2 "" 38 -150 30 H V C CNN 412 | F3 "" 0 0 60 H V C CNN 413 | $FPLIST 414 | C? 415 | C_????_* 416 | C_???? 417 | SMD*_c 418 | Capacitor* 419 | $ENDFPLIST 420 | DRAW 421 | P 2 0 1 20 -80 -30 80 -30 N 422 | P 2 0 1 20 -80 30 80 30 N 423 | X ~ 1 0 100 60 D 40 40 1 1 P 424 | X ~ 2 0 -100 60 U 40 40 1 1 P 425 | ENDDRAW 426 | ENDDEF 427 | # 428 | # pkl_C_Small 429 | # 430 | DEF pkl_C_Small C 0 10 N N 1 F N 431 | F0 "C" 10 70 50 H V L CNN 432 | F1 "pkl_C_Small" 10 -80 50 H V L CNN 433 | F2 "" 0 0 60 H V C CNN 434 | F3 "" 0 0 60 H V C CNN 435 | $FPLIST 436 | C? 437 | C_????_* 438 | C_???? 439 | SMD*_c 440 | Capacitor* 441 | $ENDFPLIST 442 | DRAW 443 | P 2 0 1 13 -60 -20 60 -20 N 444 | P 2 0 1 12 -60 20 60 20 N 445 | X ~ 1 0 100 75 D 40 40 1 1 P 446 | X ~ 2 0 -100 80 U 40 40 1 1 P 447 | ENDDRAW 448 | ENDDEF 449 | # 450 | # pkl_JACK_3C1S 451 | # 452 | DEF pkl_JACK_3C1S J 0 40 Y Y 1 F N 453 | F0 "J" -350 -300 50 H V C CNN 454 | F1 "pkl_JACK_3C1S" -150 350 50 H V C CNN 455 | F2 "" 0 0 50 H I C CNN 456 | F3 "" 0 0 50 H I C CNN 457 | DRAW 458 | S -450 200 -400 -100 0 1 0 F 459 | S -325 175 -275 -75 0 1 10 F 460 | S 300 -150 -400 250 0 1 10 N 461 | P 3 0 1 0 150 0 300 0 300 0 N 462 | P 3 0 1 10 300 200 -300 200 -300 175 N 463 | P 4 0 1 0 0 -100 -50 -50 -100 -100 -100 -100 N 464 | P 4 0 1 0 0 -100 300 -100 300 -100 300 -100 N 465 | P 4 0 1 0 50 -50 100 -100 150 -50 150 -50 N 466 | P 4 0 1 0 150 0 100 0 100 -100 100 -100 N 467 | P 4 0 1 10 300 100 -100 100 -150 50 -200 100 N 468 | X ~ 1 450 200 150 L 50 50 1 1 P 469 | X ~ 2 450 -100 150 L 50 50 1 1 P 470 | X ~ 3 450 100 150 L 50 50 1 1 P 471 | X ~ 4 450 0 150 L 50 50 1 1 P 472 | ENDDRAW 473 | ENDDEF 474 | # 475 | # pkl_LED 476 | # 477 | DEF pkl_LED D 0 40 Y N 1 F N 478 | F0 "D" 0 100 50 H V C CNN 479 | F1 "pkl_LED" 0 -100 50 H V C CNN 480 | F2 "" 0 0 60 H V C CNN 481 | F3 "" 0 0 60 H V C CNN 482 | $FPLIST 483 | LED-3MM 484 | LED-5MM 485 | LED-10MM 486 | LED-0603 487 | LED-0805 488 | LED-1206 489 | LEDV 490 | $ENDFPLIST 491 | DRAW 492 | P 2 0 1 0 50 50 50 -50 N 493 | P 3 0 1 0 -50 50 50 0 -50 -50 F 494 | P 3 0 1 0 65 -40 110 -80 105 -55 N 495 | P 3 0 1 0 80 -25 125 -65 120 -40 N 496 | X A A -200 0 150 R 40 40 1 1 P 497 | X C C 200 0 150 L 40 40 1 1 P 498 | ENDDRAW 499 | ENDDEF 500 | # 501 | # pkl_Micro_SD 502 | # 503 | DEF pkl_Micro_SD CON 0 40 Y Y 1 F N 504 | F0 "CON" -650 550 50 H V C CNN 505 | F1 "pkl_Micro_SD" 600 -550 50 H V C CNN 506 | F2 "" 150 300 50 H V C CNN 507 | F3 "" 0 0 60 H V C CNN 508 | $FPLIST 509 | Micro_SD_Card_Receptacle 510 | $ENDFPLIST 511 | DRAW 512 | S -350 -375 -250 -425 0 1 0 F 513 | S -350 -275 -250 -325 0 1 0 F 514 | S -350 -175 -250 -225 0 1 0 F 515 | S -350 -75 -250 -125 0 1 0 F 516 | S -350 25 -250 -25 0 1 0 F 517 | S -350 125 -250 75 0 1 0 F 518 | S -350 225 -250 175 0 1 0 F 519 | S -350 325 -250 275 0 1 0 F 520 | P 6 0 1 0 650 450 650 500 -800 500 -800 -500 650 -500 650 -450 N 521 | P 11 0 1 0 -400 350 -100 350 0 450 150 450 150 400 250 400 300 450 800 450 800 -450 -400 -450 -400 350 f 522 | X DAT2 1 -900 300 100 R 50 50 1 1 I 523 | X CD/DAT3 2 -900 200 100 R 50 50 1 1 I 524 | X CMD 3 -900 100 100 R 50 50 1 1 I 525 | X VDD 4 -900 0 100 R 50 50 1 1 I 526 | X CLK 5 -900 -100 100 R 50 50 1 1 I 527 | X VSS 6 -900 -200 100 R 50 50 1 1 I 528 | X DAT0 7 -900 -300 100 R 50 50 1 1 I 529 | X DAT1 8 -900 -400 100 R 50 50 1 1 I 530 | X CARD_DETECT 9 900 200 100 L 50 50 1 1 I 531 | X CARD_DETECT_GND 10 900 100 100 L 50 50 1 1 I 532 | X SHELL 11 900 -200 100 L 50 50 1 1 I 533 | ENDDRAW 534 | ENDDEF 535 | # 536 | # pkl_Q_NMOS_BD_GSD 537 | # 538 | DEF pkl_Q_NMOS_BD_GSD Q 0 0 Y N 1 F N 539 | F0 "Q" 200 50 50 H V L CNN 540 | F1 "pkl_Q_NMOS_BD_GSD" 200 -50 50 H V L CNN 541 | F2 "" 200 100 29 H V C CNN 542 | F3 "" 0 0 60 H V C CNN 543 | $FPLIST 544 | LFPAK* 545 | SO* 546 | SOT669* 547 | $ENDFPLIST 548 | DRAW 549 | C 50 0 111 0 1 10 N 550 | C 100 -70 4 0 1 0 N 551 | C 100 70 4 0 1 0 N 552 | P 2 0 1 0 30 -70 100 -70 N 553 | P 2 0 1 10 30 -50 30 -90 N 554 | P 2 0 1 0 30 0 100 0 N 555 | P 2 0 1 10 30 20 30 -20 N 556 | P 2 0 1 0 30 70 100 70 N 557 | P 2 0 1 10 30 90 30 50 N 558 | P 2 0 1 0 100 -70 100 -100 N 559 | P 2 0 1 0 100 -70 100 0 N 560 | P 2 0 1 0 100 100 100 70 N 561 | P 2 0 1 0 108 12 132 12 N 562 | P 3 0 1 10 10 75 10 -75 10 -75 N 563 | P 4 0 1 0 40 0 80 15 80 -15 40 0 F 564 | P 4 0 1 0 100 -70 120 -70 120 70 100 70 N 565 | P 4 0 1 0 110 -16 130 -16 120 14 110 -16 F 566 | X G 1 -200 0 210 R 50 50 1 1 I 567 | X S 2 100 -200 100 U 50 50 1 1 E 568 | X D 3 100 200 100 D 50 50 1 1 C 569 | ENDDRAW 570 | ENDDEF 571 | # 572 | # pkl_R4_Small 573 | # 574 | DEF pkl_R4_Small R 0 10 N N 4 F N 575 | F0 "R" 30 20 50 H V L CNN 576 | F1 "pkl_R4_Small" 30 -40 50 H V L CNN 577 | F2 "" 0 0 60 H V C CNN 578 | F3 "" 0 0 60 H V C CNN 579 | $FPLIST 580 | Resistor_* 581 | R_* 582 | $ENDFPLIST 583 | DRAW 584 | S -30 70 30 -70 0 1 8 N 585 | X ~ 1 0 100 30 D 40 40 1 1 P 586 | X ~ 2 0 -100 30 U 40 40 1 1 P 587 | X ~ 3 0 100 30 D 40 40 2 1 P 588 | X ~ 4 0 -100 30 U 40 40 2 1 P 589 | X ~ 5 0 100 30 D 40 40 3 1 P 590 | X ~ 6 0 -100 30 U 40 40 3 1 P 591 | X ~ 7 0 100 30 D 40 40 4 1 P 592 | X ~ 8 0 -100 30 U 40 40 4 1 P 593 | ENDDRAW 594 | ENDDEF 595 | # 596 | # pkl_R_Small 597 | # 598 | DEF pkl_R_Small R 0 10 N N 1 F N 599 | F0 "R" 30 20 50 H V L CNN 600 | F1 "pkl_R_Small" 30 -40 50 H V L CNN 601 | F2 "" 0 0 60 H V C CNN 602 | F3 "" 0 0 60 H V C CNN 603 | $FPLIST 604 | Resistor_* 605 | R_* 606 | $ENDFPLIST 607 | DRAW 608 | S -30 70 30 -70 0 1 8 N 609 | X ~ 1 0 100 30 D 40 40 1 1 P 610 | X ~ 2 0 -100 30 U 40 40 1 1 P 611 | ENDDRAW 612 | ENDDEF 613 | # 614 | # pkl_SWITCH-SPDT 615 | # 616 | DEF pkl_SWITCH-SPDT SW 0 40 N N 1 F N 617 | F0 "SW" 150 -75 60 H V L CNN 618 | F1 "pkl_SWITCH-SPDT" 150 75 60 H V L CNN 619 | F2 "" 0 -25 60 H V C CNN 620 | F3 "" 0 -25 60 H V C CNN 621 | DRAW 622 | C -100 0 10 0 0 0 N 623 | C 0 -100 10 0 0 0 N 624 | C 0 100 10 0 0 0 N 625 | P 2 0 0 0 -100 0 0 75 N 626 | C 0 0 150 0 1 10 N 627 | X ~ 1 0 200 100 D 50 50 1 1 P 628 | X ~ 2 -200 0 100 R 50 50 1 1 P 629 | X ~ 3 0 -200 100 U 50 50 1 1 P 630 | ENDDRAW 631 | ENDDEF 632 | # 633 | #End Library 634 | -------------------------------------------------------------------------------- /hardware/contrib/1up-mini/1up-mini.pro: -------------------------------------------------------------------------------- 1 | update=lun. 24 juil. 2017 23:53:16 CEST 2 | version=1 3 | last_client=kicad 4 | [pcbnew] 5 | version=1 6 | LastNetListRead= 7 | UseCmpFile=1 8 | PadDrill=0.600000000000 9 | PadDrillOvalY=0.600000000000 10 | PadSizeH=1.500000000000 11 | PadSizeV=1.500000000000 12 | PcbTextSizeV=1.500000000000 13 | PcbTextSizeH=1.500000000000 14 | PcbTextThickness=0.300000000000 15 | ModuleTextSizeV=1.000000000000 16 | ModuleTextSizeH=1.000000000000 17 | ModuleTextSizeThickness=0.150000000000 18 | SolderMaskClearance=0.000000000000 19 | SolderMaskMinWidth=0.000000000000 20 | DrawSegmentWidth=0.200000000000 21 | BoardOutlineThickness=0.100000000000 22 | ModuleOutlineThickness=0.150000000000 23 | [cvpcb] 24 | version=1 25 | NetIExt=net 26 | [general] 27 | version=1 28 | [schematic_editor] 29 | version=1 30 | PageLayoutDescrFile= 31 | PlotDirectoryName= 32 | SubpartIdSeparator=0 33 | SubpartFirstId=65 34 | NetFmtName=Pcbnew 35 | SpiceForceRefPrefix=0 36 | SpiceUseNetNumbers=0 37 | LabSize=60 38 | [eeschema] 39 | version=1 40 | LibDir=../../lib/pkl;../../lib/stm32;../../lib/1bitsy/kicad 41 | [eeschema/libraries] 42 | LibName1=power 43 | LibName2=device 44 | LibName3=transistors 45 | LibName4=conn 46 | LibName5=linear 47 | LibName6=regul 48 | LibName7=74xx 49 | LibName8=cmos4000 50 | LibName9=adc-dac 51 | LibName10=memory 52 | LibName11=xilinx 53 | LibName12=microcontrollers 54 | LibName13=dsp 55 | LibName14=microchip 56 | LibName15=analog_switches 57 | LibName16=motorola 58 | LibName17=texas 59 | LibName18=intel 60 | LibName19=audio 61 | LibName20=interface 62 | LibName21=digital-audio 63 | LibName22=philips 64 | LibName23=display 65 | LibName24=cypress 66 | LibName25=siliconi 67 | LibName26=opto 68 | LibName27=atmel 69 | LibName28=contrib 70 | LibName29=valves 71 | LibName30=pkl_conn 72 | LibName31=pkl_device 73 | LibName32=pkl_ftdi 74 | LibName33=pkl_logos 75 | LibName34=pkl_misc 76 | LibName35=pkl_molex 77 | LibName36=pkl_power 78 | LibName37=pkl_sensor 79 | LibName38=pkl_tag_connect 80 | LibName39=pkl_texas 81 | LibName40=stm32 82 | LibName41=1bitsy 83 | -------------------------------------------------------------------------------- /hardware/contrib/1up-mini/README.md: -------------------------------------------------------------------------------- 1 | # 1up-mini 2 | 3 | This is a board based on 1up v0.2, with horizontal form factor and easier to 4 | solder by hand. 5 | 6 | It is not supported by 1bit squared. 7 | 8 | ## What changed? 9 | 10 | It aims to be fully compatible with 1up board. Some of the components are 11 | changed to avoid hard to solder packages: 12 | 13 | - Headphone amplifier reference is changed. It consumes more power than the 14 | one used on the original board. 15 | - Volume control is the same component, with a different package. 16 | - Battery charger and power path is split in two components. 17 | - 0402 footprints are replaced with 0603. 18 | - Touch screen signals are only connected to 6 pin connector. 19 | 20 | Board shape is horizontal with symmetric buttons on both sides. 21 | 22 | ## What to change for the next iteration? 23 | 24 | - 0603 and resistor network footprints are a little bit to small for hand 25 | soldering. 26 | - SD card slot must be changed for something easier to solder. 27 | - Headphone jack could be changed for something more solid. 28 | - Hole for pogo pin is too small. Add a large pad so that it can be replaced 29 | with a cable. 30 | - Switch are hard to source. Also the one I ordered are not so good. 31 | 32 | ## Assembly 33 | 34 | Some tricky points: 35 | 36 | - You will need solder paste, flux and hot air to solder the SD card slot. 37 | - Surface under the LCD should be flat. Cut the pin used to mount the 1bitsy 38 | before soldering. Use isolating tape to avoid short circuits (there is a 39 | metal shield under the LCD). 40 | - You can replace the pogo pin with a cable. 41 | 42 | ## BOM 43 | 44 | | Reference | Package | Qty. | Designation | Mouser/URL | 45 | | ---------------------- | ---------- | ---- | --------------- | -------------------- | 46 | | C[19,26,27,29,30] | 0603 | 5 | 100 nF | | 47 | | C[20,21,24,25,31..33] | 0603 | 7 | 1 µF | | 48 | | C[22,23] | 0603 | 2 | 2.2 µF | | 49 | | C28 | 0805 | 1 | 10 µF | | 50 | | CON1 | SCHA4B0419 | 1 | Micro SD | 688-SCHA4B0419 | 51 | | D2 | 0603 | 1 | Yellow LED | | 52 | | J3 | Jack | 1 | JACK_3C1S | 490-SJ2-35853BSMT-TR | 53 | | P1 | PogoPin | 1 | PogoPin | 575-906115 or cable | 54 | | P[2..4] | | 3 | Battery conn. | | 55 | | Q1 | SOT-23 | 1 | NMOS | 726-BSS806NH6327XT | 56 | | R11 | 0603 | 1 | 49 kΩ | | 57 | | R[12..15] | 4x0603 | 4 | 10 kΩ | 667-EXB-38V103JV | 58 | | R[17,18] | 0603 | 2 | 2.7 kΩ | | 59 | | R[20..23] | 0603 | 4 | 10 Ω | | 60 | | R24 | 0603 | 1 | 1 kΩ | | 61 | | R6 | 0603 | 1 | 4.7 kΩ | | 62 | | R[7,10,16,19,25,26,30] | 0603 | 7 | 10 kΩ | | 63 | | R[8,9] | 0603 | 2 | 50 Ω | | 64 | | SW[12,13] | Switch | 2 | Side Switch | 653-B3U-3000P | 65 | | SW14 | Switch | 1 | SPDT Switch | 611-PCM12SMTR | 66 | | SW[2..11] | Switch | 1 | Switch | [aliexpress][] | 67 | | U10 | TSSOP-8 | 1 | TPS2111A | 595-TPS2111APWR | 68 | | U2 | 1bitsy | 1 | 1bitsy | | 69 | | U3 | TSSOP-14 | 1 | MCP4661-103E/ST | 579-MCP4661-103E/ST | 70 | | U4 | TSSOP-14 | 1 | TPA6139A2-PW | 595-TPA6139A2PWR | 71 | | U[5,6] | TSSOP-16 | 2 | 74HC165 | 771-74HC165PW-T | 72 | | U7 | SOT-23-6 | 1 | BQ21040 | 595-BQ21040DBVR | 73 | | U8 | ER-CON50HT | 1 | 50 pin conn. | sold with LCD | 74 | | U9 | ER-CON06HB | 1 | 6 pin conn. | sold with LCD | 75 | | LCD | | 1 | LCD | [buydisplay][] | 76 | 77 | [buydisplay]: 78 | http://www.buydisplay.com/default/serial-spi-2-8-tft-lcd-module-display-320x240-optional-touch-screen 79 | [aliexpress]: 80 | https://www.aliexpress.com/store/product/Original-new-100-Japan-conductive-rubber-head-waterproof-touch-switch-8-8-5-silent-key-micro/828867_32724415032.html 81 | -------------------------------------------------------------------------------- /hardware/contrib/1up-mini/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (lib (name pkl_logos)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_logos.pretty)(options "")(descr "")) 3 | (lib (name pkl_pads)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_pads.pretty)(options "")(descr "")) 4 | (lib (name pkl_misc)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_misc.pretty)(options "")(descr "")) 5 | (lib (name pkl_buttons_switches)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_buttons_switches.pretty)(options "")(descr "")) 6 | (lib (name pkl_connectors)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_connectors.pretty)(options "")(descr "")) 7 | (lib (name pkl_dipol)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_dipol.pretty)(options "")(descr "")) 8 | (lib (name pkl_housings_dfn_qfn)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_housings_dfn_qfn.pretty)(options "")(descr "")) 9 | (lib (name pkl_housings_sop)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_housings_sop.pretty)(options "")(descr "")) 10 | (lib (name pkl_jumpers)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_jumpers.pretty)(options "")(descr "")) 11 | (lib (name pkl_housings_sot)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_housings_sot.pretty)(options "")(descr "")) 12 | (lib (name pkl_pin_headers)(type KiCad)(uri ${KIPRJMOD}/../../lib/pkl/pkl_pin_headers.pretty)(options "")(descr "")) 13 | (lib (name 1bitsy)(type KiCad)(uri ${KIPRJMOD}/../../lib/1bitsy/kicad/1bitsy.pretty)(options "")(descr "")) 14 | ) 15 | -------------------------------------------------------------------------------- /hardware/v0.2/1bitsy-1up.pro: -------------------------------------------------------------------------------- 1 | update=Sat 24 Mar 2018 03:29:19 PM PDT 2 | version=1 3 | last_client=kicad 4 | [pcbnew] 5 | version=1 6 | LastNetListRead= 7 | UseCmpFile=1 8 | PadDrill=0.600000000000 9 | PadDrillOvalY=0.600000000000 10 | PadSizeH=1.500000000000 11 | PadSizeV=1.500000000000 12 | PcbTextSizeV=1.500000000000 13 | PcbTextSizeH=1.500000000000 14 | PcbTextThickness=0.300000000000 15 | ModuleTextSizeV=1.000000000000 16 | ModuleTextSizeH=1.000000000000 17 | ModuleTextSizeThickness=0.150000000000 18 | SolderMaskClearance=0.000000000000 19 | SolderMaskMinWidth=0.000000000000 20 | DrawSegmentWidth=0.200000000000 21 | BoardOutlineThickness=0.100000000000 22 | ModuleOutlineThickness=0.150000000000 23 | [cvpcb] 24 | version=1 25 | NetIExt=net 26 | [general] 27 | version=1 28 | [schematic_editor] 29 | version=1 30 | PageLayoutDescrFile= 31 | PlotDirectoryName= 32 | SubpartIdSeparator=0 33 | SubpartFirstId=65 34 | NetFmtName= 35 | SpiceForceRefPrefix=0 36 | SpiceUseNetNumbers=0 37 | LabSize=60 38 | [eeschema] 39 | version=1 40 | LibDir= 41 | -------------------------------------------------------------------------------- /hardware/v0.2/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (lib (name 74xx)(type Legacy)(uri ${KICAD_SYMBOL_DIR}/74xx.lib)(options "")(descr "")) 3 | (lib (name pkl_conn)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_conn.lib)(options "")(descr "")) 4 | (lib (name pkl_device)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_device.lib)(options "")(descr "")) 5 | (lib (name pkl_ftdi)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_ftdi.lib)(options "")(descr "")) 6 | (lib (name pkl_linear)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_linear.lib)(options "")(descr "")) 7 | (lib (name pkl_logos)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_logos.lib)(options "")(descr "")) 8 | (lib (name pkl_maxim)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_maxim.lib)(options "")(descr "")) 9 | (lib (name pkl_misc)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_misc.lib)(options "")(descr "")) 10 | (lib (name pkl_molex)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_molex.lib)(options "")(descr "")) 11 | (lib (name pkl_power)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_power.lib)(options "")(descr "")) 12 | (lib (name pkl_sensor)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_sensor.lib)(options "")(descr "")) 13 | (lib (name pkl_tag_connect)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_tag_connect.lib)(options "")(descr "")) 14 | (lib (name pkl_texas)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_texas.lib)(options "")(descr "")) 15 | (lib (name 1bitsy)(type Legacy)(uri ${KIPRJMOD}/../lib/1bitsy/kicad/1bitsy.lib)(options "")(descr "")) 16 | (lib (name pkl_lattice)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_lattice.lib)(options "")(descr "")) 17 | (lib (name pkl_memory)(type Legacy)(uri ${KIPRJMOD}/../lib/pkl/pkl_memory.lib)(options "")(descr "")) 18 | (lib (name stm32)(type Legacy)(uri ${KIPRJMOD}/../lib/stm32/stm32.lib)(options "")(descr "")) 19 | ) 20 | --------------------------------------------------------------------------------