Syscalls and Memory-mapped I/O ports on CX II: Difference between pages

From Hackspire
(Difference between pages)
Jump to navigation Jump to search
(Fix errors and clarify utf-8)
 
(Add USB controller locations)
 
Line 1: Line 1:
Syscalls are OS functions exposed by Ndless to C and assembly programs. This article describes the syscalls currently available with Ndless 3.6.
Not all parts have been discovered and researched yet, so the information on this page is not complete.


Your help is needed to make this list grow to a full-fledged library. Try to find new syscalls, [[Ndless features and limitations#Syscalls|test them]] and share them for integration in Ndless.
==00000000 - Boot1 ROM==


==[http://en.wikipedia.org/wiki/C_standard_library C standard library] and some [http://en.wikipedia.org/wiki/C_POSIX_library POSIX functions]==
128kB of on-chip ROM.
All standard C functions and some POSIX functions (like dirent.h) are available via newlib, except:
*<tt>int link(const char *oldpath, const char *newpath)</tt>
*<tt>int fstat(int fd, struct stat *buf)</tt>
*<tt>int kill(pid_t pid, int sig)</tt>
A program using these will compile and link fine, but behave unexpectedly.


==[http://en.wikipedia.org/wiki/Nucleus_RTOS Nucleus]==
==10000000 - SDRAM==
*<tt>int '''TCT_Local_Control_Interrupts'''(int mask)</tt>: sets the interrupt mask. Returns the previous mask.
*<tt>int '''NU_Current_Dir'''(const char *drive, char *path)</tt>: fills in <tt>path</tt> with the full path name of the current working directory. Use "A:" as ''drive''. Returns 0 on success.
*<tt>int '''NU_Get_First'''(struct dstat *statobj, const char * pattern)</tt>: given a pattern which contains both a path specifier and a search pattern, fills in the structure at <tt>statobj</tt> with information about the file and sets up internal parts of <tt>statobj</tt> to supply appropriate information for calls to <tt>NU_Get_Next</tt>. Returns non-zero if a match was not found.
*<tt>int '''NU_Get_Next'''(struct dstat *statobj)</tt>: given a pointer to a <tt>DSTAT</tt> structure that has been set up by a call to  <tt>NU_Get_First()</tt>, searches for the next match of the original pattern in the original path. Returns non-zero if found and updates <tt>statobj</tt> for subsequent calls to <tt>NU_Get_Next</tt>.
*<tt>void '''NU_Done'''(struct dstat *statobj)</tt>: given a pointer to a <tt>DSTAT</tt> structure that has been set up by a call to <tt>NU_Get_First()</tt>, frees internal elements used by the <tt>statobj</tt>.
*<tt>void '''NU_Set_Current_Dir'''(const char *name)</tt>: Set the current working directory on the default drive.


==TI-Nspire Lua extensions==
64 MiB, managed by 0x90120000.
Ndless can expose C functions to the [http://inspired-lua.org/ TI-Nspire Lua engine] through Ndless Lua Extensions. Most functions of the [http://www.lua.org/pil/contents.html#P4 Lua C API] are available.


This is an experimental feature. Ndless v3.6 or higher is recommended.
==90000000 - General Purpose I/O (GPIO)==


The [https://github.com/ndless-nspire/Ndless/tree/master/ndless-sdk/samples/luaext luaext] example of the Ndless SDK is a good start to write your own Ndless Lua extension.
See [[GPIO Pins]]
# Write a [https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/samples/luaext/luaextdemo.c Ndless program] that uses the [http://www.lua.org/pil/26.1.html Lua C API] to register Lua object and exits immediately
# Build the Lua extension to a binary file named <tt>[extension_name].luax.tns</tt> and drop it (and ask the users to drop it) to any folder of the calculator
# Write a [https://github.com/ndless-nspire/Ndless/blob/master/ndless-sdk/samples/luaext/runluaextdemo.lua TI-Nspire Lua script]. It should load the Lua extension with the following statement:
#:<pre>nrequire [extension_name]</pre>
# Use from the Lua script any Lua object registered by the Lua extension
#:''Note : on Ndless 3.1, the 'require' keyword was used, which starting from OS v3.6 isn't available anymore.''
# Run the Lua script. The 'nrequire' statement will fail if Ndless hasn't been installed on the calculator. An error will be displayed if the Lua extension isn't found.
# Enjoy the TI-Nspire Lua API and OS integration powered by native functions


==TI-Nspire specific==
==90010000 - Fast timer==
===UTF-16 String API===
Since v3.1 r672.
*<tt>String</tt> : The type of the dynamic-length strings encoded in utf-16 format


===== Details =====
The same interface as 900C0000/900D0000, see [[#900D0000 - Second timer|Second timer]].


  typedef struct {
==90020000 - Serial UART==
    char * str;
    int len;
    int chunck_size;
    int unknown_field;
  } * String;


===== Init/Dispose functions =====
[http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf PL011].


*<tt>String '''string_new'''()</tt> : Returns a new String structure
==90030000 - Unknown==
*<tt>void '''string_free'''(String)</tt> : Frees the String structure


===== Encoding functions =====
Probably some kind of hash/crypto thing.


*<tt>char * '''string_to_ascii'''(String)</tt> : Returns String converted to ascii
==90040000 - SPI controller==
*<tt>int '''string_set_ascii'''(String, char *)</tt> : Erases the content of the String with the given ascii string
*<tt>int '''string_set_utf16'''(String, char *)</tt> : Erases the content of the String with the given utf16 string


===== String manipulation functions =====
FTSSP010 SPI controller connected to the LCD.


*<tt>void '''string_lower'''(String)</tt> : Lower all characters in the String
==90060000 - Watchdog timer==
*<tt>int '''string_concat_utf16'''(String, char *)</tt> : Concatenates to the String the given utf16 string
*<tt>void '''string_erase'''(String, int n)</tt> : Erases characters in the String from beginning to <tt>n</tt> (equivalent to substring(n, len))
*<tt>void '''string_truncate'''(String, int n)</tt> : Truncates the String to <tt>n</tt> chararacters (equivalent to substring(0, n))
*<tt>int '''string_insert_replace_utf16'''(String, char *, int start, int end)</tt> : Inserts the given utf16 string between <tt>start</tt> and <tt>end</tt> in the String by erasing its content. If <tt>end</tt> is -1 it erases the end of the String
*<tt>int '''string_insert_utf16'''(String, char *, int pos)</tt> : Inserts the given utf16 string at <tt>pos</tt> in the String.
*<tt>int '''string_sprintf_utf16'''(String, char *, ...)</tt> : Fills the String using the utf16 string format and arguments (equivalent to sprintf but with utf16 everywhere)


===== Search functions =====
Possibly an [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0270b/index.html ARM SP805] or compatible.


*<tt>char '''string_charAt'''(String, int pos)</tt> : Returns the character at <tt>pos</tt> in the String
==90070000 - Second Serial UART==
*<tt>int '''string_indexOf_utf16'''(String, int start, char *pattern)</tt> : Returns the index of <tt>pattern</tt> in the String starting at <tt>start</tt>. Returns -1 if not found
*<tt>int '''string_last_indexOf_utf16'''(String, int start, char *)</tt> : Returns the last index of <tt>pattern</tt> in the String starting at <tt>start</tt>. Returns -1 if not found
*<tt>int '''string_compareTo_utf16'''(String, char *)</tt> : Returns 0 if the given utf16 string is equal to the String, -1 if it is superior, 1 if not
*<tt>char * '''string_substring_utf16'''(String, char *pattern, int *ptr)</tt> : Returns the beginning of the String (in utf16) until <tt>pattern</tt> is met (excluded). <tt>ptr</tt> is modified so that it indicates the ending index of <tt>pattern</tt> or values -1 if the pattern doesn't exist. In such case the whole string is returned.


*<tt>char * '''string_substring'''(String dst, String src, int start, int end)</tt> : Writes in the <tt>dst</tt> the resulting substring from <tt>start</tt> to <tt>end</tt> (excluded) of <tt>src</tt>. Also returns the utf16 pointer
[http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf PL011].


===== Other UTF-16 functions =====
==90080000 - Unknown==


*<tt>void '''ascii2utf16'''(void *buf, const char *str, int max_size)</tt>: converts the UTF-8 string <tt>str</tt> to the UTF-16 string <tt>buf</tt> of size <tt>max_size</tt>.
Unknown. Probably an FTSSP010 as well.
*<tt>void '''utf162ascii'''(void *buf, const char *str, int max_size)</tt>: Since v3.1 r607. converts the UTF-16 string <tt>str</tt> to the UTF-8 string <tt>buf</tt> of size <tt>max_size</tt>.
*<tt>size_t '''utf16_strlen'''(const char * s)</tt>: Since v3.1 r607. Returns the length in characters (including the finalizing null) of the UTF-16 string <tt>s</tt>.


===Graphic Context API===
==90090000 - Real-Time Clock (RTC)==


----
Similar to the [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0224b/index.html ARM PrimeCell PL031], but interrupt registers are different.


Since v3.1 r903.
* 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


The TI-Nspire Graphic Context (or "ngc") is an API created by TI, inspired by Java's Graphics2D and using Nucleus GRAFIX functions.
==900A0000 - Miscellaneous==


This API is intensively used by the OS internally and is directly exposed in the [[Lua_Programming#GC_.28as_in_Graphics_Context.29|TI-Nspire Lua framework]].
Seems to be similar to CX and Classic, except for the model ID at 900A0000 which is now 0x202.


In order to use this API inside your program, use this line:
==900B0000 - ADC==
#include <ngc.h>


The Ndless SDK provides an GC-based demo in <tt>ndless-sdk/samples/ngc/</tt>.
A Faraday FTADCC010.


===== Global parameters =====
==900C0000 - First timer==


*<tt>Gc *'''gui_gc_global_GC_ptr'''</tt> is the graphic context used (and already allocated/setup) by the OS. In fact, <tt>gui_gc_new</tt> has been removed from the syscall list because it made the TI-Nspire Clickpad/Touchpad crash, preferring the use of this graphic context. Furthermore, the OS seems to use the same gc from the beginning of its initialization, why not Ndless then?.
Same port structure as [[#900D0000 - Second timer|Second timer]].
''Notice: It is recommended to save the value of <tt>gui_gc_global_GC_ptr</tt> in a local variable as such:
Gc gc = *gui_gc_global_GC_ptr;


The <tt>gc</tt> is an off-screen buffer. Thus, each function that draws on this gc will not affect the screen until you use <tt>[[Syscalls#Blit_functions|gui_gc_blit_to_screen(gc)]]</tt>.
==900D0000 - Second timer==


The OS tends to blit the screen if it has been updated using a timed Nucleus task. You can use this principle in your programs but nothing forces you to do so. Thus, you can freely blit the screen as many times as you want when running an animation and only refresh part of it using <tt>gui_gc_blit_to_screen_region(gc, x, y, w, h)</tt> when needed.
Timer is a [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/Babehiha.html SP804].


===== Init/Dispose functions=====
==900E0000 - Keypad controller==


*<tt>Gc '''gui_gc_copy'''(Gc, int w, int h)</tt> - Allocates a new Gc from an existing one copying its parameters, replacing port's width & height with the given ones. '''Does not copy the screen buffer.'''
See also [[Keypads]] for information about the keypads themselves.
*<tt>int '''gui_gc_begin'''(Gc)</tt> - Initializes graphic port (seems to allocate 2 memory areas), may be used before any graphic manipulation.
''Notice: <tt>gui_gc_setRegion</tt> may be used before <tt>gui_gc_begin</tt> in order to make <tt>gui_gc_clipRect</tt> work with proper coordinates.''
*<tt>void '''gui_gc_finish'''(Gc)</tt> - Resets the graphic port parameters (seems to free 2 memory areas).
*<tt>void '''gui_gc_free'''(Gc)</tt> - Frees the given gc.


===== Set/Get Attributes functions=====
* 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


*<tt>void '''gui_gc_clipRect'''(Gc, int x, int y, int w, int h, gui_gc_ClipRectOp op)</tt> - Contrains the given <tt>gc</tt> to draw only in a certain area. If <tt>op</tt> is GC_CRO_RESET, the other parameters are ignored.
==90120000 - SDRAM Controller==
*<tt>void '''gui_gc_setColorRGB'''(Gc, int r, int g, int b)</tt> - Changes the pen color of the given <tt>gc</tt>
*<tt>void '''gui_gc_setColor'''(Gc, int color)</tt> - same as <tt>gui_gc_setColorRGB</tt> but using 0xRRGGBB color format
*<tt>void '''gui_gc_setAlpha'''(Gc, gui_gc_Alpha)</tt> - Changes the pen alpha mode of the given <tt>gc</tt> to non-transparent or semi-transparent.
*<tt>void '''gui_gc_setFont'''(Gc, gui_gc_Font)</tt> - Changes the font of the given <tt>gc</tt>
*<tt>gui_gc_Font '''gui_gc_getFont'''(Gc)</tt> - Returns the current font of the given <tt>gc</tt>
*<tt>void '''gui_gc_setPen'''(Gc, gui_gc_PenSize, gui_gc_PenMode)</tt> - Changes the pen size and mode of the given <tt>gc</tt>
*<tt>void '''gui_gc_setRegion'''(Gc, int xs, int ys, int ws, int hs, int x, int y, int w, int h)</tt> - Changes the region (or viewport) of the given <tt>gc</tt>. The region <x,y,w,h> is based on screen coordinates <xs,ys,ws,hs>. <tt>gui_gc_setRegion</tt> will offset all the drawings and coordinates you are using: It can be useful to use this function instead of creating a separate gc to draw an inner window.
''Notice: <tt>gui_gc_clipRect</tt> will work with old coordinates as long as you don't reset the region to the entire screen, for example, by using this main:''


int main(void)
An FTDDR3030.
{
  /* Get the gc */
  Gc gc = *gui_gc_global_GC_ptr;
  /* Initialization */
  gui_gc_setRegion(gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
  gui_gc_begin(gc);
  /* Draw */
  gui_gc_clipRect(gc, 10, 10, 10, 10, GC_CRO_SET);
  gui_gc_fillRect(gc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); /* Will only draw a 10x10 rectangle */
  /* Blit & finish */
  gui_gc_blit_to_screen(gc);
  gui_gc_finish(gc);
  return 0;
}


===== Draw functions =====
==90130000 - Unknown Controller for the LCD Backlight==


*<tt>void '''gui_gc_fillArc'''(Gc, int x, int y, int w, int h, int start, int end)</tt> - Fills an arc inside the box <<tt>x,y,w,h</tt>>. <tt>start</tt> and <tt>end</tt> have to be multiplied by 10.
The OS controls the LCD backlight by writing to 90130018.
/* Disk at <0,0> of size <20,20> */
gui_gc_fillArc(gc, 0, 0, 20, 20, 0, 3600);


*<tt>void '''gui_gc_fillPoly'''(Gc, int * points, int count)</tt> - Fills a polygon shape. <tt>points</tt> is a table of successive x,y coordinates.
==90140000 - Power management==
/* Filled rectangle shape at <100,100> of size <50,50> */
int points[] = {100,100, 150,100, 150,150, 100,150, 100,100};
gui_gc_fillPoly(gc, points, sizeof (points) / sizeof (points[0]));


*<tt>void '''gui_gc_fillRect'''(Gc, int x, int y, int w, int h)</tt> - Fills a rectangle.
A new "Aladdin PMU" unit. Not much known.
/* Filled rectangle at <100,100> of size <50,50> */
gui_gc_fillRect(gc, 100, 100, 50, 50);


*<tt>void '''gui_gc_fillGradient'''(Gc, int x, int y1, int w, int y2, int start_color, int end_color, int vertical)</tt> - Fills a line-based gradient from <tt>start_color</tt> to <tt>end_color</tt> (both in 0xRRGGBB format). As a side-effect, current color is changed to <tt>end_color</tt> after the call. ''May only work for certain color pairs'' (it may be cleverer to recreate this function rectangle-based by your own).
* 90140000 (R/?): Reason for waking up from low-power mode.
/* Black to White vertical gradient at <10,10> of size <50,50> */
* 90140050 (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.
gui_gc_fillGradient(gc, 10, 10, 50, 50, 0x000000, 0xffffff, 1);
** Bit 9: [[#C8010000 - Triple DES encryption]]
** Bit 10: [[#CC000000 - SHA-256 hash generator]]
** Bit 13: [[#90060000 - Watchdog timer]] (?)
** Bit 26: [[#90050000 - I2C controller]] (?)
* 90140050 (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.


*<tt>void '''gui_gc_drawArc'''(Gc, int x, int y, int w, int h, int start, int end)</tt> - Draws an arc insidethe box <<tt>x,y,w,h</tt>>. <tt>start</tt> and <tt>end</tt> have to be multiplied by 10.
==A4000000 - Internal SRAM==
/* Circle at <0,0> of size <20,20> */
gui_gc_drawArc(gc, 0, 0, 20, 20, 0, 3600);


*<tt>void '''gui_gc_drawLine'''(Gc, int x1, int y1, int x2, int y2)</tt> - Draws a line from <<tt>x1,y1</tt>> to <<tt>x2,y2</tt>>.
0x40000 bytes SRAM, managed by the controller at ?.
/* Line from <0,0> to <320,240> */
gui_gc_drawLine(gc, 0, 0, 320, 240);


*<tt>void '''gui_gc_drawRect'''(Gc, int x, int y, int w, int h)</tt> - Draws an empty rectangle at <<tt>x,y</tt>> of size <<tt>w,h</tt>>
==A8000000 - Internal SRAM==
/* Empty rectangle at <100,100> of size <50,50> */
gui_gc_fillRect(gc, 100, 100, 50, 50);


*<tt>void '''gui_gc_drawString'''(Gc, char * utf16, int x, int y, gui_gc_StringMode flags)</tt> - Draws an UTF-16 Null-terminated string at <<tt>x,y</tt>> using <tt>flags</tt>.
0x25800 bytes SRAM for an LCD framebuffer, managed by the controller at ?. It might be bigger in reality, but the OS only ever accesses 320*240*2 Bytes.
/* "Hello" where <50,50> is actually the top left of it */
gui_gc_drawString(gc, "H\0e\0l\0l\0o\0\0", 50, 50, GC_SM_TOP);


/* Upside-down "World" at <100,100> */
==B0000000 - USB OTG/Host/Device controller (top)==
gui_gc_drawString(gc, "W\0o\0r\0l\0d\0\0", 100, 100, GC_SM_DOWN);


*<tt>void '''gui_gc_drawPoly'''(Gc, int * points, int count)</tt> - Draws a polygon shape. <tt>points</tt> is a table of successive x,y coordinates.
An FOTG210 connected to the top USB port.
/* Empty rectangle shape at <100,100> of size <50,50> */
int points[] = {100,100, 150,100, 150,150, 100,150, 100,100};
gui_gc_fillPoly(gc, points, sizeof (points) / sizeof (points[0]));


*<tt>void '''gui_gc_drawIcon'''(Gc, int res, int icon, int x, int y)</tt> - Draws an icon pre-defined by the OS.
==B4000000 - USB OTG/Host/Device controller (bottom)==
/* Draw a star at <100,100> */
gui_gc_drawIcon(gc, RES_SYST, 255, 100, 100);


*<tt>void '''gui_gc_drawSprite'''(Gc, gui_gc_Sprite *, int x, int y)</tt> - Draws a sprite at <<tt>x,y</tt>>. Sprite pixels color is affected by <tt>gui_gc_setColor[RGB]</tt>
An FOTG210 connected to the bottom USB port (dock connector).
/* Draw a hand-made gradient at <100, 100> */
gui_gc_Sprite s = {.width = 9, .height = 1};
s.pixels = (char *) {0x0, 0x22, 0x44, 0x66, 0x88, 0xAA, 0xCC, 0xEE, 0xFF};
gui_gc_drawSprite(gc, &s, 100, 100);


*<tt>void '''gui_gc_drawImage'''(Gc, char * TI_Image, int x, int y)</tt> - Draws an image in [[TI.Image]] format at <<tt>x,y</tt>>
==B8000000 - SPI NAND controller==
/* Gray image at <100,100> of size <10,10> */
gui_gc_Image_header hdr = {.width = 10, .height = 10, .empty = 0, .depth = 2, .enc = 1};
hdr.buff_size = hdr.depth * hdr.width;
unsigned size = hdr.buff_size * hdr.height;
char * img = calloc(size + sizeof (gui_gc_Image_header), 1);
memcpy(img, &hdr, sizeof (gui_gc_Image_header));
memset(img + sizeof (gui_gc_Image_header), 77, size);
gui_gc_drawImage(gc, img, 100, 100);


===== Metric functions =====
An FTSPI020 with a MICRON 1Gb flash at CS 1.


*<tt>int '''gui_gc_getStringWidth'''(Gc, gui_gc_Font, char * utf16, int start, int length)</tt> -
==C0000000 - LCD controller==
*<tt>int '''gui_gc_getCharWidth'''(Gc, gui_gc_Font, short utf16 char)</tt> -
*<tt>int '''gui_gc_getStringSmallHeight'''(Gc, gui_gc_Font, char * utf16, int start, int length)</tt> -
*<tt>int '''gui_gc_getCharHeight'''(Gc, gui_gc_Font, short utf16 char)</tt> -
*<tt>int '''gui_gc_getStringHeight'''(Gc, gui_gc_Font, char * utf16, int start, int length)</tt> -
*<tt>int '''gui_gc_getFontHeight'''(Gc, gui_gc_Font)</tt> -
*<tt>int '''gui_gc_getIconSize'''(Gc, int ressource, int icon, int * w, int * h)</tt> -  


===== Blit functions =====
A [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0293c/index.html PL111].


*<tt>void '''gui_gc_blit_to_screen'''(Gc gc)</tt> - Blits the screen using the given <tt>gc</tt>
==C8010000 - Triple DES encryption==
*<tt>void '''gui_gc_blit_to_screen_region'''(Gc gc, int x, int y, int w, int h)</tt> - Blits part of the screen (region <<tt>x,y,w,h</tt>>) using the given <tt>gc</tt>
*<tt>void '''gui_gc_blit_gc'''(Gc source, int xs, int ys, int ws, int hs, Gc dest, int xd, int yd, int wd, int hd)</tt> - Blits (and Stretch with a cubic interpolation if <<tt>wd,hd</tt>> is different than <<tt>wd,hd</tt>>) from rectangle <<tt>xs,ys,ws,hs</tt>> of <tt>source</tt> to rectangle <<tt>xd,yd,wd,hd</tt>> of <tt>dest</tt>.


''Notice: On OS 3.1 CX/CM, when stretching only, there is a bug that distorts the source rectangle depending on the destination ratio. Even the OS shows this bug, for example Ctrl+N, 2, Ctrl+Up will not center the axes whereas on OS 3.2 it will.''
Implements the [http://en.wikipedia.org/wiki/Triple_DES Triple DES encryption algorithm].


*<tt>void '''gui_gc_blit_buffer'''(Gc gc, char * buffer, int xb, int yb, int wb, int hb)</tt> - Blits a rectangle <<tt>xb,yb,wb,hb</tt>> from <tt>buffer</tt> to the given <tt>gc</tt>. Strangely, <tt>buffer</tt> has to be 320 pixels wide in order to have the correct offsets. Also, <tt>buffer</tt> has to be allocated according to the platform: On Clickpads/Touchpads use 1/2bpp (thus, 160xH), on CM/CX use 2bpp (thus 320x2xH).
* 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


''Notice: In order to be compatible with Clickpads/Touchpads (1/2 bpp vs 2bpp), <tt>x</tt> has to be a the same parity of the current Region's <tt>x</tt>''
==CC000000 - SHA-256 hash generator==


unsigned size = 320 * 15 * 2;
Implements the [http://en.wikipedia.org/wiki/SHA_hash_functions SHA-256 hash algorithm], which is used in cryptographic signatures.
if (!lcd_isincolor()) size >>= 2;
char * buff = malloc(size);
memset(buff, 0x44, size);
/* Draws a green rectangle at <11,20> of size <15,15> */
gui_gc_setRegion(gc, 11, 20, 15, 15, 0, 0, 15, 15);
gui_gc_blit_buffer(gc, buff, 1, 0, 15, 15);
free(buff);


You may notice the spare space unused. Thus, this method is only recommended to be use on fullscreen buffers. For example, this method is used by the internal 3D engine of the OS.
* 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


=== NavNet ===
==DC000000 - Interrupt controller==
----
See [[Interrupts]]. The controller is a [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0181e/index.html PL190].
NavNet is the TI-Nspire specific [[USB Protocol]] and API for calc-to-calc and computer-to-calc transfers. It allows bidirectional and multi-service exposition with connections initiated from the calculator or the computer, abstracting the host/device orientation of USB. The protocol takes care of acknowledgement, and supports network of calculators built with the TI-Nspire™ Navigator System. Standard services such as file transfer or directory listing are available, and custom services can be implemented.
 
Request and response messages contain arbitrary data of at most 254 bytes. The convention for the [[USB Protocol#Services|standard services]] is:
* a single command byte at the beginning of the request packet, with optional parameters data
* a single acknowledgement byte at the beginning of the request packet, with optional response data, ''or'' a 2 byte error code
NavNet does not help with the construction of request and response data.
 
Starting from v3.1 r893 Ndless and the Ndless SDK support a subset of the NavNet API. Windows (with Computer Link or Student Software) is required on the computer side, but a Linux/Mac OS X version based on the [http://lpg.ticalc.org/prj_tilp/ TiLP libraries] may be available in the future. Bidirectional calc-to-calc transfers don't appear to fully work yet as there seems to be limitations in NavNet that make one or the two calculator reboot in some conditions.
 
The NdlessEditor of the Ndless SDK also shows an example of computer-to-calc file transfer supporting the ''Tools > Transfer the program to calc'' menu. The source code is available in <tt>cmd_tools/navnet_cmd</tt>. A startup script is used on the computer side that puts navnet.dll onto the PATH.
 
==== The NavNet API ====
The functions are directly available for the TI-Nspire. For computer connection, the <tt>navnet.h</tt> and <tt>libnavnet.a</tt> library (wrapper for the navnet.dll library) in <tt>ndless_pc/</tt> of the Ndless SDK must be used.
 
All functions return a number >= 0 in case of success that should be checked.
 
*<tt>int16_t TI_NN_Init(const char *opts)</tt>: (computer side) starts the NavNet stack with parameters <tt>opts</tt>. You'll typically use <tt>-c 1 -d 0</tt>, where the -c and -d switches are the log level respectively for the console and the NavNet debug file. Note that the stack cannot be started if Student Software is already running, and transfers without initialization may interfer with transfers from Student Software.
*<tt>int16_t TI_NN_Shutdown(void)</tt>: (computer side) stops the NavNet stack.
*<tt>int16_t TI_NN_RegisterNotifyCallback(uint32_t filter_flags, void (*cb)(void))</tt>: (computer side, broken on calculator side) register for connection events. A connection event is published even if a device was plugged in before the NavNet stack initialization. <tt>filter_flags</tt> should be zero. The parameters passed to the callback function are currently unknown. The computer program should wait for a notification after a <tt>TT_Init()</tt> and before a node enumeration, else the enumeration will fail.
*<tt>nn_oh_t TI_NN_CreateOperationHandle(void)</tt>: create an operation handle to be used with some NavNet functions.
*<tt>int16_t TI_NN_DestroyOperationHandle(nn_oh_t oh)</tt>: destroy an operation handle.
*<tt>int16_t TI_NN_NodeEnumInit(nn_oh_t oh)</tt>: initiates a node (computer or device) enumeration. Enumeration is required to find the partner computer or device.
*<tt>int16_t TI_NN_NodeEnumNext(nn_oh_t oh, nn_nh_t *nh)</tt>: writes the node handle of the next partner computer or device found to <tt>nh</tt>. The first node handle can be used when assuming a single node network.
*<tt>int16_t TI_NN_NodeEnumDone(nn_oh_t oh)</tt>: terminates a node enumeration.
*<tt>int16_t TI_NN_Connect(nn_nh_t nh, uint32_t service_id, nn_ch_t *ch)</tt>: connects to a remote service with service identifier <tt>service_id</tt> (see the list of [[USB_Protocol#Service_identifiers|standard identifiers]], or use a custom service id for custom services). Note that this functions only set up the client node and doesn't transmit any packet.
*<tt>int16_t TI_NN_Disconnect(nn_ch_t ch)</tt>: disconnects from a remote service by sending a disconnection packet.
*<tt>int16_t TI_NN_Write(nn_ch_t ch, void *buf, uint32_t data_size)</tt>: writes a packet to a remote service. The payload is <tt>data_size</tt> long and pointed to by <tt>buf</tt>.
*<tt>int16_t TI_NN_Read(nn_ch_t ch, uint32_t timeout_ms, void *buf, uint32_t buf_size, uint32_t *recv_size)</tt>: waits until a packet is received or a timeout. The size of the packet received is written to <tt>recv_size</tt>. Data is written to <tt>buf</tt> of <tt>buf_size</tt> bytes long. A packet size can be at most <tt>TI_NN_GetConnMaxPktSize()</tt>.
*<tt>uint32_t TI_NN_GetConnMaxPktSize(nn_ch_t ch)</tt>: returns the maximum packet size for request and response.
*<tt>int16_t TI_NN_StartService(uint32_t service_id, void *data, void (*cb)(nn_ch_t ch, void *data))</tt>: exposes a service. <tt>data</tt> will be passed as the <tt>data</tt> parameter of the callback function, and may be NULL. The service identifier musn't conflict with [[USB_Protocol#Service_identifiers|standard identifiers]].
*<tt>int16_t TI_NN_StopService(uint32_t service_id)</tt>: stops exposing a service.
*<tt>int16_t TI_NN_PutFile(nn_nh_t nh, nn_oh_t oh, const char *local_path, const char *remote_path)</tt>: transfers a file from <tt>local_path</tt> to <tt>remote_path</tt>. The local path must be absolute. The remote path is relative to the <tt>/documents</tt> TI-Nspire folder. You must first <tt>TI_NN_Connect()</tt> to service 0x4060 before using it.
 
The following functions are not yet implemented:
*TI_NN_UnregisterNotifyCallback
*TI_NN_InstallOS
*TI_NN_GetNodeInfo
*TI_NN_GetNodeScreen
*TI_NN_CopyFile
*TI_NN_Rename
*TI_NN_RmDir
*TI_NN_MkDir
*TI_NN_DeleteFile
*TI_NN_GetFileAttributes
*TI_NN_DirEnumDone
*TI_NN_DirEnumNext
*TI_NN_DirEnumInit
*TI_NN_GetFile

Revision as of 15:00, 31 August 2019

Not all parts have been discovered and researched yet, so the information on this page is not complete.

00000000 - Boot1 ROM

128kB of on-chip ROM.

10000000 - SDRAM

64 MiB, managed by 0x90120000.

90000000 - General Purpose I/O (GPIO)

See GPIO Pins

90010000 - Fast timer

The same interface as 900C0000/900D0000, see Second timer.

90020000 - Serial UART

PL011.

90030000 - Unknown

Probably some kind of hash/crypto thing.

90040000 - SPI controller

FTSSP010 SPI controller connected to the LCD.

90060000 - Watchdog timer

Possibly an ARM SP805 or compatible.

90070000 - Second Serial UART

PL011.

90080000 - Unknown

Unknown. Probably an FTSSP010 as well.

90090000 - Real-Time Clock (RTC)

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

  • 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

Seems to be similar to CX and Classic, except for the model ID at 900A0000 which is now 0x202.

900B0000 - ADC

A Faraday FTADCC010.

900C0000 - First timer

Same port structure as Second timer.

900D0000 - Second timer

Timer is 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

90120000 - SDRAM Controller

An FTDDR3030.

90130000 - Unknown Controller for the LCD Backlight

The OS controls the LCD backlight by writing to 90130018.

90140000 - Power management

A new "Aladdin PMU" unit. Not much known.

A4000000 - Internal SRAM

0x40000 bytes SRAM, managed by the controller at ?.

A8000000 - Internal SRAM

0x25800 bytes SRAM for an LCD framebuffer, managed by the controller at ?. It might be bigger in reality, but the OS only ever accesses 320*240*2 Bytes.

B0000000 - USB OTG/Host/Device controller (top)

An FOTG210 connected to the top USB port.

B4000000 - USB OTG/Host/Device controller (bottom)

An FOTG210 connected to the bottom USB port (dock connector).

B8000000 - SPI NAND controller

An FTSPI020 with a MICRON 1Gb flash at CS 1.

C0000000 - LCD controller

A PL111.

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.