USB Protocol and Memory-mapped I/O ports on CX: Difference between pages

From Hackspire
(Difference between pages)
Jump to navigation Jump to search
mNo edit summary
 
 
Line 1: Line 1:
This article describes the protocol used for USB communication between the computer and the TI-Nspire. It has been documented from TI's official linking software ''Computer Link Software'', an analysis of USB captures of data traffic, and results of tests with a custom host implementation. This documentation may be used to build a full-featured third-party implementation of the computer program, to use features provided by the link not available from Computer Link Software's GUI, to indirectly gather additional information on the TI-Nspire hardware and software, and to discover exploitable flaws in the TI-Nspire OS's implementation of the protocol. An implementation of the protocol is available in [http://lpg.ticalc.org/prj_tilp/ TiLP].
==00000000 - Boot1 ROM==
128kB of on-chip ROM.


The documentation is currently incomplete, sometimes vague or too restrictive, and may be wrong on some points. Feel free to contribute to its enhancement and refinement. Interrogations and information based on assumptions which needs to be confirmed by a deeper analysis, more tests with Computer Link Software or tests with a third-party host implementation are <span style="color: IndianRed">formatted in indian red</span>. Once enough tests have been made to validate or correct these parts, please edit them and remove the highlighting.
==10000000 - SDRAM==


The descriptions of the packets of the protocol let sometimes appear hard-coded value, for which it is not clear whether the corresponding field is constant or may vary under certain conditions. You may edit these descriptions to document additional logic found for them. Borderline cases have not all been tested: most of the time the TI-Nspire's implementation of the protocol handles them and make use of error codes. These error codes have not all been documented yet.
32 MiB SDRAM on CM or 64 MiB on CX. Managed by 0x8FFF0000.


==Loopback transfers==
==8FFF0000 - SDRAM controller==
When the TI-Nspire is connected to a computer, but Computer Link Software is ''not'' running, sending the Operating System from the menu of the document management screen make it act as if it was sending and receiving the OS at the same time. The storage memory consumption increases during the loopback transfer, as it does for a real OS upgrade. The same behavior appears when trying to send documents from there contextual menu. The received documents are copied with a new name that has numerical suffix. Loopback transfers don't seem to be faster than real ones, probably because nearly the whole connectivity stack is used, and the physical transfer is not what limits the speed.


No data is exchanged with the computer during a loopback transfer (USB analyzers don't report anything, and it works even when the TI-Nspire driver is not installed).
A DMC-340 r1p0.


==USB descriptors==
==8FFF1000 - NAND controller==
Here is the interesting part (i.e. different from the TI-84 Plus and Titanium) of the USB descriptors advertised by the TI-NSpire in standard (not TI-84 Plus emulation) mode.


Device Descriptor:
A PL351 r1p2.
idProduct E012h (reminder: E001 : Silverlink, E004: Titanium, E008: TI-84 Plus, E022: Nspire CX II)
bcdDevice 0100h // 1.00
iProduct       // "TI-Nspire(tm) Handheld"
Configuration Descriptor:
bmAttributes   80h // Bus Powered (Titanium: Self Powered Remote Wakeup)
bMaxPower   32h // 100 mA (Titanium: 0 mA)
OTG Descriptor // As on Titanium and TI-84 Plus
Interface descriptor: Vendor Specific class, 1 Bulk IN endpoint, 2 Bulk OUT endpoints (64 bytes)
(was 1 Bulk IN and 1 Bulk OUT on Titanium/TI-84 Plus, 64 bytes)
When a TI-84 Plus is [[TI-84 Plus Emulation|emulated]] by the TI-Nspire, the descriptors are the same as a real TI-84 Plus except:
Device Descriptor:
idProduct E004h // Titanium!
bcdDevice 0200h // 2.00 (Real TI-84 Plus: 1.10)
iProduct       // "TI-84 Plus Silver Edition (Emulation)"
Configuration Descriptor: // Same as the real TI-84 Plus
bmAttributes   C0h // Self Powered
bMaxPower   00h // 0 mA
Interface and enpoint descriptors: same as the TI-84 Plus (1 Bulk IN , 1 Bulk OUT)


==Introduction==
==90000000 - General Purpose I/O (GPIO)==
We will call '''host''' the participant of the communication which is the USB host, i.e. the computer for a transfer between a computer and a TI-Nspire. <span style="color: IndianRed">The host of a transfer between two TI-Nspires is probably also the USB host, determined with the Host Negotiation Protocol of [http://en.wikipedia.org/wiki/USB_OTG USB On-The-Go]</span>. The communication model of the TI-Nspire seems to allow multiple devices to communicate simultaneously with the same host, through not yet released [http://www.ti-nspire.com/tools/nspire/resources/connect_class.html USB hubs], similar to [http://education.ti.com/educationportal/sites/US/productDetail/us_ti_navigator.html TI-Navigator] available for former calculator models. The TI-Nspire and the computer thus have each a dynamically assigned '''address''' used to identify the source and destination of a packet. A message sent from a source host/device to a destination host/device will be called a '''packet''' in the rest of this documentation. It is actually a protocol packet which may be transparently split into several USB packets by the USB device and host stacks if its length is greater or equal than the maximum USB packet size supported by the TI-Nspire (64 bytes). It seems that a protocol packet does not need to end at an USB packet boundary, but because of the sequencial nature of the exchanges, this feature is useless.


Packets are exchanged between '''services''' of the host and the device. A service is a software module which produce and interpret a subset of packet types. A service is identified by a two bytes identifier. Each packet contains both the source and destination service identifiers. A service of a participant sending a packet choose the target service it wants to talk with. Service IDs are similar to TCP ports, except that multiple source and destination services are used during the same session (more specifically for acknowledgment) as we will see.
See [[GPIO Pins]]


We will use further in the documentation notations of the form: <tt>6400:8001->6401:4060</tt> where 6400 is here the source address, 8001 the source service, 6401 the destination address and 4060 the destination service.
==90010000 - Fast timer==


After a connection reset (described further) and once a device has been declared to the host, transfers are initiated by the host and have this form (each line represents a packet):
The same interface as 900C0000/900D0000, but runs at the speed of the APB clock (22.5MHz) rather than 32kHz.
Host: Request
Device: Acknowledgment
Device: Response
Host: Acknowledgment
What could be called a "functional request" (for example "transfer a file") may use several exchanges of this type. The host and the device have stateful sessions and can keep track of the current state between these exchanges (for example when listing the content of a directory, which requires one pair of request/response for each file, the device keeps track of the current file).


==Packet format==
From my tests, it seems every timer can be turned into a 32kHZ timer by setting the 0x80 register to 0xA.<br>
Packets send by a host or a device have the same format. A packet has a 16 bytes header and may have an optional data part of variable length.
Only tested on CX CR4, needs further testing whether this works on every hardware model.<br>
54 FD SA SA SS SS DA DA DS DS DC DC SZ AK SQ CK [data part] (data less than 255 bytes in size)
Also test if you can turn all timers fast by writing 0 to the register, or if there are different clock speed configurations.<br>
54 FD SA SA SS SS DA DA DS DS DC DC FF AK SQ CK SZ SZ SZ SZ [data part] (data more than 254 bytes in size)
- nspiredev500
The different fields of the header part are:
*<tt>54 FD</tt>: constant
*<tt>SA SA</tt>: source address
*<tt>SS SS</tt>: source service ID
*<tt>DA DA</tt>: destination address
*<tt>DS DS</tt>: destination service ID
*<tt>DC DC</tt>: checksum of the data part
*<tt>SZ</tt>: size of the data part
*<tt>AK</tt>: used for acknowledgment packets, 00 for other packets.
*<tt>SQ</tt>: sequence number
*<tt>CK</tt>: checksum of the header: the sum of the preceding bytes modulo 256
Here is additional information for the fields not obvious and not described before.


===Service identifiers===
A [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/Babehiha.html SP804].
The host which always initiate the transfers (except address assignment during described further) chooses the service ID it uses for standard (not acknowledgment) packets. It will be the source service ID that appears in the packets sent to the device, and the destination service ID of the responses of the device. Any non-standard service ID may be chosen. Computer link Software uses service ID greater or equal than 0x8001. The service ID must be chosen before starting to exchange packets with a new service of the device. When using another service of the device, the host must disconnect itself from the previous service (this process is described further), and choose a new local service ID for the subsequent packets for the new target service. Each time a new host service ID is chosen, it ''must'' be different that the previous ones. The device won't answer to packets with a source service ID which matches a host service which has previously asked to disconnect itself. The same service IDs can be reused only once the connection with the device is reset. At each generation Computer Link Software increments by one the service ID to ensures unique generation, but this is actually not mandatory.


The identifiers (in hexadecimal) of the currently known standard services on the device side are:
==90020000 - Serial UART==
*<tt>00D3</tt>: nACK packet - destination service not available
*<tt>00FE</tt>, <tt>00FF</tt>: packet reception acknowledgment
*<tt>4001</tt>: null <span style="color: IndianRed">(?)</span>
*<tt>4002</tt>: echo
*<tt>4003</tt>: device address request
*<tt>4004</tt>: service tuning <span style="color: IndianRed">(?)</span>
*<tt>4020</tt>: device information
*<tt>4021</tt>: screen capture
*<tt>4022</tt>: event <span style="color: IndianRed">(?)</span>
*<tt>4023</tt>: shutdown <span style="color: IndianRed">(?)</span>
*<tt>4024</tt>: screen capture with RLE
*<tt>4041</tt>: service activity <span style="color: IndianRed">(?)</span>
*<tt>4042</tt>: TE_MLPDEV <span style="color: IndianRed">(?)</span>
*<tt>4043</tt>: TE_RPC <span style="color: IndianRed">(?)</span> (not yet enabled in the OS)
*<tt>4050</tt>: login
*<tt>4051</tt>: message <span style="color: IndianRed">(?)</span>
*<tt>4054</tt>: hub connection <span style="color: IndianRed">(?)</span>
*<tt>4060</tt>: file management (sync service)
*<tt>4080</tt>: OS installation
*<tt>5000</tt>: EXTECHO <span style="color: IndianRed">(?)</span>
*<span style="color: IndianRed">To be completed</span>


The identifiers of the services on the host side are:
[http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf PL011].
*<tt>00FE</tt>, <tt>00FF</tt>: packet reception acknowledgment
*<tt>4003</tt>: device address assignment
*<tt>40DE</tt>: service disconnect
*<span style="color: IndianRed">To be completed</span>


===Sequence number===
==90030000 - Unknown==
<span style="color: IndianRed">Sequence numbers are solely used for proper acknowledgment of packets</span>. Each participant manages itself the generation of the sequence numbers for the packets it sends (a communication between a computer and a TI-Nspire brings into play two sequences). Each packet (except acknowledgment packets, see further, and except in the case of an overflow) has it own sequence number. The number is incremented each time a packet has been acknowledged by other side (<span style="color: IndianRed">do they really need to be consecutive?</span>). The generation is common for all the services of a participant, i.e. two consecutive packets sent by/to different services will have consecutive sequence numbers. The sequence number has to be reinitialized to 1 after an address assignment; any other value will make transfer fail. The sequence number which follows 255 is 1, 0 is never used (<span style="color: IndianRed">is there really a reason for this or does it still work with 0?</span>).


===Acknowledgment===
Probably some kind of hash/crypto thing.
An acknowledgment packet from the TI-Nspire acknowledges only the ''reception'' of another packet, ''not'' the fact that the packet acknowledged has correctly been taken into account by its destination service. The TI-Nspire may even acknowledge packets with an incorrect header, for example with a bad header or data checksum, or with a duplicate sequence number.


Whether sent by the host or a device, an acknowledgment packet has '''0x00FF''' as source service ID, '''except''' :
==90040000 - SPI controller==
* when the sequence number of the acknowledge packet is zero, in which case the service ID '''0x00FE''' is used
* when the packet acknowledged contained an invalid destination service ID, in which case the service ID '''0x00D3''', which should be considered as an error
The destination service ID must be the source service ID of the previously received packet the participant acknowledges. The sequence number must be the same as the one of the packet acknowledged. The field <tt>AK</tt> of the header must contain '''0x0A'''. The 2 byte-long data part must contain the destination service ID of the packet acknowledged (i.e. a local service ID). Here is an example of an acknowledgment packet sent by a TI-Nspire to a computer:
6401:00FF->6400:8001 AK=0A SQ=02
data part: 40 60
Here the device acknowledges the reception of a packet sent by the service 8001 of the host, which had 02 as sequence number, and was sent to the service 4060 of the TI-Nspire.


The device replies to requests with an invalid destination service ID with packets similar to acknowledgement packets, but with a special source service ID : '''0x00D3'''.
A PL022 for communicating with the LCD panel controller, which is probably an ILI9341 or ILI9340.
Used on CX HW-W+ only.


===Data part checksum===
==90050000 - I2C controller==
The 2 byte-long checksum is more or less a CRC checksum. The checksum is 00 00 if there is no data part in the packet. Here is an implementation in [http://www.python.org Python] of the algorithm:
def checksum(data):
    acc = 0
    for byte in data:
        first = (ord(byte) << 8) | acc >> 8
        acc = acc & 0xFF
          second = (((acc & 0xF) << 4) ^ acc) << 8
        third = second >> 5
        acc = third >> 7
        acc = (acc ^ first ^ second ^ third) & 0xFFFF
    return acc
# A few examples
assert checksum('\x00\xFF') == 0xFF00
assert checksum('\x05\x00\x00') == 0x57AD
assert checksum('\x20\x00\x00\x00\x00\x00\x00\x00\x05\x01\x00') == 0xA095
===Data part===
The format and interpretation of the data part depends on the source and destination services for the packet, and on the current state of the exchange:


- multiple-bytes integers that appear in the data part (service identifiers in ack packets for instance) are in big endian (most significant byte first),
The Touchpad on the CX is accessed through this controller. See [[Keypads#Touchpad I²C]] for protocol details. It seems to be a Synopsys Designware I2C adapter.


- strings are terminated with a null byte (the examples shown in this documentation will always make the null byte appear to prevent from forgetting it). Sizes are expressed in bytes,
* 90050000 (R/W): Control register?
* 90050004 (?): ?
* 90050010 (R/W): Data/command register
* 90050014 (R/W): Speed divider for high period (standard speed) OS: 0x9c
* 90050018 (R/W): Speed divider for low period (standard speed) OS: 0xea
* 9005001c (R/W): Speed divider for high period (high speed) OS: 0x3b
* 90050020 (R/W): Speed divider for low period (high speed) OS: 0x2b
* 9005002c (R/W?): Interrupt status
* 90050030 (R/W): Interrupt mask
* 90050040 (R/W): Interrupt clear. Write 1 bits to clear
* 9005006c (R/W): Enable register
* 90050070 (R): Status register
* 90050074 (R?/W): TX FIFO?
* 90050078 (R?/W): RX FIFO?
* 900500f4 (?): ?
* 90050080 (?): ?


- blocks of pure data always start with a single ID byte (the command byte which is service dependent). When the ID byte is provided in a Request packet, the ID byte is repeated in the response Packet as first byte (even if data has to be split into several packets).
==90060000 - Watchdog timer==


Common packets with a data part are those which indicates the success or failure of the processing initiated by the previous request packet (or response packet in the case of a processing by the host). These packets should not be confused with packets [[#Acknowledgment|acknowledging the ''reception'']]: for example a request packet can be received successfully, but its data part can contain incorrect data - the device would here return an ACK packet and then a ''failure'' packet. These '''success''' and '''failure''' packets are 2 bytes long, starts with '''0xFF''' and are followed by '''0x00''' in case of success, or an error code in case of failure. The error code is not specific to a type of request (<span style="color: IndianRed">but is it specific to a service?</span>), some codes are reused when they have the same meaning (for example in the case of the [[#File management|file management service]]).
Possibly an [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0270b/index.html ARM SP805] or compatible. Runs at the APB clock frequency.


Note: if data to be sent/received is bigger than packet size, data has to be split into several packets.
==90090000 - Real-Time Clock (RTC)==


==Services==
Similar to the [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0224b/index.html ARM PrimeCell PL031], but interrupt registers are different.
Now that we have seen the common parts of the protocol, let's review the functions offered by each service. The descriptions of the various IN (from the device to the host) and OUT (from the host to the device) packets will be presented in this format (random values are used here):
OUT: 6400:8001->6401:4060
FF 00
In this example the service 0x8001 of the host whose address is 0x6400 sends to the service 0x4060 of the device with address 0x6401 the 2 byte-long sequence <tt>FF 00</tt> in the data part of the packet (which is a [[#Data part|success packet]]). The examples in the following sections will most of time use for common packets 0x6400 as host address, 0x6401 as device address and 0x8001 as generated host service ID. Values which are ''not'' example values will appear in bold. Multi-bytes fields in the data part of some packets which are not constant values will be surrounded with square brackets. If the field has a constant length, its length will appear just after the opening bracket. Fields with no specified length have a variable length.
[2 device address]: a 2 byte-long field containing the device address
[directory path] 00: a field of variable length containing the path as a null-terminated string
Mandatory IN and OUT acknowledgment packets will never be shown, only ''request'' and ''response'' packets will be described. Exchanges which don't fit in this type of description will be presented with enough details to fully understand their special features.


===Address assignment===
At least on HW-AA it's a standard PL031 with no registers changed.
Before starting any communication with the device, whether the host program has already been started and the device has just been plugged in, or the host program has just been started and the device was already plugged, the host must first:
#reset the connection
#assign an address to the device
The connection reset is mandatory because it forces the device to forget the [[#Service identifiers|identifiers of the host services]] and [[#Sequence number|sequence numbers]] used in the previous communication. Not resetting the connection may cause the reuse of these unique elements, and thus the absence of response to the host requests. A connection reset is triggered by issuing the [http://msdn2.microsoft.com/en-us/library/ms793191.aspx IOCTL_INTERNAL_USB_RESET_PORT] kernel-mode I/O request on Microsoft Windows.


Just after the reset, the device will spontaneously send an '''address request''' packet, with a sequence number set to 1:
* 90090000 (R): Current time, increments by 1 every second.
IN: '''0000:4003->0000:4003'''
* 90090004 (R/W): Alarm value. When the time passes this, interrupt becomes active.
The host must response with an '''address assignment''' packet. The sequence number of this paquet doesn't matter, Computer Link Software uses 1.
* 90090008 (R/W): Sets the value of 90090000 (clock will not read new time until a couple seconds later). Reads last value written.
OUT: 6400:'''4003'''->6401:'''4003'''
* 9009000C (R/W): Interrupt mask (1-bit)
[2 device address] FF 00
* 90090010 (R/W): Masked interrupt status, reads 1 if interrupt active and mask bit is set. Write 1 to acknowledge.
In this example, the address which appears in the data part of the packet would be 6401 (the same as the destination address in the header). Note that the host should use in the source address field of the header the address it has chosen for itself, and keep it for all the subsequent packets. Computer Link Software always choose 6400 as host address and assigns the address 6401 to the device (<span style="color: IndianRed">what if more than one TI-Nspire is plugged to the computer?</span>). The two bytes <tt>FF 00</tt> mean that the host accepts the address request.
* 90090014 (R): Status
** Bit 0: Time setting in progress
** Bit 1: Alarm setting in progress
** Bit 2: Interrupt acknowledgment in progress
** Bit 3: Interrupt mask setting in progress


In the special case of address assignment, the device will ''not'' send an acknowledgment packet for the address assignment packet.
==900A0000 - Miscellaneous==


The host can now use whatever device service he would like to. It has to choose before a [[#Service identifiers|service identifier]], and will do this before starting to use any service. Remember that an address assignment forces the sequence numbers of both host and device to reinitialize to 1 for the next packet sent by each.
* 900A0000 (R): ? 0x101
* 900A0004 (R/W): Set bit 0x20 to enable TI-84+ keypad link port. Other bits likely control functions of peripherals as well.
* 900A0008 (W): Write a 2 to cause a hardware reset
* 900A0028-900A002C (R): These registers together give a 64-bit number (28 is low, 2C is high) which comprises 56 data bits and 8 parity checking bits, allowing any single-bit error in it to be detected and corrected.
** Parity bit 0: Check of all data bits
** Parity bits 1, 2, 4, 8, 16, and 32: Checks of the data bits whose positions, expressed in binary, have that respective bit set.
** Data bits 3, 5-7, 9-15, 17-31, and 33-55: Serial number (middle part of the calculator's Product ID)
** Data bits 56-57: Unknown
** Data bits 58-62: "ASIC user flags"; must match the 80E0 field in an OS image. 01 = CAS, 00 = non-CAS, 03 = CM CAS, 02 = CM non-CAS.
** Parity bit 63: Check of parity bits 1, 2, 4, 8, 16, and 32.
* 900A0F04 (R/W): Unknown; Boot1 sets this to 0x1D


===Login request===
==900B0000 - Power management==


Starting at OS 1.2.xxxx, the NSpire attempts to connect to the LOGIN service just after address assignment:
* 900B0000 (R/W): [[Clock speed]] load value
* 900B0004 (R/W): 25-bit mask of which events may wake the hardware up from low-power mode.
** Bit 10: Unknown, probably the [[#90100000 - TI-84 Plus link port|TI-84 Plus link port]]
** Bit 12: [[#90090000 - Real-Time Clock (RTC)|RTC]] interrupt
** Bit 13: Unknown, probably ON key or USB activity
** Bit 17: Battery door open/close?
** Bit 23: Keypad remove/replace?
* 900B0008 (R/W): Reason for waking up from low-power mode. Write "1" bits to acknowledge.
* 900B000C (R/W): Clock speed control. Write 4 to set the clock speed according to the value in 900B0000. If interrupts are disabled the new clock speed will only become effective after exiting the program. Write 3A to enter low-power mode; this requires various peripherals to be prepared and probably works by stopping the clock.
* 900B0010 (R/W): ON interrupt mask (1-bit). 1 if ON interrupt should be serviced or 0 if not.
* 900B0014 (R/W): Bit 0 is set if ON interrupt is requested. Bit 1 also causes an interrupt, but the cause is unknown (and it is not masked by [900B0010]) - it is set after writing 4 to 900B000C. Write "1" bits to reset the requests.
* 900B0018 (R/W): Disable bus access to peripherals. Reads will just return the last word read from anywhere in the address range, and writes will be ignored.
** Bit 4: [[#C4000000 - Analog-to-Digital Converter (ADC)]]
** Bit 5: [[#B0000000 - USB OTG controller]]
** Bit 6: [[#B4000000 - USB HOST controller]]
** Bit 7: [[#B8010000 - SRAM Controller]]
** Bit 10: [[#CC000000 - SHA-256 hash generator]]
** Bit 11: [[#900C0000 - First timer]]
** Bit 12: [[#900D0000 - Second timer]]
** Bit 13: [[#90060000 - Watchdog timer]]
** Bit 17: [[#90020000 - Serial UART]]
** Bit 22: [[#90110000_-_LED]]?
* 900B0020 (R/W): ? - Possibly another peripheral bus access disable register.
* 900B0024 (R): Reads current clock speed value (see 900B0000 for details)
* 900B0028 (R): Bit 4 (0x10) clear when ON key pressed


IN: 6401:8013->6400:'''4050'''
==900C0000 - First timer==
  02 00 00 00 00 00


and the computer simply replies that service is not available:
A [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/Babehiha.html SP804].


OUT: 6400:'''00d3'''->6401:8013
==900D0000 - Second timer==
  40 50


From OS 1.4.xxxx, the Nspire adds disconnection from service. So, we have more packets:
A [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/Babehiha.html SP804].


IN: 6401:40de->6400:4050
==900E0000 - Keypad controller==
  80 00


OUT: 6400:00ff->6401:8000
See also [[Keypads]] for information about the keypads themselves.
  40 50


Please note that hand-held request LOGIN connection three seconds after device reset. If your program is designed as one thread listening on all ports (sequential, like TiLP), you have to take this into account. Otherwise, you will get spurious LOGIN request at any time during transfer.
* 900E0000 (R/W):
** Bits 0-1: Scan mode
*** Mode 0: Idle.
*** Mode 1: Indiscriminate key detection. Data registers are not updated, but whenever any key is pressed, interrupt bit 2 is set (and cannot be cleared until the key is released).
*** Mode 2: Single scan. The keypad is scanned once, and then the mode returns to 0.
*** Mode 3: Continuous scan. When scanning completes, it just starts over again after a delay.
** Bits 2-15: Number of APB cycles to wait before scanning each row
** Bits 16-31: Number of APB cycles to wait between scans
* 900E0004 (R/W):
** Bits 0-7: Number of rows to read (later rows are not updated in 900E0010-900E002F, and just read as whatever they were before being disabled)
** Bits 8-15: Number of columns to read (later column bits in a row are set to 1 when it is updated)
* 900E0008 (R/W): Keypad interrupt status/acknowledge (3-bit). Write "1" bits to acknowledge.
** Bit 0: Keypad scan complete
** Bit 1: Keypad data register changed
** Bit 2: Key pressed in mode 1
* 900E000C (R/W): Keypad interrupt mask (3-bit). Set each bit to 1 if the corresponding event in [900E0008] should cause an interrupt.
* 900E0010-900E002F (R): Keypad data, one halfword per row.
* 900E0030-900E003F (R/W): Keypad GPIOs. Each register is 20 bits, with one bit per GPIO. The role of each register is unknown.
* 900E0040 (R/W): Interrupt enable. Bits unknown but seems to be related to touchpad. Causes interrupt on touchpad touched.
* 900E0044 (R/W): Interrupt status. Bits unknown. Write 1s to acknowledge.
* 900E0048 (R/W): Unknown


If your program is designed as a real daemon launching one thread per port (parallel), you don't have to be bothered by this.
==900F0000 - HDQ/1-Wire and LCD contrast==


===Device Information===
The HDQ/1-Wire registers resemble those on the TI OMAP processors, and are possibly used to communicate with the wireless cradle. There is no conceivable reason for the LCD contrast register to be part of the same module, but here it is. :-(
To request Device Information:


OUT: XX
* 900F0004 (W): Transmitted data
where XX is the command byte; current values are:
* 900F0008 (R): Received data
01 -> serial number
* 900F000C (R/W): Control/status
02 -> device name
* 900F0010 (R): Interrupt status (automatically acknowledged when read)
03 -> list of supported file extensions
* 900F0020 (R/W): LCD contrast/backlight. Valid range for contrast: 0x11a to 0x1ce; normal value is 0x174. However, it can range from 0x100 (backlight off) to about 0x1d0 (about max brightness).


The response to 01 is:
==90110000 - LED==
IN: 01 raw data


Raw data contents:
* 90110B00 (R/W): Control register
@00d (8 bytes): FLASH free
** Bit 0: Set this bit to enable green light blink data. If green blink data iteration is not on, the green light state is read from bit 0 of green blink data.
@08d (8 bytes): FLASH physical
** Bit 1: Set this bit and bit 6 to enable green blink data iteration.
@16d (8 bytes): RAM free
** Bit 2: Set this bit to force green light off. Overrides bit 4.
@24d (8 bytes): RAM physical
** Bit 3: Set this bit to force red light off. Overrides bits 5 and 13.
--
** Bit 4: Set this bit to force green light on.
@32d (1 byte): battery level - FF=unknown, 00=powered, 01=low, 7F=OK
** Bit 5: Set this bit to force red light on.
@33d (2 bytes): 1 if charging, else 0
** Bit 6: See this bit and bit 1 to enable green blink data iteration. Reset before modifying green blink data or delay.
@35d (1 byte): clock speed in Mhz
** Bit 9: Set this bit to enable red light blink data. If red blink data iteration is not on, the red light state is read from bit 0 of red blink data.
--
** Bit 10: Set this bit and bit 12 to enable red blink data iteration.
@36d (4 bytes): product version (X.Y.ZZZZ) stored as XX YY ZZ ZZ
** Bit 12: Set this bit and bit 10 to enable red blink data iteration. Reset before modifying red blink data or delay.
@40d (4 bytes): same for boot1 version
** Bit 13: Forces red light on if bit 4 is 0, or red light off if bit 4 is 1. (?)
@44d (4 bytes): same for boot2 version
* 90110B04 (R/W): Green blink data. 32 bits of on and off state, represented by 1 and 0. Iteration is done from bit 31 to bit 0 repeatedly.
--
* 90110B08 (R/W): Green blink delay (negative). OS sets this to -2048.
@48d (4 bytes): hardware version - 1 if TI-Nspire CAS, 0 if TI-Nspire
* 90110B0C (R/W): Red blink data. 32 bits of on and off state, represented by 1 and 0. Iteration is done from bit 31 to bit 0 repeatedly.
@52d (2 bytes): runLevel - 1 for boot code (for example in recovery mode), 2 for OS
* 90110B10 (R/W): Red blink delay (negative). OS sets this to -2048.
--
@54d (2 bytes): LCD x
@56d (2 bytes): LCD y
@58d (2 bytes): LCD w
@60d (2 bytes): LCD h
@62d (1 byte): 4 bits per pixel
@63d (1 byte): sample model (always 0 which means [http://en.wikipedia.org/wiki/Packed_pixel packed])
--
@64d (1 byte): device - 0E if TI-Nspire CAS, 1E if TI-Nspire
--
@65d (17 bytes): a part of the Electronic Id (16 digits) stored as a null-terminated string (the first two digits and the last 8 ones are missing)
@82d (27 bytes): the full Electronic Id (26 digits) stored as a null-terminated string


The response to 02 is:
Note: If red and green lights are on at the same time, the color becomes yellow.
IN: 02 T I - N S p i r e 00


The response to 03 is:
==A4000000 - Internal SRAM==
IN: 03 . t n s 00 . t n o 00


The first string is the file extension and the second one is the OS extension.
0x20000 bytes SRAM, managed by the controller at 0xB8000000.


===Service disconnection===
==B0000000 - USB OTG controller==
Nothing special needs to be sent by the host to connect to a service of a device before using it. Simply using the correct destination service ID in the request packets it sends is enough.


Once the host has started to use a device service, it needs to disconnect from the current service before using a different service. The request is:
The OTG controller on all models is a ChipIdea-based dual-role USB controller. It only supports full speed communications so the PFSC bit (bit 24) must be set in the PORTSC register when in host mode. Otherwise, it'll attempt to connect at high speed for devices that support it and will never succeed in enumerating them.
OUT: 6400:'''40DE'''->6401:[id of the device service from which to disconnect]
[id of the host service which was used until then to communicate with the device service]
For example if the host uses the device service 4060 with the generated host service ID 8001 and wants to disconnect from it:
(... The host uses the service. Some requests with the header:
  OUT: 6400:8001->6401:4060
...)
OUT: 6400:40DE->6401:4060
8001
Note that Computer Link Software disconnects very often from the services it uses, even between requests to the same service (for example between a directory listing and a file attributes request to the file management service). This is not necessary.


===File management===
Documentation can be found in the [http://www.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf IMX233 reference manual].
The data part of the packets exchanged with the file management service of the TI-Nspire contains either a success or failure code (see the section on the [[#Data part|data part]]), or a structure specific to each command. For the latter, the first byte is the command byte; current values are:
The host interface is, again, based on EHCI; but the register defaults are different. The addresses have been adjusted from the ones contained in the IMX233 reference manual.


03: put file
* Module identification registers
04: ok to put/get file
** B0000000: HW_USBCTRL_ID - default 0xE241FA05
05: file contents
** B0000004: HW_USBCTRL_HWGENERAL - default 0x00000015
07: get file
** B0000008: HW_USBCTRL_HWHOST - default 0x10020001
0a: create folder
** B000000C: HW_USBCTRL_HWDEVICE - default 0x0000000B
0b: delete folder
** B0000010: HW_USBCTRL_HWTXBUF - default 0x40060910
0d: start dirlist
** B0000014: HW_USBCTRL_HWRXBUF - default 0x00000710
0e: get next dirlist entry
* Capability registers
0f: stop dirlist
** B0000100: HW_USBCTRL_CAPLENGTH - default 0x01000040
10: directory list entry
** B0000104: HW_USBCTRL_HCSPARAMS - default 0x00010011
20: get directory or file attributes
** B0000108: HW_USBCTRL_HCCPARAMS - default 0x00000006
** B0000120: HW_USBCTRL_DCIVERSION - default 0x00000001
** B0000124: HW_USBCTRL_DCCPARAMS - default 0x00000185 (host-capable, device-capable, 5 endpoints)
* Operational registers
** B0000140: HW_USBCTRL_USBCMD - default 0x00080B00 in host mode, 0x00080000 in device mode
** B0000144: HW_USBCTRL_USBSTS - default 0x00001000 in host mode, 0x00000000 in device mode
** B0000148: HW_USBCTRL_USBINTR - default 0x00000000
** B000014C: HW_USBCTRL_FRINDEX - default 0x00000000
** B0000154: (in host mode) HW_USBCTRL_PERIODICLISTBASE - default 0x00000000
** B0000154: (in device mode) HW_USBCTRL_DEVICEADDR - default 0x00000000
** B0000158: (in host mode) HW_USBCTRL_ASYNCLISTADDR - default 0x00000000
** B0000158: (in device mode) HW_USBCTRL_ENDPOINTLISTADDR - default 0x00000000
** B000015C: HW_USBCTRL_TTCTRL - default 0x00000000
** B0000160: HW_USBCTRL_BURSTSIZE - default 0x00001010
** B0000164: HW_USBCTRL_TXFILLTUNING - default 0x000000000
** B000016C: HW_USBCTRL_IC_USB - default 0x00000000
** B0000170: HW_USBCTRL_ULPI - default 0x00000000
** B0000178: HW_USBCTRL_ENDPTNAK - default 0x00000000
** B000017C: HW_USBCTRL_ENDPTNAKEN - default 0x00000000
** B0000184: HW_USBCTRL_PORTSC1 - default 0x10000000
** B00001A4: HW_USBCTRL_OTGSC - default 0x00000120
** B00001A8: HW_USBCTRL_USBMODE - default 0x00000000
** B00001AC: HW_USBCTRL_ENDPTSETUPSTAT - default 0x00000000
** B00001B0: HW_USBCTRL_ENDPTPRIME - default 0x00000000
** B00001B4: HW_USBCTRL_ENDPTFLUSH - default 0x00000000
** B00001B8: HW_USBCTRL_ENDPTSTAT - default 0x00000000
** B00001BC: HW_USBCTRL_ENDPTCOMPLETE - default 0x00000000
** B00001C0: HW_USBCTRL_ENDPTCTRL0 - default 0x00100010
** B00001C4: HW_USBCTRL_ENDPTCTRL1 - default 0x00000000
** B00001C8: HW_USBCTRL_ENDPTCTRL2 - default 0x00000000
** B00001CC: HW_USBCTRL_ENDPTCTRL3 - default 0x00000000
** B00001D0: HW_USBCTRL_ENDPTCTRL4 - default 0x00000000


We will use the names given by Computer Link Software to the different commands.
===Role switching===


Note: NSpire uses UTF-8 to encode directory and file names. <span style="color: IndianRed">Is there any size limit for directory/file names?</span>
During role switching some GPIO output registers are modified.


====Directory listing====
* GPIO2:
Listing the content of a directory requires multiple sets of requests and responses. A typical sequence would be:
** Active low.
OUT: DirEnumInit
** Controls VBUS/pull-up (drives VBUS to 5v for host mode)
IN: Success/Failure
OUT: DirEnumNext
IN: Directory or file info
OUT: DirEnumNext
...
IN: No more directory or file
OUT: DirEnumDone
IN: Success
Only the data part of the different packets will be shown in the following descriptions.


=====DirEnumInit=====
* USB-B: GPIO6
Initiates a directory listing.
** Active low.
OUT: 0D [>=8 directory name] 00
** Probably controls charging from USB
''Directory name'' is the name of the directory to list, with or without leading and/or trailing slash. It can be "/" get a list of the different directories on the TI-Nspire. The TI-Nspire only supports one level of directories. The name must be at least 8 characters long, padded with null characters if needed. The response is one of:
IN:
- FF 00: success
- FF 0A: the directory doesn't exist
- FF 0F: invalid directory name


=====DirEnumNext=====
==B4000000 - USB HOST controller==
Get information about the next file in the directory being listed, if there are any more.
OUT: 0E
If information about the next file or directory can be returned, the response is:
IN: 10 00 [1 data part size - 3] [name of the directory or the file] 00 [4 size of the file] [4 date?] [1 directory flag] 00
File names have the suffix ''.tns''. "''data part size - 3''" is the size of the file information structure without the 3 header bytes. The size of a directory is always 0. The meaning of the date is currently not very clear (<span style="color: IndianRed">more to come</span>). "''directory flag''" is 00 for a file, and 01 for a directory.


Else the response is <tt>FF XX</tt>, where <tt>XX</tt> is 11 if there are no more file or directory in the list, or 10 if we are not currently listing a directory or if the previous ''DirEnumInit'' failed.
Same port structure as B0000000.


=====DirEnumDone=====
==B8001000 - SRAM Controller==
<span style="color: IndianRed">Probably needed before trying to list another directory.</span>
OUT: 0F
IN: FF 00


====Directory and file attributes====
A [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0380g/DDI0380G_smc_pl350_series_r2p1_trm.pdf PL352] r1p2.
This command is returns the attributes of a directory or a file:
OUT: 20 01 [>=8 directory or file path] 00
IN: 20 [4 size, 0 for a directory] [4 date] [00 if file, 01 if directory] [1 flags(?): always 00]
The directory or file path must be at least 8 characters long, padded with null characters if needed. <tt>FF 0A</tt> is returned by the device if the path does not exist.


(<span style="color: IndianRed">TODO: clarify this point</span>) <tt>date</tt> is the date of the file. It changes each time the file is saved. It could be the age of the file in seconds (but what would be a date of 0, and how does the TI-Nspire track this?)
==C0000000 - LCD controller==


If the file or directory does not exist, the TI-Nspire sends:
A [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0293c/index.html PL111].
IN: FF 0A


====Sending a file====
==C4000000 - Analog-to-Digital Converter (ADC)==
The command ''PutFile'' should be issued, then the content of the file split into as many packets as needed.
OUT: 03 01 [>=8 file path] 00 [4 file size]
''File path'' is the full path to the file to create on the device. The target directory should already exist. The directory name may have a leading slash. The file name must be terminated by the extension ''".tns"''. An example could be ''"/Examples/myfile.tns"''. ''File size'' can be 0 for an empty file  (although empty files couldn't be opened by the TI-Nspire after reception).


The device response is <tt>04</tt> if it is ready to receive the file content, <tt>FF 14</tt> if the file path is invalid, <tt>FF 15</tt> if the file path doesn't have a ''".tns"'' extension:
Used to check various voltages. Channels 1 ("VBATT"), 2 ("VSYS"), and 4 ("B12") are used to check the battery status; channel 3 is used to determine which keypad is in use.


IN: 04
* C4000000 (R): Masked interrupt status (4 bits per channel: bits 0-3 are for channel 0, etc)
* C4000004 (R/W): Raw interrupt status, write 1 bits to acknowledge
* C4000008 (R/W): Interrupt enable register
* C4000100-C40001DF: Per-channel registers (channel 0 starts at C4000100, channel 1 at C4000120, etc.)
** +00 (R/W): Set bit 0 to start measurement; interrupt status bits 0 and 1 will be set when complete and the value will be stored in +10 register. Other commands do exist, including some that write to memory.
** +04 (R/W): Unknown (28 bits)
** +08 (R/W): Number of halfwords to write (25 bits)
** +0C (R/W): Base address (word-aligned)
** +10 (R): Read measured voltage. Scale for channels 1 and 2 is 155 units = 1 volt; scale for other channels is 310 units = 1 volt
** +14 (R/W): Speed (10 bits, set to AHB clock speed / 40000)


The file content is then split into 253 byte-long chunks (since the maximum length of the data part is 254 bytes, and since the data part starts with a command byte). The last packet must be less than 253 bytes long. If the file is zero bytes long, nothing is sent by the host.
==C8010000 - Triple DES encryption==
OUT: 05 [253 file content chunk #1]
OUT: 05 [253 file content chunk #2]
...
OUT: 05 [<253 last file content chunk]
The device response is <tt>FF 00</tt> if the file has been correctly received, <tt>FF 09</tt> if the parent folder doesn't not exist: the file has not been created. The device does send a response if the host was transmitting an empty file.


IN: FF 00
Implements the [http://en.wikipedia.org/wiki/Triple_DES Triple DES encryption algorithm].


====Creating a directory====
* C8010000 (R/W): Right half of block
Request:
* C8010004 (R/W): Left half of block. Writing this causes the block to be encrypted/decrypted.
OUT: 0A 03 [>=8 directory path] 00
* C8010008 (R/W): Right 32 bits of key 1
* C801000C (R/W):
** Bits 0-23: Left 24 bits of key 1
** Bit 30: Set to 0 to encrypt, 1 to decrypt
* C8010010 (R/W): Right 32 bits of key 2
* C8010014 (R/W): Left 24 bits of key 2
* C8010018 (R/W): Right 32 bits of key 3
* C801001C (R/W): Left 24 bits of key 3


Acknowledgement:
==CC000000 - SHA-256 hash generator==
IN: FF 00


====Receiving a file====
Implements the [http://en.wikipedia.org/wiki/SHA_hash_functions SHA-256 hash algorithm], which is used in cryptographic signatures.
The command ''GetFile'' should be issued, then the content of the file split into as many packets as needed.


OUT: 07 01 [>=8 file path] 00
* CC000000 (R): Busy if bit 0 set
* CC000000 (W): Write 0x10 and then 0x0 to initialize. Write 0xA to process first block, 0xE to process subsequent blocks
* CC000008 (R/W): Some sort of bus write-allow register? If a bit is set, it allows R/W access to the registers of the peripheral, if clear, R/O access only. Don't know what it's doing here, but it's here anyway.
** Bit 8: [[#CC000000 - SHA-256 hash generator]]
** Bit 10: ?
* CC000010-CC00004F (R/W): 512-bit block
* CC000060-CC00007F (R): 256-bit state


''File path'' is the full path to the file to retrieve on the device. The target directory should already exist. The directory name may have a leading slash. The file name must be terminated by the extension "''.tns''". An example could be "''/Examples/myfile.tns''".
==DC000000 - Interrupt controller==
 
See [[Interrupts]]. The controller is a [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0181e/index.html PL190].
The NSpire send size of file:
 
IN: 03 01 [9 00] [4 size of file]
 
The device response is 04 if it is ready to receive the file content, FF 0A if the path does not exist.
 
OUT: 04
 
The file contents is then split into 253 byte-long chunks (since the maximum length of the data part is 254 bytes, and since the data part starts with a command byte). The last packet must be less than 253 bytes long. If the file is zero bytes long, nothing is sent by the host.
 
IN: 05 [253 file content chunk #1]
IN: 05 [253 file content chunk #2]
...
IN: 05 [<253 last file content chunk]
 
Please note that data contents is the same as file contents (i.e. a set of XML files compressed with PK-ZIP).
 
To finish, computer send a final acknowledgment:
 
OUT: FF 00
 
====Deleting a file====
Request:
OUT: 09 01 [>=8 file path] 00
The constraints on ''file path'' are the same as those described in [[#Sending_a_file|Sending a file]].
 
Acknowledgement:
IN: FF 00
 
====Deleting a directory====
Request:
OUT: 0B 03 [>=8 directory path] 00
 
Acknowledgement:
IN: FF 00
If the directory is not empty, the files it contains are also deleted.
 
====Renaming a file or directory====
Request:
OUT: 21 01 [>=8 initial file path] [>=9 new file path]
The constraints on the file pathes are the same as those described in [[#Sending_a_file|Sending a file]].
 
Acknowledgement:
IN: FF 00
 
====Copying a file====
Request:
OUT: 0C 01 [>=8 initial file path] [>=9 new file path]
 
Acknowledgement:
IN: FF 00
(<span style="color: IndianRed">TODO: possible error codes</span>)
 
To copy a directory, the target directory must be created, the source directory must be listed, and each file must be copied independently.
 
===Screenshot (RLE)===
To request a screenshot:
OUT: 00
 
The first response is:
IN: 01 raw data
 
where raw data contents is:
@00d (4 bytes): RLE raw data size
@04d (2 bytes): y (?) - always 0
@06d (2 bytes): x (?) - always 0
@08d (2 bytes): LCD width in pixels (0140 = 320 pixels)
@10d (2 bytes): LCD height in pixels (00F0 = 240 pixels)
@12d (1 byte): bits per pixel (4)
@13d (1 byte): sample model - always 0 which means [http://en.wikipedia.org/wiki/Packed_pixel packed]
 
The RLE raw data is then split into as much 270 bytes-long packets (254 bytes long for the data part) as needed. The last packet will be shorter than 270 bytes.
IN: 02 [253 RLE raw data]
where ''raw data'' is the screenshot encoded with an implementation of Run Length Encoding ([http://en.wikipedia.org/wiki/Run-length_encoding RLE]) described below. The encoding is applied to the screenshot ''before'' it is split into packets.
 
The encoded stream is made of sequences of blocks on the same pattern as <tt>LL DD DD DD  ... DD</tt>. The first byte ''LL'' is a signed byte representing a length:
* if it is equal to or greater than zero, then it is the length of the next "run" minus one. The next byte is the value to repeat. For instance <tt>FF FF FF FF FF</tt> would be encoded as <tt>04 FF</tt>. Note that if a run is longer than the maximum length which could be encoded like this (128), then run is divided into sub-runs with a length equal or lower than 128 (for instance <tt>7F 01 7F 01 03 01</tt> represents a run of 128 + 128 + 4 = 260 times the byte 01).
* if it is lower than zero, then it is <tt>-(L - 1)</tt>, where ''L'' is the length (greater than zero) of a sequence not encoded which follows. This is used for sequences of isolated values for which the RLE encoded version would take more space than the original one. For instance <tt>01 03 04 06</tt> could be encoded as <tt>FD 01 03 04 06</tt> (<tt>FD</tt> is the signed byte -3).
 
In the RLE-decoded stream, each pixel is coded with a 4 bit gray scale (16 colors), where <tt>0b000</tt> is black and <tt>0b1111</tt> is white.
 
===OS installation===
 
To send an OS:
 
OUT: 03 [4 size of OS]
IN : 04 (*)
OUT: 05 [253 OS file contents]
IN:  FF 00 (once)
OUT: 05 [253 file contents chunk #2]
...
OUT: 05 [<253 last file contents chunk]
 
(*) if NSpire rejects OS, it sends 02 00 00 00 00 00.
 
Next, the NSpire continuously send progress bar value (0..64h) until maximum value is reached (100d = 64h):
 
IN : 06 06 (  6%)
IN : 06 0B ( 11%)
...
IN : 06 64 (100%)
 
If OS can not be installed, NSpire will reply with:
 
IN : 06 06
...
IN : 06 60
IN : FF 04
 
===Echo===
 
The echo service simply echoes any received data as follows:
 
OUT: raw data
IN: raw data
 
==Testing==
===Computer Link Software===
Computer Link Software's functions can be tested on the command line using the testing code embedded in the Java binding ''NavNet.jar'' for the low-level connector. <tt>TESTNUM</tt> is the number of the test to run (remove the echo at the beginning and the file redirection at the end the first time to understand how it works). The command line to use with [http://www.cygwin.com/ Cygwin] on Microsoft Windows is:
$ echo $TESTNUM | java -cp "C:\Program Files\TI Education\TI-Nspire Computer Link\lib\navnet.jar" com.ti.eps.navnet.main  >logs 2>&1
The logs of both the native NavNet connector and the Java testing program will be written to the output file. The verbosity of the native logs can be tuned in <tt>Main.class</tt>:
NavNet.init("-c X -d X -p connectors"); // X (initially 4) should be between 0 (no logs) and 5 (finest)
 
===USB traffic analysis===
<span style="color: IndianRed">Any suggestions of a ''free'' USB analyzer for Microsoft Windows?</span>
 
Tools:
 
- somewhat old (2002) but working on Windows9x/XP: [http://sourceforge.net/projects/usbsnoop/ SnoopyPro]
 
- another tool derivated from SniffUsb (free of use but not free software): [http://www.pcausa.com/Utilities/UsbSnoop/default.htm SniffUsb-2]
 
Unfortunately these tools don't seem to work on Windows Vista.
 
The TiLP team can provide you some tools to make traffic analysis more convenient:
 
- xml2hex which turns SnoopyPro log into hexadecimal log,
 
- OR log2hex which turns SniffUsb log into hexadecimal log,
 
- and hex2nsp which turns hexadecimal log into ready-to-read NSpire packet listing.
Both of them are available on the <[http://svn.tilp.info/cgi-bin/viewcvs.cgi/linkguide/trunk/analysis/ TiLP LinkGuide repository]>.
 
If you want to help, you can take a look at some NSpire <[http://svn.tilp.info/cgi-bin/viewcvs.cgi/linkguide/trunk/analysis/logs/nspire/ logs]>.
 
==TODO==
*Find the differences between PC/TI-Nspire transfers and TI-Nspire/TI-Nspire transfers.
*Test and document the [[#Service identifiers|services available]]

Revision as of 20:42, 25 June 2020

00000000 - Boot1 ROM

128kB of on-chip ROM.

10000000 - SDRAM

32 MiB SDRAM on CM or 64 MiB on CX. Managed by 0x8FFF0000.

8FFF0000 - SDRAM controller

A DMC-340 r1p0.

8FFF1000 - NAND controller

A PL351 r1p2.

90000000 - General Purpose I/O (GPIO)

See GPIO Pins

90010000 - Fast timer

The same interface as 900C0000/900D0000, but runs at the speed of the APB clock (22.5MHz) rather than 32kHz.

From my tests, it seems every timer can be turned into a 32kHZ timer by setting the 0x80 register to 0xA.
Only tested on CX CR4, needs further testing whether this works on every hardware model.
Also test if you can turn all timers fast by writing 0 to the register, or if there are different clock speed configurations.
- nspiredev500

A SP804.

90020000 - Serial UART

PL011.

90030000 - Unknown

Probably some kind of hash/crypto thing.

90040000 - SPI controller

A PL022 for communicating with the LCD panel controller, which is probably an ILI9341 or ILI9340. Used on CX HW-W+ only.

90050000 - I2C controller

The Touchpad on the CX is accessed through this controller. See Keypads#Touchpad I²C for protocol details. It seems to be a Synopsys Designware I2C adapter.

  • 90050000 (R/W): Control register?
  • 90050004 (?): ?
  • 90050010 (R/W): Data/command register
  • 90050014 (R/W): Speed divider for high period (standard speed) OS: 0x9c
  • 90050018 (R/W): Speed divider for low period (standard speed) OS: 0xea
  • 9005001c (R/W): Speed divider for high period (high speed) OS: 0x3b
  • 90050020 (R/W): Speed divider for low period (high speed) OS: 0x2b
  • 9005002c (R/W?): Interrupt status
  • 90050030 (R/W): Interrupt mask
  • 90050040 (R/W): Interrupt clear. Write 1 bits to clear
  • 9005006c (R/W): Enable register
  • 90050070 (R): Status register
  • 90050074 (R?/W): TX FIFO?
  • 90050078 (R?/W): RX FIFO?
  • 900500f4 (?): ?
  • 90050080 (?): ?

90060000 - Watchdog timer

Possibly an ARM SP805 or compatible. Runs at the APB clock frequency.

90090000 - Real-Time Clock (RTC)

Similar to the ARM PrimeCell PL031, but interrupt registers are different.

At least on HW-AA it's a standard PL031 with no registers changed.

  • 90090000 (R): Current time, increments by 1 every second.
  • 90090004 (R/W): Alarm value. When the time passes this, interrupt becomes active.
  • 90090008 (R/W): Sets the value of 90090000 (clock will not read new time until a couple seconds later). Reads last value written.
  • 9009000C (R/W): Interrupt mask (1-bit)
  • 90090010 (R/W): Masked interrupt status, reads 1 if interrupt active and mask bit is set. Write 1 to acknowledge.
  • 90090014 (R): Status
    • Bit 0: Time setting in progress
    • Bit 1: Alarm setting in progress
    • Bit 2: Interrupt acknowledgment in progress
    • Bit 3: Interrupt mask setting in progress

900A0000 - Miscellaneous

  • 900A0000 (R): ? 0x101
  • 900A0004 (R/W): Set bit 0x20 to enable TI-84+ keypad link port. Other bits likely control functions of peripherals as well.
  • 900A0008 (W): Write a 2 to cause a hardware reset
  • 900A0028-900A002C (R): These registers together give a 64-bit number (28 is low, 2C is high) which comprises 56 data bits and 8 parity checking bits, allowing any single-bit error in it to be detected and corrected.
    • Parity bit 0: Check of all data bits
    • Parity bits 1, 2, 4, 8, 16, and 32: Checks of the data bits whose positions, expressed in binary, have that respective bit set.
    • Data bits 3, 5-7, 9-15, 17-31, and 33-55: Serial number (middle part of the calculator's Product ID)
    • Data bits 56-57: Unknown
    • Data bits 58-62: "ASIC user flags"; must match the 80E0 field in an OS image. 01 = CAS, 00 = non-CAS, 03 = CM CAS, 02 = CM non-CAS.
    • Parity bit 63: Check of parity bits 1, 2, 4, 8, 16, and 32.
  • 900A0F04 (R/W): Unknown; Boot1 sets this to 0x1D

900B0000 - Power management

  • 900B0000 (R/W): Clock speed load value
  • 900B0004 (R/W): 25-bit mask of which events may wake the hardware up from low-power mode.
    • Bit 10: Unknown, probably the TI-84 Plus link port
    • Bit 12: RTC interrupt
    • Bit 13: Unknown, probably ON key or USB activity
    • Bit 17: Battery door open/close?
    • Bit 23: Keypad remove/replace?
  • 900B0008 (R/W): Reason for waking up from low-power mode. Write "1" bits to acknowledge.
  • 900B000C (R/W): Clock speed control. Write 4 to set the clock speed according to the value in 900B0000. If interrupts are disabled the new clock speed will only become effective after exiting the program. Write 3A to enter low-power mode; this requires various peripherals to be prepared and probably works by stopping the clock.
  • 900B0010 (R/W): ON interrupt mask (1-bit). 1 if ON interrupt should be serviced or 0 if not.
  • 900B0014 (R/W): Bit 0 is set if ON interrupt is requested. Bit 1 also causes an interrupt, but the cause is unknown (and it is not masked by [900B0010]) - it is set after writing 4 to 900B000C. Write "1" bits to reset the requests.
  • 900B0018 (R/W): Disable bus access to peripherals. Reads will just return the last word read from anywhere in the address range, and writes will be ignored.
  • 900B0020 (R/W): ? - Possibly another peripheral bus access disable register.
  • 900B0024 (R): Reads current clock speed value (see 900B0000 for details)
  • 900B0028 (R): Bit 4 (0x10) clear when ON key pressed

900C0000 - First timer

A SP804.

900D0000 - Second timer

A SP804.

900E0000 - Keypad controller

See also Keypads for information about the keypads themselves.

  • 900E0000 (R/W):
    • Bits 0-1: Scan mode
      • Mode 0: Idle.
      • Mode 1: Indiscriminate key detection. Data registers are not updated, but whenever any key is pressed, interrupt bit 2 is set (and cannot be cleared until the key is released).
      • Mode 2: Single scan. The keypad is scanned once, and then the mode returns to 0.
      • Mode 3: Continuous scan. When scanning completes, it just starts over again after a delay.
    • Bits 2-15: Number of APB cycles to wait before scanning each row
    • Bits 16-31: Number of APB cycles to wait between scans
  • 900E0004 (R/W):
    • Bits 0-7: Number of rows to read (later rows are not updated in 900E0010-900E002F, and just read as whatever they were before being disabled)
    • Bits 8-15: Number of columns to read (later column bits in a row are set to 1 when it is updated)
  • 900E0008 (R/W): Keypad interrupt status/acknowledge (3-bit). Write "1" bits to acknowledge.
    • Bit 0: Keypad scan complete
    • Bit 1: Keypad data register changed
    • Bit 2: Key pressed in mode 1
  • 900E000C (R/W): Keypad interrupt mask (3-bit). Set each bit to 1 if the corresponding event in [900E0008] should cause an interrupt.
  • 900E0010-900E002F (R): Keypad data, one halfword per row.
  • 900E0030-900E003F (R/W): Keypad GPIOs. Each register is 20 bits, with one bit per GPIO. The role of each register is unknown.
  • 900E0040 (R/W): Interrupt enable. Bits unknown but seems to be related to touchpad. Causes interrupt on touchpad touched.
  • 900E0044 (R/W): Interrupt status. Bits unknown. Write 1s to acknowledge.
  • 900E0048 (R/W): Unknown

900F0000 - HDQ/1-Wire and LCD contrast

The HDQ/1-Wire registers resemble those on the TI OMAP processors, and are possibly used to communicate with the wireless cradle. There is no conceivable reason for the LCD contrast register to be part of the same module, but here it is. :-(

  • 900F0004 (W): Transmitted data
  • 900F0008 (R): Received data
  • 900F000C (R/W): Control/status
  • 900F0010 (R): Interrupt status (automatically acknowledged when read)
  • 900F0020 (R/W): LCD contrast/backlight. Valid range for contrast: 0x11a to 0x1ce; normal value is 0x174. However, it can range from 0x100 (backlight off) to about 0x1d0 (about max brightness).

90110000 - LED

  • 90110B00 (R/W): Control register
    • Bit 0: Set this bit to enable green light blink data. If green blink data iteration is not on, the green light state is read from bit 0 of green blink data.
    • Bit 1: Set this bit and bit 6 to enable green blink data iteration.
    • Bit 2: Set this bit to force green light off. Overrides bit 4.
    • Bit 3: Set this bit to force red light off. Overrides bits 5 and 13.
    • Bit 4: Set this bit to force green light on.
    • Bit 5: Set this bit to force red light on.
    • Bit 6: See this bit and bit 1 to enable green blink data iteration. Reset before modifying green blink data or delay.
    • Bit 9: Set this bit to enable red light blink data. If red blink data iteration is not on, the red light state is read from bit 0 of red blink data.
    • Bit 10: Set this bit and bit 12 to enable red blink data iteration.
    • Bit 12: Set this bit and bit 10 to enable red blink data iteration. Reset before modifying red blink data or delay.
    • Bit 13: Forces red light on if bit 4 is 0, or red light off if bit 4 is 1. (?)
  • 90110B04 (R/W): Green blink data. 32 bits of on and off state, represented by 1 and 0. Iteration is done from bit 31 to bit 0 repeatedly.
  • 90110B08 (R/W): Green blink delay (negative). OS sets this to -2048.
  • 90110B0C (R/W): Red blink data. 32 bits of on and off state, represented by 1 and 0. Iteration is done from bit 31 to bit 0 repeatedly.
  • 90110B10 (R/W): Red blink delay (negative). OS sets this to -2048.

Note: If red and green lights are on at the same time, the color becomes yellow.

A4000000 - Internal SRAM

0x20000 bytes SRAM, managed by the controller at 0xB8000000.

B0000000 - USB OTG controller

The OTG controller on all models is a ChipIdea-based dual-role USB controller. It only supports full speed communications so the PFSC bit (bit 24) must be set in the PORTSC register when in host mode. Otherwise, it'll attempt to connect at high speed for devices that support it and will never succeed in enumerating them.

Documentation can be found in the IMX233 reference manual. The host interface is, again, based on EHCI; but the register defaults are different. The addresses have been adjusted from the ones contained in the IMX233 reference manual.

  • Module identification registers
    • B0000000: HW_USBCTRL_ID - default 0xE241FA05
    • B0000004: HW_USBCTRL_HWGENERAL - default 0x00000015
    • B0000008: HW_USBCTRL_HWHOST - default 0x10020001
    • B000000C: HW_USBCTRL_HWDEVICE - default 0x0000000B
    • B0000010: HW_USBCTRL_HWTXBUF - default 0x40060910
    • B0000014: HW_USBCTRL_HWRXBUF - default 0x00000710
  • Capability registers
    • B0000100: HW_USBCTRL_CAPLENGTH - default 0x01000040
    • B0000104: HW_USBCTRL_HCSPARAMS - default 0x00010011
    • B0000108: HW_USBCTRL_HCCPARAMS - default 0x00000006
    • B0000120: HW_USBCTRL_DCIVERSION - default 0x00000001
    • B0000124: HW_USBCTRL_DCCPARAMS - default 0x00000185 (host-capable, device-capable, 5 endpoints)
  • Operational registers
    • B0000140: HW_USBCTRL_USBCMD - default 0x00080B00 in host mode, 0x00080000 in device mode
    • B0000144: HW_USBCTRL_USBSTS - default 0x00001000 in host mode, 0x00000000 in device mode
    • B0000148: HW_USBCTRL_USBINTR - default 0x00000000
    • B000014C: HW_USBCTRL_FRINDEX - default 0x00000000
    • B0000154: (in host mode) HW_USBCTRL_PERIODICLISTBASE - default 0x00000000
    • B0000154: (in device mode) HW_USBCTRL_DEVICEADDR - default 0x00000000
    • B0000158: (in host mode) HW_USBCTRL_ASYNCLISTADDR - default 0x00000000
    • B0000158: (in device mode) HW_USBCTRL_ENDPOINTLISTADDR - default 0x00000000
    • B000015C: HW_USBCTRL_TTCTRL - default 0x00000000
    • B0000160: HW_USBCTRL_BURSTSIZE - default 0x00001010
    • B0000164: HW_USBCTRL_TXFILLTUNING - default 0x000000000
    • B000016C: HW_USBCTRL_IC_USB - default 0x00000000
    • B0000170: HW_USBCTRL_ULPI - default 0x00000000
    • B0000178: HW_USBCTRL_ENDPTNAK - default 0x00000000
    • B000017C: HW_USBCTRL_ENDPTNAKEN - default 0x00000000
    • B0000184: HW_USBCTRL_PORTSC1 - default 0x10000000
    • B00001A4: HW_USBCTRL_OTGSC - default 0x00000120
    • B00001A8: HW_USBCTRL_USBMODE - default 0x00000000
    • B00001AC: HW_USBCTRL_ENDPTSETUPSTAT - default 0x00000000
    • B00001B0: HW_USBCTRL_ENDPTPRIME - default 0x00000000
    • B00001B4: HW_USBCTRL_ENDPTFLUSH - default 0x00000000
    • B00001B8: HW_USBCTRL_ENDPTSTAT - default 0x00000000
    • B00001BC: HW_USBCTRL_ENDPTCOMPLETE - default 0x00000000
    • B00001C0: HW_USBCTRL_ENDPTCTRL0 - default 0x00100010
    • B00001C4: HW_USBCTRL_ENDPTCTRL1 - default 0x00000000
    • B00001C8: HW_USBCTRL_ENDPTCTRL2 - default 0x00000000
    • B00001CC: HW_USBCTRL_ENDPTCTRL3 - default 0x00000000
    • B00001D0: HW_USBCTRL_ENDPTCTRL4 - default 0x00000000

Role switching

During role switching some GPIO output registers are modified.

  • GPIO2:
    • Active low.
    • Controls VBUS/pull-up (drives VBUS to 5v for host mode)
  • USB-B: GPIO6
    • Active low.
    • Probably controls charging from USB

B4000000 - USB HOST controller

Same port structure as B0000000.

B8001000 - SRAM Controller

A PL352 r1p2.

C0000000 - LCD controller

A PL111.

C4000000 - Analog-to-Digital Converter (ADC)

Used to check various voltages. Channels 1 ("VBATT"), 2 ("VSYS"), and 4 ("B12") are used to check the battery status; channel 3 is used to determine which keypad is in use.

  • C4000000 (R): Masked interrupt status (4 bits per channel: bits 0-3 are for channel 0, etc)
  • C4000004 (R/W): Raw interrupt status, write 1 bits to acknowledge
  • C4000008 (R/W): Interrupt enable register
  • C4000100-C40001DF: Per-channel registers (channel 0 starts at C4000100, channel 1 at C4000120, etc.)
    • +00 (R/W): Set bit 0 to start measurement; interrupt status bits 0 and 1 will be set when complete and the value will be stored in +10 register. Other commands do exist, including some that write to memory.
    • +04 (R/W): Unknown (28 bits)
    • +08 (R/W): Number of halfwords to write (25 bits)
    • +0C (R/W): Base address (word-aligned)
    • +10 (R): Read measured voltage. Scale for channels 1 and 2 is 155 units = 1 volt; scale for other channels is 310 units = 1 volt
    • +14 (R/W): Speed (10 bits, set to AHB clock speed / 40000)

C8010000 - Triple DES encryption

Implements the Triple DES encryption algorithm.

  • C8010000 (R/W): Right half of block
  • C8010004 (R/W): Left half of block. Writing this causes the block to be encrypted/decrypted.
  • C8010008 (R/W): Right 32 bits of key 1
  • C801000C (R/W):
    • Bits 0-23: Left 24 bits of key 1
    • Bit 30: Set to 0 to encrypt, 1 to decrypt
  • C8010010 (R/W): Right 32 bits of key 2
  • C8010014 (R/W): Left 24 bits of key 2
  • C8010018 (R/W): Right 32 bits of key 3
  • C801001C (R/W): Left 24 bits of key 3

CC000000 - SHA-256 hash generator

Implements the SHA-256 hash algorithm, which is used in cryptographic signatures.

  • CC000000 (R): Busy if bit 0 set
  • CC000000 (W): Write 0x10 and then 0x0 to initialize. Write 0xA to process first block, 0xE to process subsequent blocks
  • CC000008 (R/W): Some sort of bus write-allow register? If a bit is set, it allows R/W access to the registers of the peripheral, if clear, R/O access only. Don't know what it's doing here, but it's here anyway.
  • CC000010-CC00004F (R/W): 512-bit block
  • CC000060-CC00007F (R): 256-bit state

DC000000 - Interrupt controller

See Interrupts. The controller is a PL190.