Keypads and C and assembly development introduction: Difference between pages

From Hackspire
(Difference between pages)
Jump to navigation Jump to search
(Add text about the on/home button)
 
(Recommend WSL more)
 
Line 1: Line 1:
==Key maps==
This tutorial describes how to set up an environment and use the Ndless SDK to write native Ndless-compatible programs for the TI-Nspire.


Each bit in the 900E0010-900E001F registers represents a key. Only bits 0 to 10 are used in each halfword. The mapping depends on the currently used keypad.
==Install dependencies==
===On Linux distros===
* '''Make sure your system has the following dependencies''': git, GCC (with c++ support), binutils, GMP (libgmp-dev), MPFR (libmpfr-dev), MPC (libmpc-dev), zlib, boost-program-options, wget. Install them with your system's package manager if not.


'''Clickpad keypad map:'''
===On Mac OS X===
* TODO
* '''Make sure your system has the following dependencies''': git, GCC (with c++ support), binutils, GMP, MPFR, MPC, boost-program-options, zlib, wget. Install them with your system's package manager if not, for example brew.


If the bit is cleared, the key is being pressed.
===On Windows===
MinGW and MSYS do not work correctly, so use WSL (distro should not matter) or install Cygwin (32bit, x86). WSL is closer to a real Linux environment and likely easier to set up.


{|border="1" cellspacing="0" cellpadding="5"
====Cygwin====
|-
Install the following dependencies: php (5.6+), libboost-devel, libboost_program_options*, binutils, gcc-core, gcc-g++, git, mpfr, mpfr-devel, gmp, libgmp-devel, libmpc3, libmpc-devel, make, zlib-devel, wget
! offset
! bit 0
! bit 1
! bit 2
! bit 3
! bit 4
! bit 5
! bit 6
! bit 7
! bit 8
! bit 9
! bit 10
|-
| 0010
| ret
| enter
| space
| (-)
| Z
| .
| Y
| 0
| X
| on
| theta
|-
| 0012
| ,
| +
| W
| 3
| V
| 2
| U
| 1
| T
| e^x
| pi
|-
| 0014
| ?
| -
| S
| 6
| R
| 5
| Q
| 4
| P
| 10^x
| EE
|-
| 0016
| :
| *
| O
| 9
| N
| 8
| M
| 7
| L
| x^2
| i
|-
| 0018
| "
| /
| K
| tan
| J
| cos
| I
| sin
| H
| ^
| >
|-
| 001A
| '
| cat
| G
| )
| F
| (
| E
| var
| D
| shift
| <
|-
| 001C
| flag
| click
| C
| home
| B
| menu
| A
| esc
| &#124;
| tab
| bgcolor=lightgray |
|-
| 001E
| up
| u+r
| right
| r+d
| down
| d+l
| left
| l+u
| del
| ctrl
| =
|}


'''TI-84+ keypad map:'''
==Build and install toolchain and SDK==
*'''Get the latest code from [https://github.com/ndless-nspire/Ndless GitHub]'''
git clone --recursive https://github.com/ndless-nspire/Ndless.git


If the bit is cleared, the key is being pressed.
* On Windows, fix the few symlinks, for instance zehn.h in the ndless-sdk/tools/genzehn folder, which has to be deleted then copied there from ndless-sdk/include (and if you intend to rebuild Ndless, utils.c from the resources folder into the different installers folders)


{|border="1" cellspacing="0" cellpadding="5"
* '''Run the SDK's ''build_toolchain.sh'' '''script that will download and build a complete ARM toolchain compatible with Ndless, and install it (edit the <tt>PREFIX</tt> variable at the beginning of the script to change the install location). You don't need to be root for this.
|-
cd ndless-sdk/toolchain/
! offset
./build_toolchain.sh
! bit 0
! bit 1
! bit 2
! bit 3
! bit 4
! bit 5
! bit 6
! bit 7
! bit 8
! bit 9
! bit 10
|-
| 0010
| down
| left
| right
| up
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 0012
| enter
| +
| -
| *
| /
| ^
| clear
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 0014
| (-)
| 3
| 6
| 9
| )
| tan
| vars
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 0016
| .
| 2
| 5
| 8
| (
| cos
| prgm
| stat
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 0018
| 0
| 1
| 4
| 7
| ,
| sin
| apps
| X
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 001A
| on
| sto
| ln
| log
| x^2
| x^-1
| math
| alpha
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 001C
| graph
| trace
| zoom
| wind
| y=
| 2nd
| mode
| del
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|-
| 001E
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
|}


'''Touchpad/CX/CM/CX II keypad map:'''
Running the script again will continue from the last successful step (not redownloading everything for instance). At the end of a successful build you should see <tt>Done!</tt>. Alternatively you can verify the build using <tt>echo $?</tt>. <tt>0</tt> indicates success.
* Now '''add the following folders to your PATH environment variable'''. On linux, <tt>~/.bash_profile</tt> should be a good place for this, just add something like this to it:
export PATH="[path_to_ndless]/ndless-sdk/toolchain/install/bin:[path_to_ndless]/ndless-sdk/bin:${PATH}"
* '''Build Ndless and the SDK''', in the top level of the repository, run:
make


If the bit is set, the key is being pressed.
===Verifying the installation===
*Open a console, and run:
$ nspire-gcc
If everything has been set up correctly you should see something similar to:
arm-none-eabi-gcc: fatal error: no input files
compilation terminated.


The On/Home button on the CX/CM is accessible at bit 4 of 0x900B0028 and on the CX II at bit 8 of 0x90140810. Both are inverted, i.e. 0 = pressed, 1 = not pressed.
==2-minute tutorial==
libndls' <code>on_key_pressed()</code> function handles that for all models.
As a convention for the next chapters, lines starting with <tt>$</tt> are commands you should type in a console. Other lines are the command's output.
===Your first build===
Ndless comes with sample programs in the ''samples/'' directory of the Ndless SDK. We will try to build the C Hello World.
Change the current directory of the console:
$ cd "<my_ndless_sdk_copy>/ndless-sdk/samples/helloworld-sdl"
Ndless programs are built with ''GNU Make'', which is run with the command <tt>make</tt>. So let's ''make'' the program:
$ make
nspire-gcc -Wall -W -marm -Os -c hello-sdl.c
mkdir -p .
nspire-ld hello-sdl.o -o ./helloworld-sdl.elf
genzehn --input ./helloworld-sdl.elf --output ./helloworld-sdl.tns --name "helloworld-sdl"
make-prg ./helloworld-sdl.tns ./helloworld-sdl.prg.tns
<tt>nspire-gcc</tt> is Ndless's wrapper for the GNU C Compiler ''GCC'', which compiles C and assembly source files to object files (here ''hello.o'').


{|border="1" cellspacing="0" cellpadding="5"
<tt>nspire-ld</tt> is the wrapper for ''GCC'', which redirects gcc with the option "-fuse-ld=gold" to use another wrapper "arm-none-eabi-ld.gold" as linker. "arm-none-eabi-ld.gold" adds some necessary libraries to the final program.
|-
! offset
! bit 0
! bit 1
! bit 2
! bit 3
! bit 4
! bit 5
! bit 6
! bit 7
! bit 8
! bit 9
! bit 10
|-
| 0010
| ret
| enter
| bgcolor=lightgray |
| (-)
| space
| Z
| Y
| 0
| ?!
| on
| bgcolor=lightgray |
|-
| 0012
| X
| W
| V
| 3
| U
| T
| S
| 1
| pi
| trig
| 10^x
|-
| 0014
| R
| Q
| P
| 6
| O
| N
| M
| 4
| EE
| x^2
| bgcolor=lightgray |
|-
| 0016
| L
| K
| J
| 9
| I
| H
| G
| 7
| /
| e^x
| bgcolor=lightgray |
|-
| 0018
| F
| E
| D
| bgcolor=lightgray |
| C
| B
| A
| =
| *
| ^
| bgcolor=lightgray |
|-
| 001A
| bgcolor=lightgray |
| var
| -
| )
| .
| (
| 5
| cat
| frac
| del
| scratch
|-
| 001C
| flag
| bgcolor=lightgray |
| +
| doc
| 2
| menu
| 8
| esc
| bgcolor=lightgray |
| tab
| bgcolor=lightgray |
|-
| 001E
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| bgcolor=lightgray |
| shift
| ctrl
| ,
|}


==Touchpad I²C==
<tt>genzehn</tt> converts the executable created by "nspire-ld" to a format, which ndless supports.


Communication with the actual touchpad is done with the [http://en.wikipedia.org/wiki/I%C2%B2C I²C] protocol.
<tt>make-prg</tt> adds a simple loader on top so the executable works on older versions of ndless.


On the original Touchpad models, the I2C protocol is bitbanged through the GPIO: GPIO 1 is the Serial Clock (SCL) and GPIO 3 is the Serial Data Line (SDA). On the CX and CX II models, there is a dedicated [[Memory-mapped_I/O_ports#90050000_-_I2C_controller|I2C controller]] for accessing it.
===Your first program===
 
If you want to create a program from scratch:
Calculators before the CX II HW rev. AK use the Synaptics protocol, but later versions (indicated by bit 0 of the [[NAND_Memory_Layout#Manuf_Format|HW flags]]) use a custom touchpad and protocol called "CapTIvate".
*Create a new directory for the program
 
*Type in a console:
===Synaptics protocol===
cd "<your directory path>"
 
nspire-tools new <name>
The touchpad seems to be a [http://read.pudn.com/downloads64/doc/fileformat/229278/510-501-rev4-tm603.pdf TM-603].
:where <name> is your program name. This will create a Makefile to build ''<program>.tns''
[http://lxr.free-electrons.com/source/drivers/input/mouse/synaptics_i2c.c The linux driver] is a good source for documentation.
*Create a new .c file and edit your program
 
*Run <tt>make</tt> to build it
it responds to messages with address 0x20. A write message consists of the first port to write to, followed by the values to write: the port number auto-increments, so a message of <tt>00 de ad</tt> writes <tt>de</tt> to port <tt>00</tt> and <tt>ad</tt> to port <tt>01</tt>. A read message reads from whatever port was set by the previous write message, so it generally has to be preceded by an empty write to set the port.
 
A list of some of the touchpad's ports follows. All 16-bit numbers are big-endian.
 
* Any page:
** FF: Page number
* Page 04 (default):
** 00: Contact (usually is 01 if proximity >= 0x2F, 00 otherwise)
** 01: Proximity
** 02-03: X position
** 04-05: Y position
** 06: relative X
** 07: relative Y (both refresh on irq)
** 0A: 1 if touchpad pressed down, 0 if not
** 0B: Status (reading this clears the low bits)
*** Bit 0 (0x01): Set when proximity is nonzero
*** Bit 1 (0x02): Set when velocity bytes are nonzero
*** Bit 2 (0x04): Set when unknown byte at 08 is nonzero
*** Bit 3 (0x08): Set when pressed byte has changed
*** Bit 6 (0x40): Set when the touchpad is configured
*** Bit 7 (0x80): Set when an error occured
** E4-E7: Firmware version
* Page 10:
** 04-05: Maximum X coordinate (0x0918)
** 06-07: Maximum Y coordinate (0x069B)
 
===CapTIvate protocol===
 
The captivate touchpad seems to use an entirely custom protocol with less capabilities. It has a simpler structure: The first byte is a command byte, then data is either read or written, depending on the command.
Unlike the synaptics protocol, multi-byte values are little-endian.
 
====01: Read "WHY_BOTHER_ME"====
 
* Byte 0: 0/Unknown
* Byte 1: Flag byte
** Bit 0: Set if touchpad pressed
** Bit 1: Set if touchpad touched
** Bit 2: Clear if touchpad touched (?)
** Bit 3: Set if something changed after the last read
* Byte 2+3: X position
* Byte 4+5: Y position
 
====03: Write unknown====
 
The OS writes a single byte here.
 
====06: Read status====
 
* Byte 0: 0/Unknown
* Byte 1: Whether the touchpad is configured
* Byte 2-5: Unknown
 
====07: Read size====
 
* Byte 0: 0/Unknown
* Byte 1: 0/Unknown
* Byte 2+3: Width
* Byte 4+5: Height
 
====08: Read firmware version====
 
    0, 0, 1, 0, 0, 4
 
====0A: Read unknown====
 
Six unknown bytes.
 
====0C: Write unknown====
 
The OS writes a single byte here.
 
==Keypad Connector==
The Connector joining the keypads to the nspire itself has a very basic design concept: There are a bunch of GPIO pins, VCC, and GND. The OS memory-maps the pins to the bit chart seen above, using half as input, half as output. The same pins the touchpad uses for its I2C connection are used for buttons on the clickpad.
 
The pins are as follows:
1. Ground
2. Vcc
3-30. GPIO pins, alternating Column-Row-Column-Row
 
On the 84+ Pad:
Pin 23 = Link port wire 1
Pin 25 = Link port wire 2
 
 
The OS is constantly doing iskeypressed() on all the keys, so the pins end up looking like a square wave if read by a 'scope. Input pins only show the wave if one of their buttons is pressed, but output pins show the whole wave regardless.
 
If you can't envision how the keys actually work yet, this might help:
All the buttons have 2 connectors, that get shorted when they are pressed.
The bits in the table above represent columns of buttons. It's not layed out perfectly because it has more than 8 buttons per column, so it gets offset strangely.
The bits in the offsets (the rows) represent rows of buttons.
 
The columns are each hooked to one Input pin.
The rows are each hooked to one output pin.
The calculator turns on ''One'' output pin, and looks for any signals on the inputs. If there are any, it records the button that matches the input pin and that column.
It then repeats this process for all the other columns, and the iskeypressed() process is complete.
 
If this doesn't make any sense still, email me (willrandship at gmail dot com) and I'll see if I can help.
--[[User:Willrandship|William Shipley]] 05:38, 16 September 2011 (CEST)

Revision as of 18:50, 16 May 2022

This tutorial describes how to set up an environment and use the Ndless SDK to write native Ndless-compatible programs for the TI-Nspire.

Install dependencies

On Linux distros

  • Make sure your system has the following dependencies: git, GCC (with c++ support), binutils, GMP (libgmp-dev), MPFR (libmpfr-dev), MPC (libmpc-dev), zlib, boost-program-options, wget. Install them with your system's package manager if not.

On Mac OS X

  • TODO
  • Make sure your system has the following dependencies: git, GCC (with c++ support), binutils, GMP, MPFR, MPC, boost-program-options, zlib, wget. Install them with your system's package manager if not, for example brew.

On Windows

MinGW and MSYS do not work correctly, so use WSL (distro should not matter) or install Cygwin (32bit, x86). WSL is closer to a real Linux environment and likely easier to set up.

Cygwin

Install the following dependencies: php (5.6+), libboost-devel, libboost_program_options*, binutils, gcc-core, gcc-g++, git, mpfr, mpfr-devel, gmp, libgmp-devel, libmpc3, libmpc-devel, make, zlib-devel, wget

Build and install toolchain and SDK

  • Get the latest code from GitHub
git clone --recursive https://github.com/ndless-nspire/Ndless.git
  • On Windows, fix the few symlinks, for instance zehn.h in the ndless-sdk/tools/genzehn folder, which has to be deleted then copied there from ndless-sdk/include (and if you intend to rebuild Ndless, utils.c from the resources folder into the different installers folders)
  • Run the SDK's build_toolchain.sh script that will download and build a complete ARM toolchain compatible with Ndless, and install it (edit the PREFIX variable at the beginning of the script to change the install location). You don't need to be root for this.
cd ndless-sdk/toolchain/
./build_toolchain.sh

Running the script again will continue from the last successful step (not redownloading everything for instance). At the end of a successful build you should see Done!. Alternatively you can verify the build using echo $?. 0 indicates success.

  • Now add the following folders to your PATH environment variable. On linux, ~/.bash_profile should be a good place for this, just add something like this to it:
export PATH="[path_to_ndless]/ndless-sdk/toolchain/install/bin:[path_to_ndless]/ndless-sdk/bin:${PATH}"
  • Build Ndless and the SDK, in the top level of the repository, run:
make

Verifying the installation

  • Open a console, and run:
$ nspire-gcc

If everything has been set up correctly you should see something similar to:

arm-none-eabi-gcc: fatal error: no input files
compilation terminated.

2-minute tutorial

As a convention for the next chapters, lines starting with $ are commands you should type in a console. Other lines are the command's output.

Your first build

Ndless comes with sample programs in the samples/ directory of the Ndless SDK. We will try to build the C Hello World. Change the current directory of the console:

$ cd "<my_ndless_sdk_copy>/ndless-sdk/samples/helloworld-sdl"

Ndless programs are built with GNU Make, which is run with the command make. So let's make the program:

$ make
nspire-gcc -Wall -W -marm -Os -c hello-sdl.c
mkdir -p .
nspire-ld hello-sdl.o -o ./helloworld-sdl.elf 
genzehn --input ./helloworld-sdl.elf --output ./helloworld-sdl.tns --name "helloworld-sdl"
make-prg ./helloworld-sdl.tns ./helloworld-sdl.prg.tns

nspire-gcc is Ndless's wrapper for the GNU C Compiler GCC, which compiles C and assembly source files to object files (here hello.o).

nspire-ld is the wrapper for GCC, which redirects gcc with the option "-fuse-ld=gold" to use another wrapper "arm-none-eabi-ld.gold" as linker. "arm-none-eabi-ld.gold" adds some necessary libraries to the final program.

genzehn converts the executable created by "nspire-ld" to a format, which ndless supports.

make-prg adds a simple loader on top so the executable works on older versions of ndless.

Your first program

If you want to create a program from scratch:

  • Create a new directory for the program
  • Type in a console:
cd "<your directory path>"
nspire-tools new <name>
where <name> is your program name. This will create a Makefile to build <program>.tns
  • Create a new .c file and edit your program
  • Run make to build it