https://wikiti.brandonw.net/api.php?action=feedcontributions&user=Thepenguin77&feedformat=atomWikiTI - User contributions [en]2024-03-29T07:00:16ZUser contributionsMediaWiki 1.23.5https://wikiti.brandonw.net/index.php?title=83Plus:OS:Hooks83Plus:OS:Hooks2013-09-04T13:44:44Z<p>Thepenguin77: grammar</p>
<hr />
<div>[[Category:83Plus:OS Information|Hooks]]<br />
__TOC__<br />
<br />
=Description=<br />
Hooks are a hidden feature of the TI OS that were originally included for the official TI flash apps to use. The hooks allow a program or app to gain control at different times during the operating system to modify values or add additional features. Although the hooks were designed to be used by flash apps, they also work for programs in ram.<br />
<br />
=Usage=<br />
*The first step to using a hook is to decide which one you need. The list of [[:Category:83Plus:Hooks:By_Name|hooks]] can help you decide which one to use. Just be sure that the hook you pick won't interfere with other OS processes.<br />
*Next, you must find an area of memory for your hook that won't get destroyed during the life of the hook. Typically hooks are saved in flash apps so this is not a problem as you can't overwrite an app. However, if you must put your hook in ram, try to find an unusual place if you want your hook to survive. AppBackUpScreen is definitely not the place to put a long-term hook.<br />
*Once you have your location figured out. Put the address in HL and the page in A. If the hook is in ram, the page is 1. And then call the specific bcall for that hook.<br />
*For the actual hook, it is imperative that the first line is .db $83. The OS uses this as a marker for hooks. It is a safety check so that the OS doesn't jump to a hook that has been destroyed.<br />
*When you are done with your hook. Just call the specific disable bcall for that hook.<br />
<br />
=Memory=<br />
*Each hook has 3 bytes of memory and a flag<br />
**The first two bytes are the address of the hook. The third byte is the page it is on.<br />
**The flag is as simple as 1 is on 0 is off.<br />
<br />
=Restoring and Chaining=<br />
Since the hooks are so useful, many different programs make use of them. This can create problems when two different programs want to use the same hook at the same time. There are three options in this case: either ignore the first hook, save the first hook and restore later, or chain the hooks.<br />
==Restoring==<br />
Restoring the hook is the easier of the two options.<br />
*The first task is to save the hook's three bytes and its active flag to somewhere where they won't get destroyed.<br />
*Next install your hook and let it run its course.<br />
*When it is time to uninstall your hook, just restore the three bytes and the active flag.<br />
==Chaining==<br />
This is much harder than restoring, but the benefits of having one hook occur after the other can be worth the hassle.<br />
*Just like restoring the hook, the first step is to save the hook's three bytes and it's active flag.<br />
*Install your hook like normal.<br />
*When your hook is finished, it now needs to jump to the address you saved in the first step. When this jump is made, care should be taken to put the calculator in exactly the same state that you found it when the hook was called. Remember: the other hook thinks it is being called by the OS.<br />
A few notes:<br />
*Watch out for double chaining. Say program A lays a hook. Program B sees A's hook and chains with it. So the current order is B->A. But now program A gets run again. It sees that program B's hook and chains to it. Program A has no idea that it is already being chained to. So now the order is A->B->A. Program A's hook gets called twice. While the situation is not completely avoidable, remember that if you chain hooks, it is a possibility.<br />
*When chaining hooks. If you need to return a value directly back to the OS, depending on the situation, it is probably safe the skip the jump to the other hook and just return to the OS. If you have to return a value, you don't have much of a choice anyways.<br />
<br />
=See also=<br />
[[Category:83Plus:Hooks:By_Name]]</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Hooks:9B7C83Plus:Hooks:9B7C2012-12-08T20:15:33Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Hooks:By Address|9B7C - Cursor Hook]] [[Category:83Plus:Hooks:By Name|Cursor Hook]]<br />
== Synopsis ==<br />
'''Name:''' Cursor Hook<br />
<br />
'''Hook Pointer Block Address:''' [[83Plus:RAM:9B7C|9B7C]]<br />
<br />
'''Hook Enable BCALL:''' [[83Plus:BCALLs:4F60|4F60]]<br />
<br />
'''Hook Disable BCALL:''' [[83Plus:BCALLs:4F69|4F69]]<br />
<br />
'''Hook Call BCALL:''' [[83Plus:BCALLs:4F57|4F57]]<br />
<br />
'''Hook Active Flag:''' [[83Plus:Flags:34#Bit_7|7, (iy + 34h)]]<br />
<br />
This hook is called when the edit cursor (the flashing block cursor) is shown or hidden.<br />
<br />
== Using the Hook ==<br />
There are three events that are passed for various events, identified when A = 22h, 23h, or 24h. I'm not aware of any event where A < 22h.<br />
<br />
* '''A = 22h:''' This is one of the two events that occur before the cursor will be displayed. Returning with the zero flag set will abort the display sequence, but returning with the zero flag reset will cause the sequence to continue. If you want to change the cursor, draw your own one here and return with the zero flag set.<br />
* '''A = 23h:''' I (JasonM) have no clue why this event exists! It is called after event 22h, but before the actual drawing occurs. It's only called if you returned with the zero flag reset for event 22h (basically, if you said you want the cursor to flash.) If you return with zero set, it cancels the flash, otherwise it will draw it's usual cursor. It would appear that the TI-OS just wants to confirm your decision from the first event!<br />
** If event 22h is returned with Z set (i.e. cancel normal cursor), then this event will trigger only if the [[83Plus:Flags:0C#Bit 3|cursor is showing]] and a key is pressed (the ability to check which key is inconclusive, although BC seems to be preserved from event 22h). Here would be a good time to erase an old custom cursor and draw the new one. Return with Z set in this case to cancel the normal action (Z reset will draw the normal large-font cursor).<br />
** (thepenguin77) This is indeed called when a key is pressed while the cursor is showing. I believe the idea here is that you can update the cursor on the chance that it changed (like 2nd, Alpha, or Ins). Treat this as event 22h so that the cursor will be immediately updated to reflect the shift key. (Otherwise it waits until the next flash).<br />
* '''A = 24h:''' This event is called when the cursor block is about to be replaced with the character underneath it. Returning with the zero flag set will cause this operation to be canceled (the cursor block will be left on the screen.) The character underneath the cursor is passed in B (it's simply a copy of [[83Plus:RAM:844E|curUnder]]), and you should return the character in A. If you want to, you can return any character you like: this will make it appear that the cursor is above a character other than it actually is (note: this doesn't actually edit the text in the edit buffer.) The TI-OS tends to cause redraw errors if you return a character other than in B, so it's probably a good idea to to just return B (make sure you do an "or a" to clear the zero flag, or the cursor won't disappear.)<br />
<br />
== Comments ==<br />
Since it will be fired when the user enters most contexts (any context that starts in an edit buffer), it can serve as a useful hook if you want to fire in a particular context after the context is set up. It could also serve as a replacement for a custom interrupt under some situtations.<br />
<br />
== Credits and Contributions ==<br />
* '''Michael Vincent:''' Example of hook usage in [http://www.detachedsolutions.com/omnicalc Omnicalc]</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Hooks:9B7C83Plus:Hooks:9B7C2012-12-08T20:07:58Z<p>Thepenguin77: 23h</p>
<hr />
<div>[[Category:83Plus:Hooks:By Address|9B7C - Cursor Hook]] [[Category:83Plus:Hooks:By Name|Cursor Hook]]<br />
== Synopsis ==<br />
'''Name:''' Cursor Hook<br />
<br />
'''Hook Pointer Block Address:''' [[83Plus:RAM:9B7C|9B7C]]<br />
<br />
'''Hook Enable BCALL:''' [[83Plus:BCALLs:4F60|4F60]]<br />
<br />
'''Hook Disable BCALL:''' [[83Plus:BCALLs:4F69|4F69]]<br />
<br />
'''Hook Call BCALL:''' [[83Plus:BCALLs:4F57|4F57]]<br />
<br />
'''Hook Active Flag:''' [[83Plus:Flags:34#Bit_7|7, (iy + 34h)]]<br />
<br />
This hook is called when the edit cursor (the flashing block cursor) is shown or hidden.<br />
<br />
== Using the Hook ==<br />
There are three events that are passed for various events, identified when A = 22h, 23h, or 24h. I'm not aware of any event where A < 22h.<br />
<br />
* '''A = 22h:''' This is one of the two events that occur before the cursor will be displayed. Returning with the zero flag set will abort the display sequence, but returning with the zero flag reset will cause the sequence to continue. If you want to change the cursor, draw your own one here and return with the zero flag set.<br />
* '''A = 23h:''' I (JasonM) have no clue why this event exists! It is called after event 22h, but before the actual drawing occurs. It's only called if you returned with the zero flag reset for event 22h (basically, if you said you want the cursor to flash.) If you return with zero set, it cancels the flash, otherwise it will draw it's usual cursor. It would appear that the TI-OS just wants to confirm your decision from the first event!<br />
** If event 22h is returned with Z set (i.e. cancel normal cursor), then this event will trigger only if the [[83Plus:Flags:0C#Bit 3|cursor is showing]] and a key is pressed (the ability to check which key is inconclusive, although BC seems to be preserved from event 22h). Here would be a good time to erase an old custom cursor and draw the new one. Return with Z set in this case to cancel the normal action (Z reset will draw the normal large-font cursor).<br />
** (thepenguin77), I don't feel like disassembling the OS and figuring out the exact use of this, but it is called when a shift key is pressed (2nd/Alpha). Treat this as event 22h so that the cursor will be immediately updated to reflect the shift key. (Otherwise it waits until the next flash).<br />
* '''A = 24h:''' This event is called when the cursor block is about to be replaced with the character underneath it. Returning with the zero flag set will cause this operation to be canceled (the cursor block will be left on the screen.) The character underneath the cursor is passed in B (it's simply a copy of [[83Plus:RAM:844E|curUnder]]), and you should return the character in A. If you want to, you can return any character you like: this will make it appear that the cursor is above a character other than it actually is (note: this doesn't actually edit the text in the edit buffer.) The TI-OS tends to cause redraw errors if you return a character other than in B, so it's probably a good idea to to just return B (make sure you do an "or a" to clear the zero flag, or the cursor won't disappear.)<br />
<br />
== Comments ==<br />
Since it will be fired when the user enters most contexts (any context that starts in an edit buffer), it can serve as a useful hook if you want to fire in a particular context after the context is set up. It could also serve as a replacement for a custom interrupt under some situtations.<br />
<br />
== Credits and Contributions ==<br />
* '''Michael Vincent:''' Example of hook usage in [http://www.detachedsolutions.com/omnicalc Omnicalc]</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:OS:Ram_Pages83Plus:OS:Ram Pages2012-10-07T19:25:09Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:OS_Information|Ram Pages]]<br />
<br />
This is to mark what ram pages may be used for short term or long term use.<br />
<br />
'''It should be noted that on the newer calculator models ([[83Plus:Ports:15|port 15]] >= 55h) pages 82-87 refer to the same physical memory'''<br />
<br />
'''80'''<br />
* Default for TIOS at C000h<br />
* Execution protected<br />
<br />
<br />
'''81'''<br />
* Default for TIOS at 8000h<br />
<br />
<br />
'''82'''<br />
* Not used by TIOS under typical execution<br />
* Execution protected<br />
<br />
<br />
'''83'''<br />
* OS 2.x uses at least some of the range 4000h through 4080h to store app base pages prior to app execution.<br />
* 4100 through 433A is used for various buffers during USB communication.<br />
* 3rd Party Uses<br />
** Temporary swap for Virtual Calc by Michael Vincent<br />
** Temporary code execution for Real Sound by James Montelongo<br />
** Temporary CALCnet buffers for direct USB for Doors CS 7.2 and higher by Christopher "Kerm Martian" Mitchell<br />
<br />
<br />
'''84'''<br />
* Not used by TIOS under typical execution<br />
* Execution protected<br />
* 3rd Party Uses<br />
** Long term use for Virtual Calc by Michael Vincent<br />
<br />
<br />
'''85'''<br />
* Not used by TIOS under typical execution<br />
* 3rd Party Uses<br />
** Long term use for Virtual Calc by Michael Vincent<br />
<br />
<br />
'''86'''<br />
* Not used by TIOS under typical execution<br />
* Execution protected<br />
* 3rd Party Uses<br />
** Long term use for Restore Mem by Michael Vincent<br />
<br />
'''87'''<br />
* Not used by TIOS under typical execution<br />
* 3rd Party Uses<br />
** Long term use for Restore Mem by Michael Vincent</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8B83Plus:Ports:8B2012-05-03T22:46:15Z<p>Thepenguin77: Created page with '8B - USB Events Mask USB Events Mask {{84P-Only Port|0B}} == Synopsis == '''Port Number:''' 8Bh '''Functio…'</p>
<hr />
<div>[[Category:83Plus:Ports:By Address|8B - USB Events Mask]] [[Category:83Plus:Ports:By Name|USB Events Mask]]<br />
{{84P-Only Port|0B}}<br />
== Synopsis ==<br />
'''Port Number:''' 8Bh<br />
<br />
'''Function:''' USB Events Mask<br />
<br />
This port is a mask for what errors [[83Plus:Ports:86|port 86]] will report.<br />
<br />
Set the corresponding bits here to receive notifications via port 86.<br />
<br />
=== Values ===<br />
* Bit 0: Possibly set if the bus has been suspended (no activity for some length of time.)<br />
* Bit 1: Unknown; probably related to HNP and/or SRP.<br />
* Bit 2: Set if a bus reset has occurred (both D+ and D? pulled low for some length of time.)<br />
* Bit 3: Unknown.<br />
* Bit 4: Possibly set if a device has been connected (D+, or maybe D?, pulled high for some length of time.)<br />
* Bit 5: This usually indicates that something was unplugged.<br />
* Bit 6: Unknown; probably related to HNP.<br />
* Bit 7: Calculator cannot provide sufficient power. Usually caused by low batteries, although, some devices cause this every time.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:OS:Opening_System_Apps83Plus:OS:Opening System Apps2012-03-04T02:07:03Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:OS Information|Opening System Apps]]<br />
<br />
For now, this page is purely about how to open the program editor. When someone decides to take a shot at another system app, you can remove this line.<br />
<br />
=Program Editor=<br />
This is all the code that is needed to properly open the program editor.<br />
<br />
<nowiki><br />
ld a, kExtApps ;1<br />
ld (cxCurApp), a<br />
<br />
ld a, kPrgmEd<br />
bcall(_pullDownChk) ;2<br />
bcall(_clrTR)<br />
<br />
ld hl, programName<br />
ld de, progToEdit-1 ;3<br />
bcall(_mov9B)<br />
<br />
bcall(_newContext0) ;4<br />
<br />
ld sp, (onSP) ;5<br />
bcall(_resetStacks)<br />
<br />
bcall(_mon) ;6<br />
<br />
programName:<br />
.db progObj, "NAME", 0<br />
</nowiki><br />
<br />
Here's why this code works by parts:<br />
<br />
1. There are two main reasons to set the current app to kExtApps: 1) the OS won't try to clean up an app that isn't already open, 2) if for some reason the previous app was kPrgmEd, the editor is not going to initialize. By setting this, we are essentially resetting the app system<br />
<br />
2. This little section takes care of any menus that are currently up. For instance, without this block, if you open the editor from the standard PRGM->Edit menu, the editor will appear to open correctly. But as soon as you try to move, you'll find out that you are actually still inside of the PRGM->Edit menu and all hell will break loose.<br />
<br />
3. Simply put, progToEdit is the name of the program you are going to edit. You don't have to copy the progObj token if you don't want to, but this example just does it for good measure.<br />
<br />
4. The _clrTr will actually return kPrgmEd in A, you then feed this value into _newContext0 so that the OS can initialize the program editor app. After the _newContext0, the program editor has actually loaded: the screen looks good and the edit buffer is open. What this means is that at this point, you can mod the edit buffer in whatever way you choose. (In zStart, this is where instant goto happens) <br />
<br />
5. These two lines are semi-optional. You don't technically have to have them, but they are a good idea. You should reset the stacks at this point because if you don't do it now, they aren't going to be reset. This means that after a few iterations of opening the editor, SP is going to make its way into the VAT and you'll start corrupting stuff.<br />
<br />
6. This hands control back over to the OS so it can do its job.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:OS:Opening_System_Apps83Plus:OS:Opening System Apps2012-02-20T14:47:57Z<p>Thepenguin77: Created page with 'Opening System Apps For now, this page is purely about how to open the program editor. When someone decides to take a shot at another system a…'</p>
<hr />
<div>[[Category:83Plus:OS Information|Opening System Apps]]<br />
<br />
For now, this page is purely about how to open the program editor. When someone decides to take a shot at another system app, you can remove this line.<br />
<br />
=Program Editor=<br />
This is all the code that is needed to properly open the program editor.<br />
<br />
<nowiki><br />
ld a, kExtApps ;1<br />
ld (cxCurApp), a<br />
<br />
ld a, kPrgmEd<br />
bcall(_pullDownChk) ;2<br />
bcall(_clrTR)<br />
<br />
ld hl, programName<br />
ld de, progToEdit-1 ;3<br />
bcall(_mov9B)<br />
<br />
bcall(_newContext0) ;4<br />
bcall(_mon)<br />
<br />
programName:<br />
.db progObj, "NAME", 0<br />
</nowiki><br />
<br />
Here's why this code works by parts:<br />
<br />
1. There are two main reasons to set the current app to kExtApps: 1) the OS won't try to clean up an app that isn't already open, 2) if for some reason the previous app was kPrgmEd, the editor is not going to initialize. By setting this, we are essentially resetting the app system<br />
<br />
2. This little section takes care of any menus that are currently up. For instance, without this block, if you open the editor from the standard PRGM->Edit menu, the editor will appear to open correctly. But as soon as you try to move, you'll find out that you are actually still inside of the PRGM->Edit menu and all hell will break loose.<br />
<br />
3. Simply put, progToEdit is the name of the program you are going to edit. You don't have to copy the progObj token if you don't want to, but this example just does it for good measure.<br />
<br />
4. The _clrTr will actually return kPrgmEd in A, you then feed this value into _newContext0 so that the OS can initialize the program editor app. After the _newContext0, the program editor has actually loaded: the screen looks good and the edit buffer is open. What this means is that at this point, you can mod the edit buffer in whatever way you choose. (In zStart, this is where instant goto happens) After you've done your modding (or not) you call _mon to hand control over to the OS and let it do its business.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:OS:Raw_Flash_Commands83Plus:OS:Raw Flash Commands2012-02-20T14:46:28Z<p>Thepenguin77: /* Full Chip Erase */</p>
<hr />
<div>[[Category:83Plus:General Hardware Information|Raw Flash Commands]]<br />
The TI-83+ through TI-84+SE have a flash chip whose data can be erased and rewritten. Issuing write and erase commands is done through memory-mapped writes. The flash chip will not accept any commands unless flash is unlocked. Additionally, any read from flash while issuing a command sequence will abort the command sequence. Consequentially, command sequences can only be issued from RAM and interrupts must be disabled. (Or IM 2 with the ISR and IVT entirely in RAM, I suppose.)<br />
<br />
== Basic Flash Commands ==<br />
It takes the flash chip a long time to perform a write or erase operation. During this time, it is impossible to read data from the flash chip, because all reads will simply report a status byte.<br />
<br />
=== Reset ===<br />
You can reset the flash chip by writing 0F0h to 0000h.<br />
ld a, 0F0h<br />
ld (0), a<br />
Reset the flash chip if a program or erase operation fails, to abort either of those, and to leave autoselect mode. The flash chip does not accept resets during write or erase operations.<br />
<br />
=== Writing ===<br />
The design of flash memory is such that a 0 can be written over a 1, but the reverse is not possible. Any write attempting to do this will fail. To write a 1 over a 0, see the below.<br />
<nowiki><br />
writeFlashByte:<br />
; Writes a byte to flash. Flash must be unlocked. Be aware that pressing CLEAR<br />
; will abort the write.<br />
; Inputs:<br />
; - B: Byte to write<br />
; - C: Page<br />
; - HL: Address to write to. This will not be wrapped.<br />
; Outputs:<br />
; - NZ on failure<br />
; Kills:<br />
; - AF, BC<br />
; Protips:<br />
; - Calling writeFlashByteRaw instead will skip the page changing<br />
; - Do push bc \ pop af afterwards to restore flags to pre-call values. That's<br />
; right, documented side-effect programming! <br />
in a, (memPageAPort) ; save page<br />
push af<br />
ld a, c<br />
out (6), a<br />
di<br />
call writeFlashByteRaw<br />
ei<br />
pop bc ; restore page without screwing up flags<br />
ld a, b<br />
out (memPageAPort), a<br />
ret<br />
writeFlashByteRaw:<br />
; Flash program sequence<br />
ld a, 0AAh ; First bus cycle---unlock<br />
ld (0AAAh), a<br />
ld a, 55h ; Second bus cycle---unlock<br />
ld (0555h), a<br />
ld a, 0A0h ; Third bus cycle---write command<br />
ld (0AAAh), a<br />
ld (hl), b ; Fourth bus cycle---program data<br />
; Wait for the write operation to complete<br />
ld a, 0FDh ; This checks for the CLEAR key.<br />
out (keyPort), a ; If pressed, it aborts.<br />
inc hl<br />
dec hl<br />
programWaitLoop:<br />
in a, (keyPort)<br />
cp 0BFh<br />
jr z, abortProgram<br />
ld a, b<br />
xor (hl)<br />
bit 7, a<br />
jr z, programDone<br />
bit 5, (hl)<br />
jr z, programWaitLoop<br />
abortProgram:<br />
ld a, 0F0h<br />
ld (0000h), a<br />
inc a<br />
programDone:<br />
ret</nowiki><br />
<br />
=== Erasing ===<br />
The design of flash memory is such that writing a 1 over a 0 is not possible, except in large blocks known as sectors. The flash chips TI likes to use have sectors that are almost all 64 K in size, except the last which, which is broken up into several sectors. Erase operations take a long time, during which running code from flash is impossible. If you want, you could probably make something blink or something while you're waiting.<br />
<nowiki><br />
eraseSector:<br />
; Erases a sector of flash. Note: Use eraseSectorRaw for the certificate.<br />
; Inputs:<br />
; - C: Page<br />
; Outputs:<br />
; - Z on fail (this is opposite of writeFlashByte)<br />
; Kills:<br />
; - AF, BC, HL<br />
in a, (memPageAPort)<br />
push af<br />
ld a, c<br />
out (memPageAPort), a<br />
ld hl, 4000h<br />
di<br />
call eraseSectorRaw<br />
ei<br />
pop bc<br />
ld a, b<br />
out (memPageAPort), a<br />
ret<br />
eraseSectorRaw:<br />
; Flash program sequence<br />
ld a, 0AAh ; First bus cycle---unlock<br />
ld (0AAAh), a<br />
ld a, 55h ; Second bus cycle---unlock<br />
ld (0555h), a<br />
ld a, 080h ; Third bus cycle---write command<br />
ld (0AAAh), a<br />
ld a, 0AAh ; Fourth bus cycle---unlock (again)<br />
ld (0AAAh), a<br />
ld a, 55h ; Fifth bus cycle---unlock (again)<br />
ld (0555h), a<br />
ld a, 30h ; Do not change this value. In theory, you could superbrick your calculator.<br />
ld (hl), a<br />
; Wait for the erase operation to complete<br />
ld a, 0FDh<br />
out (keyPort), a<br />
inc hl<br />
dec hl <br />
eraseWaitLoop:<br />
in a, (keyPort)<br />
cp 0BFh<br />
jr z, abortErase<br />
ld a, (hl)<br />
bit 7, a<br />
jr nz, eraseDone<br />
bit 5, a<br />
jr z, eraseWaitLoop<br />
abortErase:<br />
ld a, 0F0h<br />
ld (4000h), a<br />
xor a<br />
eraseDone:<br />
ret<br />
</nowiki><br />
<br />
=== Erase Suspend ===<br />
The flash chip supports suspending an erase operation in program. This allows you to read data from the flash chip again. I'm not sure why would want to do this, but<br />
ld a, 0B0h<br />
ld (0), a<br />
will suspend an erase operation. Then<br />
ld a, 30h<br />
ld (0), a<br />
will resume the erase operation. According to the data sheet, you can actually start writing data to another sector and resume the erase later.<br />
<br />
=== Full Chip Erase ===<br />
Do not use this command under any circumstances. It will fully brick your calculator by means of erasing the boot sector (and everything else). (For the skeptics, this has actually been tested.)<br />
<br />
== Autoselect Mode ==<br />
The flash chips support a set of commands known as the autoselect commands. These commands are intended to allow the flash chip to identify itself to a manufacturer and to verify that sectors are protected. However, they are also usable in-system. To use the autoselect commands, you must first unlock flash. <br />
<br />
The basic code for an autoselect operation is<br />
; First bus cycle---unlock<br />
ld a, 0AAh<br />
ld (0AAAh), a<br />
; Second bus cycle---unlock<br />
ld a, 55h<br />
ld (0555h), a<br />
; Third bus cycle---write command<br />
ld a, 090h<br />
ld (0AAAh), a<br />
; Read autoselect code<br />
ld a, (address)<br />
ld b, a<br />
ld a, 0F0h ; You need to issue a reset command to exit autoselect mode<br />
ld (0000h), a<br />
where address is the code for the autoselect command. Address 0 returns the Manufacturer ID; address 2 returns the device ID. Known manufacturer IDs are<br />
{|-<br />
|<u>Manufacturer</u><br />
|<u>ID</u><br />
|-<br />
|AMD<br />
|01<br />
|-<br />
|Fujitsu<br />
|04<br />
|-<br />
|EON (read from 200h)<br />
|1C<br />
|-<br />
|Extended code, read real code from 200h&nbsp;&nbsp;&nbsp;<br />
|7F<br />
|-<br />
|Macronix<br />
|C4<br />
|}<br />
Though the manufacturer ID changes from unit to unit, the device ID should be consistent:<br />
{|-<br />
|<u>Flash Chip Size</u>&nbsp;&nbsp;&nbsp;<br />
|<u>ID</u><br />
|-<br />
|512 K (5.0 V)<br />
|23<br />
|-<br />
|512 K (3.0 V)<br />
|B9<br />
|-<br />
|1 MB<br />
|DA<br />
|-<br />
|2 MB<br />
|C4<br />
|}<br />
Thus, a TI-83+SE and a TI-84+SE should both have C4 for the device ID; a TI-84+ should have DA for the device ID; and a TI-83+ should have 23 or B9 for the device.<br />
<br />
If you swap the first page of any sector into the 4000h memory bank and read from 4004h, it will return whether or not that sector is protected by the flash chip's built-in write/erase lock. This always returns 0 on all TI-83+SE and TI-84+/SEs because TI has never used the locking feature in those units. <br />
<br />
It appears that TI used to use the flash chip's locking feature on the original TI-83+, because older units read 01 for sector 1Fh. (Older units read 23 for the device ID, and newer units read B9 for the device ID. It is possible that the switch to the B9 devices occurred at the same time as the switch to the ASIC for the TI-83+.) However, since at least 2007, TI has not used the locking feature on the TI-83+. These units always read 0. Therefore, it is still possible that the ASIC supports unlocking the boot sector of these units.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:MultiplicationZ80 Routines:Math:Multiplication2011-12-09T01:10:31Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:Z80 Routines:Math|Multiplication]]<br />
[[Category:Z80 Routines|Multiplication]]<br />
<br />
== Introduction ==<br />
<br />
All these routines use the restoring multiplication algorithm, adapted to the z80 architecture to maximize speed.<br />
They can easily be unrolled to gain some speed.<br />
<br />
== Unsigned versions ==<br />
<br />
=== 8*8 multiplication ===<br />
<br />
The following routine multiplies h by e and places the result in hl<br />
<br />
<nowiki><br />
mult_h_e<br />
ld l, 0<br />
ld d, l<br />
<br />
sla h ; optimised 1st iteration<br />
jr nc, $+3<br />
ld l, e<br />
<br />
ld b, 7<br />
_loop:<br />
add hl, hl <br />
jr nc, $+3<br />
add hl, de<br />
<br />
djnz _loop<br />
<br />
ret<br />
</nowiki><br />
<br />
=== 16*8 multiplication ===<br />
<br />
The following routine multiplies de by a and places the result in ahl (which means a is the most significant byte of the product, l the least significant and h the intermediate one...)<br />
<br />
<nowiki><br />
mult_a_de<br />
ld c, 0<br />
ld h, c<br />
ld l, h<br />
<br />
add a, a ; optimised 1st iteration<br />
jr nc, $+4<br />
ld h,d<br />
ld l,e<br />
<br />
ld b, 7<br />
_loop:<br />
add hl, hl<br />
rla<br />
jr nc, $+4<br />
add hl, de<br />
adc a, c ; yes this is actually adc a, 0 but since c is free we set it to zero and so we can save 1 byte and up to 3 T-states per iteration<br />
<br />
djnz _loop<br />
<br />
ret<br />
</nowiki><br />
<br />
=== 16*16 multiplication ===<br />
<br />
The following routine multiplies bc by de and places the result in dehl.<br />
<br />
<nowiki><br />
mult_de_bc<br />
ld hl, 0<br />
<br />
sla e ; optimised 1st iteration<br />
rl d<br />
jr nc, $+4<br />
ld h, b<br />
ld l, c<br />
<br />
ld a, 15<br />
_loop:<br />
add hl, hl<br />
rl e<br />
rl d<br />
jr nc, $+6<br />
add hl, bc<br />
jr nc, $+3<br />
inc de<br />
<br />
dec a<br />
jr nz, _loop<br />
<br />
ret<br />
</nowiki><br />
<br />
== Signed versions ==<br />
<br />
<!-- do the routines later, basically try to use cpu instruction that preserve bit 7 (sign) or if this is not possible, just take the sign out, do the multiplication and give the sign afterwards and accordingly. --><br />
<br />
=== 8*8 multiplication ===<br />
<br />
=== 16*8 multiplication ===</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Z80_Routines:Math:MultiplicationZ80 Routines:Math:Multiplication2011-12-09T00:54:39Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:Z80 Routines:Math|Multiplication]]<br />
[[Category:Z80 Routines|Multiplication]]<br />
<br />
== Introduction ==<br />
<br />
All these routines use the restoring multiplication algorithm, adapted to the z80 architecture to maximize speed.<br />
They can easily be unrolled to gain some speed.<br />
<br />
== Unsigned versions ==<br />
<br />
=== 8*8 multiplication ===<br />
<br />
The following routine multiplies h by e and places the result in hl<br />
<br />
<nowiki><br />
mult_h_e<br />
ld l, 0<br />
ld d, l<br />
<br />
sla h ; optimised 1st iteration<br />
jr nc, $+3<br />
ld l, e<br />
<br />
ld b, 7<br />
_loop:<br />
add hl, hl <br />
jr nc, $+3<br />
add hl, de<br />
<br />
djnz _loop<br />
<br />
ret<br />
</nowiki><br />
<br />
=== 16*8 multiplication ===<br />
<br />
The following routine multiplies de by a and places the result in ahl (which means a is the most significant byte of the product, l the least significant and h the intermediate one...)<br />
<br />
<nowiki><br />
mult_a_de<br />
ld c, 0<br />
ld h, c<br />
ld l, h<br />
<br />
add a, a ; optimised 1st iteration<br />
jr nc, $+4<br />
ld h,d<br />
ld l,e<br />
<br />
ld b, 7<br />
_loop:<br />
add hl, hl<br />
rla<br />
jr nc, $+4<br />
add hl, de<br />
adc a, c ; yes this is actually adc a, 0 but since c is free we set it to zero and so we can save 1 byte and up to 3 T-states per iteration<br />
<br />
djnz _loop<br />
<br />
ret<br />
</nowiki><br />
<br />
=== 16*16 multiplication ===<br />
<br />
The following routine multiplies bc by de and places the result in dehl.<br />
<br />
<nowiki><br />
mult_de_bc<br />
ld hl, 0<br />
<br />
sla e ; optimised 1st iteration<br />
rl d<br />
jr nc, $+4<br />
ld h, b<br />
ld l, c<br />
<br />
ld a, 15<br />
_loop:<br />
add hl, hl<br />
rl e<br />
rl d<br />
jr nc, $+6<br />
add hl, bc<br />
jr nc, $+3<br />
inc de<br />
<br />
dec a<br />
jr nz, _loop<br />
<br />
ret<br />
</nowiki><br />
<br />
=== 24*24 multiplication ===<br />
<br />
The following routine multiplies bcd by ehl and places the result in bcdehl. It uses 2 bytes of ram, but those can be substituted for IX half registers. (By thepenguin77)<br />
<br />
<nowiki><br />
multDBCbyEHL:<br />
<br />
push de<br />
push hl<br />
<br />
ld ix, $8000<br />
ld (ix), l<br />
xor a<br />
ld h, a<br />
ld l, a<br />
<br />
call do8Bits<br />
<br />
ld (ix+1), a<br />
pop af<br />
ld (ix), a <br />
push de<br />
ld a, (ix+1)<br />
<br />
call do8Bits<br />
<br />
ld (ix+1), a<br />
pop af ;least sig number<br />
ex de, hl<br />
ex (sp), hl ;D and 2nd least sig in for new number<br />
ld (ix), l<br />
pop hl ;D and 2nd least sig<br />
push af ;least sig number<br />
push hl ;2nd least sig number<br />
ex de, hl<br />
ld a, (ix+1)<br />
<br />
call do8Bits<br />
<br />
ld b, a<br />
ld c, h<br />
ld d, l<br />
pop hl<br />
ld a, l<br />
pop hl<br />
ld h, a<br />
ret<br />
<br />
;####<br />
;input: DBC = 1 number<br />
; AHL = running number<br />
; (ix) = to multiply by<br />
;output: AHLE = output<br />
; E is done<br />
; DBC = 1 number<br />
<br />
do8Bits:<br />
ld (ix+1), 8<br />
loop:<br />
srl (ix)<br />
jr nc, skip<br />
<br />
add hl, bc<br />
adc a, d<br />
skip:<br />
rra <br />
rr h<br />
rr l<br />
rr e<br />
dec (ix+1)<br />
jr nz, loop<br />
ret<br />
</nowiki><br />
<br />
== Signed versions ==<br />
<br />
<!-- do the routines later, basically try to use cpu instruction that preserve bit 7 (sign) or if this is not possible, just take the sign out, do the multiplication and give the sign afterwards and accordingly. --><br />
<br />
=== 8*8 multiplication ===<br />
<br />
=== 16*8 multiplication ===</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:State_of_the_calculator_at_boot83Plus:State of the calculator at boot2011-11-26T02:23:40Z<p>Thepenguin77: </p>
<hr />
<div>This page is dedicated to what happens right when the calculator begins to execute code.<br />
<br />
For now, all the information is about the 84+. When someone does some boot code work with the 83+, this page will have to be updated.<br />
<br />
==Registers==<br />
All registers are 00h. However, if you are writing a boot code, you should still initialize the variables on the off chance that one is not 00h, or if someone jumps to your boot code.<br />
<br />
==Port Values==<br />
These port values were all found on an 84+SE hardware revision M with a [[83Plus:Ports:15|port 15]] value of 55h.<br />
<br />
{| cellspacing="0" border="1"<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|00h||03h<br />
|-<br />
|01h||FFh<br />
|-<br />
|02h||E3h<br />
|-<br />
|03h||00h<br />
|-<br />
|04h||08h<br />
|-<br />
|05h||00h<br />
|-<br />
|06h||00h<br />
|-<br />
|07h||00h<br />
|-<br />
|08h||00h<br />
|-<br />
|09h||20h<br />
|-<br />
|0Ah||00h<br />
|-<br />
|0Bh||00h<br />
|-<br />
|0Ch||00h<br />
|-<br />
|0Dh||00h<br />
|-<br />
|0Eh||00h<br />
|-<br />
|0Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|10h||FFh<br />
|-<br />
|11h||FFh<br />
|-<br />
|12h||FFh<br />
|-<br />
|13h||FFh<br />
|-<br />
|14h||00h<br />
|-<br />
|15h||55h<br />
|-<br />
|16h||00h<br />
|-<br />
|17h||00h<br />
|-<br />
|18h||00h<br />
|-<br />
|19h||00h<br />
|-<br />
|1Ah||00h<br />
|-<br />
|1Bh||00h<br />
|-<br />
|1Ch||00h<br />
|-<br />
|1Dh||00h<br />
|-<br />
|1Eh||00h<br />
|-<br />
|1Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|20h||00h<br />
|-<br />
|21h||33h<br />
|-<br />
|22h||00h<br />
|-<br />
|23h||00h<br />
|-<br />
|24h||00h<br />
|-<br />
|25h||00h<br />
|-<br />
|26h||00h<br />
|-<br />
|27h||00h<br />
|-<br />
|28h||00h<br />
|-<br />
|29h||00h<br />
|-<br />
|2Ah||00h<br />
|-<br />
|2Bh||00h<br />
|-<br />
|2Ch||00h<br />
|-<br />
|2Dh||00h<br />
|-<br />
|2Eh||00h<br />
|-<br />
|2Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|30h||00h<br />
|-<br />
|31h||00h<br />
|-<br />
|32h||00h<br />
|-<br />
|33h||00h<br />
|-<br />
|34h||00h<br />
|-<br />
|35h||00h<br />
|-<br />
|36h||00h<br />
|-<br />
|37h||00h<br />
|-<br />
|38h||00h<br />
|-<br />
|39h||00h<br />
|-<br />
|3Ah||00h<br />
|-<br />
|3Bh||00h<br />
|-<br />
|3Ch||FFh<br />
|-<br />
|3Dh||FFh<br />
|-<br />
|3Eh||FFh<br />
|-<br />
|3Fh||FFh<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|40h||00h<br />
|-<br />
|41h||00h<br />
|-<br />
|42h||00h<br />
|-<br />
|43h||00h<br />
|-<br />
|44h||00h<br />
|-<br />
|45h||00h<br />
|-<br />
|46h||00h<br />
|-<br />
|47h||00h<br />
|-<br />
|48h||00h<br />
|-<br />
|49h||18h<br />
|-<br />
|4Ah||06h<br />
|-<br />
|4Bh||00h<br />
|-<br />
|4Ch||22h<br />
|-<br />
|4Dh||A9h<br />
|-<br />
|4Eh||00h<br />
|-<br />
|4Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|50h||00h<br />
|-<br />
|51h||00h<br />
|-<br />
|52h||00h<br />
|-<br />
|53h||00h<br />
|-<br />
|54h||02h<br />
|-<br />
|55h||1Fh<br />
|-<br />
|56h||00h<br />
|-<br />
|57h||00h<br />
|-<br />
|58h||00h<br />
|-<br />
|59h||00h<br />
|-<br />
|5Ah||00h<br />
|-<br />
|5Bh||00h<br />
|-<br />
|5Ch||00h<br />
|-<br />
|5Dh||00h<br />
|-<br />
|5Eh||00h<br />
|-<br />
|5Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|60h||00h<br />
|-<br />
|61h||00h<br />
|-<br />
|62h||00h<br />
|-<br />
|63h||00h<br />
|-<br />
|64h||00h<br />
|-<br />
|65h||00h<br />
|-<br />
|66h||00h<br />
|-<br />
|67h||00h<br />
|-<br />
|68h||00h<br />
|-<br />
|69h||18h<br />
|-<br />
|6Ah||06h<br />
|-<br />
|6Bh||00h<br />
|-<br />
|6Ch||22h<br />
|-<br />
|6Dh||A9h<br />
|-<br />
|6Eh||00h<br />
|-<br />
|6Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|70h||00h<br />
|-<br />
|71h||00h<br />
|-<br />
|72h||00h<br />
|-<br />
|73h||00h<br />
|-<br />
|74h||02h<br />
|-<br />
|75h||1Fh<br />
|-<br />
|76h||00h<br />
|-<br />
|77h||00h<br />
|-<br />
|78h||00h<br />
|-<br />
|79h||00h<br />
|-<br />
|7Ah||00h<br />
|-<br />
|7Bh||00h<br />
|-<br />
|7Ch||00h<br />
|-<br />
|7Dh||00h<br />
|-<br />
|7Eh||00h<br />
|-<br />
|7Fh||00h<br />
|}<br />
|}<br />
<br />
<br />
'''Interesting points:'''<br />
* Flash is locked<br />
* 4000h contains flash page 00h<br />
* 8000h contains flash page 00h<br />
* C000h contains ram page 00h<br />
* The LCD driver is disconnected ([[83Plus:Ports:29|port 29]] causes this)<br />
* The boot code is unlocked<br />
* 84+BE/SE cannot be determined from [[83Plus:Ports:21|port 21]] as it reads 33h<br />
* All parts of flash except privileged pages are non-executable (2C-2F, 3F, 6C-6F, and 7F)<br />
* All of ram is non-executable except the first 1024 bytes of ram page 00h<br />
* None of the LCD delay ports are set<br />
* The clock is off<br />
* The USB driver is off<br />
<br />
==Memory Mapping==<br />
Here's where the boot code gets fun. Since on boot all variables and ports have been reset, it would logically follow that execution should start at 0000h. There's a problem though, 0000h is always flash page 00h. In order to beat this, TI actually had to add a hack to put the boot code into the 0000h region.<br />
<br />
* The calculator is in memory map mode 0<br />
* 0000h contains the boot code (3Fh / 7Fh) and behaves normally<br />
* 4000h contains flash page 00h<br />
* 8000h contains flash page 00h<br />
* C000h contains ram page 00h<br />
* Page 00h is restored to 0000h when and only when a byte is executed in a memory bank controlled by [[83Plus:Ports:06|port 06]]. This means that in memory map mode 0, a byte must be executed in the 4000h-7FFFh range, and in memory map mode 1, a byte must be executed in the 4000-BFFFh range. When this byte is executed, 00h instantly goes back to 0000h.<br />
<br />
It has also been determined that [[83Plus:Ports:0E|ports 0E and 0F]] play no part in this behavior on the 84+.<br />
<br />
==Gathering this Information==<br />
This information could only be gathered by replacing the boot code. This was a very dangerous operation as one mistake will brick the calculator. You should not attempt to recreate anything on this page or write your own boot code unless you are a master at z80 assembly.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:UnknownCategory:83Plus:Ports:Unknown2011-11-26T02:19:54Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By_Address|Unknown Ports]]<br />
<br />
== Synopsis ==<br />
There are several ports that have not yet been totally solved. Here is a list of them and what information is available.<br />
<br />
<br />
<br />
===83+ & SE Calculator Ports===<br />
'''Port 04:''' Writing:<br />
* Bit 3: always 0, doesn't seem to have any effect<br />
* Bit 4: always 1, doesn't seem to have any effect, guessing leftover from 83 code<br />
* Bits 5, 6, and 7: Bit 7 is known to control the voltage level at which port 02 bit 0 flips. Its default is 0. Bits 5 and 6 are usually left to 1. The EOS messes with bit 6 when testing the battery level. On the TI-89T hardware, bit 5 of a similar port also affects the voltage level threshold. On both the Z80 series hardware and the 68K series hardware, the OS waits for a while between changing this threshold and reading it. It would be great if somebody with a finely-variable voltage DC power supply tested this.<br />
<br />
<br />
<br />
===SE Calculator Ports Only===<br />
'''Port 0A:''' Writing:<br />
* Tied to the link assist on the SE calculators. Only written to in the boot code where it receives B4.<br />
** If this is set to DF or above, ti-connect won't detect the calculator over silver link.<br />
<br />
'''Port 0B:'''<br />
* Tied to the link assist on the SE calculators. Only written to in boot code where it receives B4. Possibly controls the timeout for receiving.<br />
<br />
'''Port 0C:'''<br />
* Tied to the link assist on the SE calculators. Only written to in boot code where it receives B4. Possibly controls the timeout for sending.<br />
** If this is set to E0 or above, the link assist won't throw an error if you write to port 0D without another calculator attached.<br />
<br />
'''Port 0E:'''<br />
* Tied with swapping bank $4000. Before swapping pages this port should contain 00, otherwise data read from those pages may not be accurate. Only bits 0 and 1 can be toggled. Needs research on the 83+SE.<br />
<br />
'''Port 0F:'''<br />
* Tied with swapping bank $8000. Before swapping pages this port should contain 00, otherwise data read from those pages may not be accurate. Only bits 0 and 1 can be toggled. Needs research on the 83+SE.<br />
<br />
'''Port 24:'''<br />
* DrDnar and thepenguin77 figured out the purposes of bits 0 and 1 of this port. However, bits 2-7 can be altered, yet no effect is apparent. This is a [[:Category:83Plus:Ports:By_Address:Protected|protected port]].<br />
<br />
'''Port 2D:'''<br />
* Only bits 0 and 1 can be altered, but no effect is apparent. Only written to in the boot code, where it receives 02.<br />
<br />
'''USB Ports:'''<br />
* All information concerning the USB ports will be handled [[83Plus:OS:84_Plus_USB_Information|here]].<br />
<br />
==Comments==<br />
Other ports have unknown functions but are never written to, read from, or change in a significant way, some likely have no purpose at all.<br />
<br />
There is still quite bit unknown about the hardware, however the remainder is less significant to or can not be used by the average coder.<br />
<br />
<br />
== Credits and Contributions ==<br />
* '''Tijl Coosemans'''<br />
* '''Dan Englender'''<br />
* '''James Montelongo'''<br />
* '''Michael Vincent'''</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:0E83Plus:Ports:0E2011-11-26T02:18:01Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By_Address|0E-0F - Boot Code Paging]] [[Category:83Plus:Ports:By_Name|Boot Code Paging]]<br />
<br />
== Synopsis ==<br />
'''Port Numbers:''' 0Eh and 0Fh<br />
<br />
'''Function:''' Boot Code Paging<br />
<br />
These ports have no function on the 84+ line. They might do something on the 83+SE.<br />
<br />
=== Read Values ===<br />
* Bits 0-1: Whatever was last written<br />
* Bits 2-7: always 0<br />
<br />
=== Write Values ===<br />
* Bits 0-1: Set a new value<br />
* Bit 2-7: No effect<br />
<br />
== Comments ==<br />
These two ports are written to very early in the boot code where they both receive 03 then 00. Port 0E is written to first and is used before accessing page 7F in the 8000h region via memory map mode 1. Port 0Fh is written to second before accessing page 7F in the 4000h region via memory map mode 0. Once execution is running normally in the 4000h region, both ports are set back to 00.<br />
<br />
It would seem that port 0E is related to the 8000h range and port 0F is related to the 4000h range, but that might not be correct.<br />
<br />
It has also been confirmed on all three ASIC revisions that this port is not necessary to fix the boot code memory mapping. For more information on that see: [[83Plus:State_of_the_calculator_at_boot|State of the calculator at boot]]</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:State_of_the_calculator_at_boot83Plus:State of the calculator at boot2011-11-26T02:09:43Z<p>Thepenguin77: </p>
<hr />
<div>This page is dedicated to what happens right when the calculator begins to execute code.<br />
<br />
For now, all the information is about the 84+. When someone does some boot code work with the 83+, this page will have to be updated.<br />
<br />
==Registers==<br />
All registers are 00h. However, if you are writing a boot code, you should still initialize the variables on the off chance that one is not 00h, or if someone jumps to your boot code.<br />
<br />
==Port Values==<br />
These port values were all found on an 84+SE hardware revision M with a [[83Plus:Ports:15|port 15]] value of 55h.<br />
<br />
{| cellspacing="0" border="1"<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|00h||03h<br />
|-<br />
|01h||FFh<br />
|-<br />
|02h||E3h<br />
|-<br />
|03h||00h<br />
|-<br />
|04h||08h<br />
|-<br />
|05h||00h<br />
|-<br />
|06h||00h<br />
|-<br />
|07h||00h<br />
|-<br />
|08h||00h<br />
|-<br />
|09h||20h<br />
|-<br />
|0Ah||00h<br />
|-<br />
|0Bh||00h<br />
|-<br />
|0Ch||00h<br />
|-<br />
|0Dh||00h<br />
|-<br />
|0Eh||00h<br />
|-<br />
|0Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|10h||FFh<br />
|-<br />
|11h||FFh<br />
|-<br />
|12h||FFh<br />
|-<br />
|13h||FFh<br />
|-<br />
|14h||00h<br />
|-<br />
|15h||55h<br />
|-<br />
|16h||00h<br />
|-<br />
|17h||00h<br />
|-<br />
|18h||00h<br />
|-<br />
|19h||00h<br />
|-<br />
|1Ah||00h<br />
|-<br />
|1Bh||00h<br />
|-<br />
|1Ch||00h<br />
|-<br />
|1Dh||00h<br />
|-<br />
|1Eh||00h<br />
|-<br />
|1Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|20h||00h<br />
|-<br />
|21h||33h<br />
|-<br />
|22h||00h<br />
|-<br />
|23h||00h<br />
|-<br />
|24h||00h<br />
|-<br />
|25h||00h<br />
|-<br />
|26h||00h<br />
|-<br />
|27h||00h<br />
|-<br />
|28h||00h<br />
|-<br />
|29h||00h<br />
|-<br />
|2Ah||00h<br />
|-<br />
|2Bh||00h<br />
|-<br />
|2Ch||00h<br />
|-<br />
|2Dh||00h<br />
|-<br />
|2Eh||00h<br />
|-<br />
|2Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|30h||00h<br />
|-<br />
|31h||00h<br />
|-<br />
|32h||00h<br />
|-<br />
|33h||00h<br />
|-<br />
|34h||00h<br />
|-<br />
|35h||00h<br />
|-<br />
|36h||00h<br />
|-<br />
|37h||00h<br />
|-<br />
|38h||00h<br />
|-<br />
|39h||00h<br />
|-<br />
|3Ah||00h<br />
|-<br />
|3Bh||00h<br />
|-<br />
|3Ch||FFh<br />
|-<br />
|3Dh||FFh<br />
|-<br />
|3Eh||FFh<br />
|-<br />
|3Fh||FFh<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|40h||00h<br />
|-<br />
|41h||00h<br />
|-<br />
|42h||00h<br />
|-<br />
|43h||00h<br />
|-<br />
|44h||00h<br />
|-<br />
|45h||00h<br />
|-<br />
|46h||00h<br />
|-<br />
|47h||00h<br />
|-<br />
|48h||00h<br />
|-<br />
|49h||18h<br />
|-<br />
|4Ah||06h<br />
|-<br />
|4Bh||00h<br />
|-<br />
|4Ch||22h<br />
|-<br />
|4Dh||A9h<br />
|-<br />
|4Eh||00h<br />
|-<br />
|4Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|50h||00h<br />
|-<br />
|51h||00h<br />
|-<br />
|52h||00h<br />
|-<br />
|53h||00h<br />
|-<br />
|54h||02h<br />
|-<br />
|55h||1Fh<br />
|-<br />
|56h||00h<br />
|-<br />
|57h||00h<br />
|-<br />
|58h||00h<br />
|-<br />
|59h||00h<br />
|-<br />
|5Ah||00h<br />
|-<br />
|5Bh||00h<br />
|-<br />
|5Ch||00h<br />
|-<br />
|5Dh||00h<br />
|-<br />
|5Eh||00h<br />
|-<br />
|5Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|60h||00h<br />
|-<br />
|61h||00h<br />
|-<br />
|62h||00h<br />
|-<br />
|63h||00h<br />
|-<br />
|64h||00h<br />
|-<br />
|65h||00h<br />
|-<br />
|66h||00h<br />
|-<br />
|67h||00h<br />
|-<br />
|68h||00h<br />
|-<br />
|69h||18h<br />
|-<br />
|6Ah||06h<br />
|-<br />
|6Bh||00h<br />
|-<br />
|6Ch||22h<br />
|-<br />
|6Dh||A9h<br />
|-<br />
|6Eh||00h<br />
|-<br />
|6Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|70h||00h<br />
|-<br />
|71h||00h<br />
|-<br />
|72h||00h<br />
|-<br />
|73h||00h<br />
|-<br />
|74h||02h<br />
|-<br />
|75h||1Fh<br />
|-<br />
|76h||00h<br />
|-<br />
|77h||00h<br />
|-<br />
|78h||00h<br />
|-<br />
|79h||00h<br />
|-<br />
|7Ah||00h<br />
|-<br />
|7Bh||00h<br />
|-<br />
|7Ch||00h<br />
|-<br />
|7Dh||00h<br />
|-<br />
|7Eh||00h<br />
|-<br />
|7Fh||00h<br />
|}<br />
|}<br />
<br />
<br />
'''Interesting points:'''<br />
* Flash is locked<br />
* 4000h contains flash page 00h<br />
* 8000h contains flash page 00h<br />
* C000h contains ram page 00h<br />
* The LCD driver is disconnected ([[83Plus:Ports:29|port 29]] causes this)<br />
* The boot code is unlocked<br />
* 84+BE/SE cannot be determined from [[83Plus:Ports:21|port 21]] as it reads 33h<br />
* All parts of flash except privileged pages are non-executable (2C-2F, 3F, 6C-6F, and 7F)<br />
* All of ram is non-executable except the first 1024 bytes of ram page 00h<br />
* None of the LCD delay ports are set<br />
* The clock is off<br />
* The USB driver is off<br />
<br />
==Memory Mapping==<br />
Here's where the boot code gets fun. Since on boot all variables and ports have been reset, it would logically follow that execution should start at 0000h. There's a problem though, 0000h is always flash page 00h. In order to beat this, TI actually had to add a hack to put the boot code into the 0000h region.<br />
<br />
* The calculator is in memory map mode 0<br />
* Page 7Fh is swapped into the 0000h region and acts completely normal<br />
* Every other port works exactly how it should<br />
* Page 00h is restored to 0000h when and only when a byte is executed in a memory bank controlled by [[83Plus:Ports:06|port 06]]. This means that in memory map mode 0, a byte must be executed in the 4000h-7FFFh range, and in memory map mode 1, a byte must be executed in the 4000-BFFFh range. When this byte is executed, 00h instantly goes back to 0000h.<br />
<br />
It has also been determined that [[83Plus:Ports:0E|ports 0E and 0F]] play no part in this behavior on the 84+.<br />
<br />
==Gathering this Information==<br />
This information could only be gathered by replacing the boot code. This was a very dangerous operation as one mistake will brick the calculator. You should not attempt to recreate anything on this page or write your own boot code unless you are a master at z80 assembly.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:0F83Plus:Ports:0F2011-11-26T02:05:59Z<p>Thepenguin77: Redirected page to 83Plus:Ports:0E</p>
<hr />
<div>#Redirect [[83Plus:Ports:0E]]</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:By_AddressCategory:83Plus:Ports:By Address2011-11-26T02:04:21Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports|Ports by Address/Number]]<br />
See also [[:Category:83Plus:Ports:By Name|list of ports by name]] and [[83Plus:State_of_the_calculator_at_boot|State of the calculator at boot]].<br />
<br />
Please read our page on [[Contributing]] before editing these pages!<br />
<br />
<br />
'''A note about 83+BE ports:''' On the 83+BE, many of the ports have been mirrored to the 00h-07h region. If a port is mirrored, when it is being read, take the bitwise-AND with 07h to find the actual port being accessed. All writes to mirrored ports are ignored.<br />
<br />
Legitimate 83+BE ports (the rest are mirrored):<br />
* '''Read values''' - 00h-07h and 10h-13h are original ports<br />
* '''Write values''' - 00h-07h, 10h-13h, 14h, and 16h are original ports</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:State_of_the_calculator_at_boot83Plus:State of the calculator at boot2011-11-26T02:03:17Z<p>Thepenguin77: Created page with 'This page is dedicated to what happens right when the calculator begins to execute code. For now, all the information is about the 84+. When someone does some boot code work wit…'</p>
<hr />
<div>This page is dedicated to what happens right when the calculator begins to execute code.<br />
<br />
For now, all the information is about the 84+. When someone does some boot code work with the 83+, this page will have to be updated.<br />
<br />
==Registers==<br />
All registers are 00h. However, if you are writing a boot code, you should still initialize the variables on the off chance that one is not 00h, or if someone jumps to your boot code.<br />
<br />
==Port Values==<br />
These port values were all found on an 84+SE hardware revision M with a [[83Plus:Ports:15|port 15]] value of 55h.<br />
<br />
{| cellspacing="0" border="1"<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|00h||03h<br />
|-<br />
|01h||FFh<br />
|-<br />
|02h||E3h<br />
|-<br />
|03h||00h<br />
|-<br />
|04h||08h<br />
|-<br />
|05h||00h<br />
|-<br />
|06h||00h<br />
|-<br />
|07h||00h<br />
|-<br />
|08h||00h<br />
|-<br />
|09h||20h<br />
|-<br />
|0Ah||00h<br />
|-<br />
|0Bh||00h<br />
|-<br />
|0Ch||00h<br />
|-<br />
|0Dh||00h<br />
|-<br />
|0Eh||00h<br />
|-<br />
|0Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|10h||FFh<br />
|-<br />
|11h||FFh<br />
|-<br />
|12h||FFh<br />
|-<br />
|13h||FFh<br />
|-<br />
|14h||00h<br />
|-<br />
|15h||55h<br />
|-<br />
|16h||00h<br />
|-<br />
|17h||00h<br />
|-<br />
|18h||00h<br />
|-<br />
|19h||00h<br />
|-<br />
|1Ah||00h<br />
|-<br />
|1Bh||00h<br />
|-<br />
|1Ch||00h<br />
|-<br />
|1Dh||00h<br />
|-<br />
|1Eh||00h<br />
|-<br />
|1Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|20h||00h<br />
|-<br />
|21h||33h<br />
|-<br />
|22h||00h<br />
|-<br />
|23h||00h<br />
|-<br />
|24h||00h<br />
|-<br />
|25h||00h<br />
|-<br />
|26h||00h<br />
|-<br />
|27h||00h<br />
|-<br />
|28h||00h<br />
|-<br />
|29h||00h<br />
|-<br />
|2Ah||00h<br />
|-<br />
|2Bh||00h<br />
|-<br />
|2Ch||00h<br />
|-<br />
|2Dh||00h<br />
|-<br />
|2Eh||00h<br />
|-<br />
|2Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|30h||00h<br />
|-<br />
|31h||00h<br />
|-<br />
|32h||00h<br />
|-<br />
|33h||00h<br />
|-<br />
|34h||00h<br />
|-<br />
|35h||00h<br />
|-<br />
|36h||00h<br />
|-<br />
|37h||00h<br />
|-<br />
|38h||00h<br />
|-<br />
|39h||00h<br />
|-<br />
|3Ah||00h<br />
|-<br />
|3Bh||00h<br />
|-<br />
|3Ch||FFh<br />
|-<br />
|3Dh||FFh<br />
|-<br />
|3Eh||FFh<br />
|-<br />
|3Fh||FFh<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|40h||00h<br />
|-<br />
|41h||00h<br />
|-<br />
|42h||00h<br />
|-<br />
|43h||00h<br />
|-<br />
|44h||00h<br />
|-<br />
|45h||00h<br />
|-<br />
|46h||00h<br />
|-<br />
|47h||00h<br />
|-<br />
|48h||00h<br />
|-<br />
|49h||18h<br />
|-<br />
|4Ah||06h<br />
|-<br />
|4Bh||00h<br />
|-<br />
|4Ch||22h<br />
|-<br />
|4Dh||A9h<br />
|-<br />
|4Eh||00h<br />
|-<br />
|4Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|50h||00h<br />
|-<br />
|51h||00h<br />
|-<br />
|52h||00h<br />
|-<br />
|53h||00h<br />
|-<br />
|54h||02h<br />
|-<br />
|55h||1Fh<br />
|-<br />
|56h||00h<br />
|-<br />
|57h||00h<br />
|-<br />
|58h||00h<br />
|-<br />
|59h||00h<br />
|-<br />
|5Ah||00h<br />
|-<br />
|5Bh||00h<br />
|-<br />
|5Ch||00h<br />
|-<br />
|5Dh||00h<br />
|-<br />
|5Eh||00h<br />
|-<br />
|5Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|60h||00h<br />
|-<br />
|61h||00h<br />
|-<br />
|62h||00h<br />
|-<br />
|63h||00h<br />
|-<br />
|64h||00h<br />
|-<br />
|65h||00h<br />
|-<br />
|66h||00h<br />
|-<br />
|67h||00h<br />
|-<br />
|68h||00h<br />
|-<br />
|69h||18h<br />
|-<br />
|6Ah||06h<br />
|-<br />
|6Bh||00h<br />
|-<br />
|6Ch||22h<br />
|-<br />
|6Dh||A9h<br />
|-<br />
|6Eh||00h<br />
|-<br />
|6Fh||00h<br />
|}<br />
|<br />
{|<br />
|Port||Value<br />
|-<br />
|70h||00h<br />
|-<br />
|71h||00h<br />
|-<br />
|72h||00h<br />
|-<br />
|73h||00h<br />
|-<br />
|74h||02h<br />
|-<br />
|75h||1Fh<br />
|-<br />
|76h||00h<br />
|-<br />
|77h||00h<br />
|-<br />
|78h||00h<br />
|-<br />
|79h||00h<br />
|-<br />
|7Ah||00h<br />
|-<br />
|7Bh||00h<br />
|-<br />
|7Ch||00h<br />
|-<br />
|7Dh||00h<br />
|-<br />
|7Eh||00h<br />
|-<br />
|7Fh||00h<br />
|}<br />
|}<br />
<br />
<br />
'''Interesting points:'''<br />
* Flash is locked<br />
* 4000h contains flash page 00h<br />
* 8000h contains flash page 00h<br />
* C000h contains ram page 00h<br />
* The LCD driver is disconnected ([[83Plus:Ports:29|port 29]] causes this)<br />
* The boot code is unlocked<br />
* 84+BE/SE cannot be determined from [[83Plus:Ports:21|port 21]] as it reads 33h<br />
* All parts of flash except privileged pages are non-executable (2C-2F, 3F, 6C-6F, and 7F)<br />
* All of ram is non-executable except the first 1024 bytes of ram page 00h<br />
* None of the LCD delay ports are set<br />
* The clock is off<br />
* The USB driver is off<br />
<br />
==Memory Mapping==<br />
Here's where the boot code gets fun. Since on boot all variables and ports have been reset, it would logically follow that execution should start at 0000h. There's a problem though, 0000h is always flash page 00h. In order to beat this, TI actually had to add a hack to put the boot code into the 0000h region.<br />
<br />
* The calculator is in memory map mode 0<br />
* Page 7Fh is swapped into the 0000h region and acts completely normal<br />
* Every other port works exactly how it should<br />
* Page 00h is restored to 0000h when and only when a byte is executed in a memory bank controlled by [[83Plus:Ports:06|port 06]]. This means that in memory map mode 0, a byte must be executed in the 4000h-7FFFh range, and in memory map mode 1, a byte must be executed in the 4000-BFFFh range. When this byte is executed, 00h instantly goes back to 0000h.<br />
<br />
==Gathering this Information==<br />
This information could only be gathered by replacing the boot code. This was a very dangerous operation as one mistake will brick the calculator. You should not attempt to recreate anything on this page or write your own boot code unless you are a master at z80 assembly.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:0E83Plus:Ports:0E2011-11-26T00:45:15Z<p>Thepenguin77: Created page with '0E-0F - Boot Code Paging Boot Code Paging == Synopsis == '''Port Numbers:''' 0Eh and 0Fh '''Function:''' …'</p>
<hr />
<div>[[Category:83Plus:Ports:By_Address|0E-0F - Boot Code Paging]] [[Category:83Plus:Ports:By_Name|Boot Code Paging]]<br />
<br />
== Synopsis ==<br />
'''Port Numbers:''' 0Eh and 0Fh<br />
<br />
'''Function:''' Boot Code Paging<br />
<br />
These ports have no function on the 84+ line. They probably do something on the 83+ line.<br />
<br />
=== Read Values ===<br />
* Bits 0-1: Whatever was last written<br />
* Bits 2-7: always 0<br />
<br />
=== Write Values ===<br />
* Bits 0-1: Set a new value<br />
* Bit 2-7: No effect<br />
<br />
== Comments ==<br />
These two ports are written to very early in the boot code where they both receive 03 then 00. Port 0E is written to first and is used before accessing page 7F in the 8000h region via memory map mode 1. Port 0Fh is written to second before accessing page 7F in the 4000h region via memory map mode 0. Once execution is running normally in the 4000h region, both ports are set back to 00.<br />
<br />
It would seem that port 0E is related to the 8000h range and port 0F is related to the 4000h range, but that might not be correct.<br />
<br />
It has also been confirmed on all three ASIC revisions that this port is not necessary to fix the boot code memory mapping. For more information on that see: [[83Plus:State_of_the_calculator_at_boot|State of the calculator at boot]]</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:5A83Plus:Ports:5A2011-11-07T20:37:38Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|5A - USB Presentation Link Port Mirroring Enable]] [[Category:83Plus:Ports:By Name|USB Presentation Link Port Mirroring Enable]]<br />
{{84P-Only Port|02}}<br />
== Synopsis ==<br />
'''Port Number:''' 5Ah<br />
<br />
'''Function:''' USB Presentation Link Port Mirroring Enable<br />
<br />
This port enables or disables the "Presentation Link port mirroring" hardware, which redirects writes to ports [[83Plus:Ports:10|10]] and [[83Plus:Ports:11|11]] to outgoing bulk endpoint 02.<br />
The TI-84 Plus/Silver Edition OS uses this upon connection of the USB Presentation Link adapter.<br />
<br />
=== Read Values ===<br />
* Bit 0: Set if port mirroring is enabled.<br />
* Bits 1-7: Always 0<br />
<br />
=== Write Values ===<br />
* Bit 0: Set to enable port mirroring.<br />
* Bits 1-7: Not used<br />
<br />
== Comments ==<br />
When this port is set to 1, the USB controller will send a two-byte packet on outgoing bulk endpoint 02 whenever a value is written to ports [[83Plus:Ports:10|10]] and [[83Plus:Ports:11|11]]. You must set up endpoint 02 like this yourself before enabling it.<br />
<br />
When enabled, a write to [[83Plus:Ports:10|port 10]] will cause the following packet to be sent:<br />
<br />
<value written to [[83Plus:Ports:10|port 10]]> 00<br />
<br />
A write to [[83Plus:Ports:11|port 11]] will cause the following packet to be sent:<br />
<br />
<value written to [[83Plus:Ports:11|port 11]]> 01<br />
<br />
This would seem to imply that the second byte is an offset from [[83Plus:Ports:10|port 10]], but this is untested.<br />
<br />
This port only functions in host mode.<br />
<br />
Someone with more experience in making guesses as to what the controller and/or hardware is actually doing here should probably provide more input.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:5B83Plus:Ports:5B2011-11-07T20:36:49Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|5B - USB Protocol Interrupt Enable]] [[Category:83Plus:Ports:By Name|USB Protocol Interrupt Enable]]<br />
{{84P-Only Port|03}}<br />
== Synopsis ==<br />
'''Port Number:''' 5Bh<br />
<br />
'''Function:''' USB Protocol Interrupt Enable<br />
<br />
This port controls whether interrupts should be generated for USB protocol events.<br />
<br />
=== Read Values ===<br />
* Bit 0: Set if USB protocol interrupts are enabled.<br />
* Bit 1: Always 0<br />
* Bit 2: Unknown<br />
* Bits 3-7: Always 0<br />
<br />
=== Write Values ===<br />
* Bit 0: Set to allow USB protocol interrupts<br />
* Bit 1: Not used<br />
* Bit 2: Unknown<br />
* Bits 3-7: Not used<br />
<br />
== Comments ==<br />
When this port is set to 1, the USB controller will generate an interrupt whenever a USB transaction finishes, as well as for various other USB-protocol-related events.<br />
<br />
When such an interrupt occurs, [[83Plus:Ports:55|port 55]] bit 4 will be cleared. Ports [[83Plus:Ports:82|82]], [[83Plus:Ports:84|84]], and [[83Plus:Ports:86|86]] (and possibly 83 and 85) will tell you what event(s) caused the interrupt. Reading from any of these ports also clears it and acknowledges the interrupt.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:3A83Plus:Ports:3A2011-11-03T20:02:40Z<p>Thepenguin77: Created page with '3A - Old USB Flags Old USB Flags {{SE-Only Port|02}} == Synopsis == '''Port Number:''' 3Ah '''Function:''…'</p>
<hr />
<div>[[Category:83Plus:Ports:By_Address|3A - Old USB Flags]] [[Category:83Plus:Ports:By_Name|Old USB Flags]]<br />
{{SE-Only Port|02}}<br />
<br />
== Synopsis ==<br />
'''Port Number:''' 3Ah<br />
<br />
'''Function:''' Old USB Flags<br />
<br />
This port deals with the old USB driver that was only present in 84+BE/SE hardware revisions (none) and A. <br />
<br />
== Old hardware ==<br />
=== Read Values ===<br />
* Bits 0-2 - Used for USB related stuff<br />
* Bit 3 - Set<br />
* Bits 4-7 - Unknown<br />
<br />
=== Write Values ===<br />
* Bits 0-2 - Used for USB related stuff<br />
* Bit 3 - No effect<br />
* Bit 4 - Set after using [[83Plus:Ports:04|port 04]] to check batteries but then reset<br />
* Bits 5-6 - Unknown<br />
* Bit 7 - Set before using [[83Plus:Ports:04|port 04]] to check batteries<br />
<br />
== New Hardware ==<br />
=== Read Values ===<br />
* Bits 0-3 - Reset<br />
* Bits 4-7 - No significance<br />
<br />
=== Write Values ===<br />
* Bits 0-3 - Unchangeable<br />
* Bits 4-7 - Quirky (no effect)<br />
<br />
== Comments ==<br />
The purpose of the lower 3 bits is unknown. Someone with a model (none) or A calculator will have to do some testing. If the old USB hardware is present, most of the USB ports work differently.<br />
<br />
On the old hardware, [[83Plus:Ports:39|port 39h]] also seems to be tied to the functions of this port.<br />
<br />
The upper four bits are quirky and are heavily depend on hardware revision. On at least hardware M, the upper 4 bits are tied to the upper 4 bits of [[83Plus:Ports:39|port 39h]].<br />
<br />
Another way to check for the old USB revision is to check [[83Plus:Ports:15|port 15h]] for the value 44h.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:1583Plus:Ports:152011-11-03T19:40:49Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By_Address|15 - ASIC Version]] [[Category:83Plus:Ports:By_Name|ASIC Version]]<br />
{{SE-Only Port|05}}<br />
<br />
== Synopsis ==<br />
'''Port Number:''' 15h<br />
<br />
'''Function:''' ASIC Version<br />
<br />
This port reports the ASIC version from which the number of ram pages and USB driver revision can be determined.<br />
<br />
=== Read Values ===<br />
* 33 - TI-REF 83PL2M/TA2 - No USB driver and has 128KB of RAM<br />
* 44 - TI-REF 83PLUSB/TA2 - Uses old USB driver and has 128KB of RAM<br />
* 45 - TI-REF 84PLUSB/TA3 - Uses new USB driver and has 128KB of RAM<br />
* 55 - TI-REF 84PLC/TA1 - Uses new USB driver and has 48KB of RAM<br />
<br />
<br />
=== Write Values ===<br />
No effect<br />
<br />
== Comments ==<br />
Even though this port is in the protected range, it can't be written to. So there's really no reason to call it protected.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:By_AddressCategory:83Plus:Ports:By Address2011-10-29T03:24:41Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports|Ports by Address/Number]]<br />
See also [[:Category:83Plus:Ports:By Name|list of ports by name]].<br />
<br />
Please read our page on [[Contributing]] before editing these pages!<br />
<br />
<br />
'''A note about 83+BE ports:''' On the 83+BE, many of the ports have been mirrored to the 00h-07h region. If a port is mirrored, when it is being read, take the bitwise-AND with 07h to find the actual port being accessed. All writes to mirrored ports are ignored.<br />
<br />
Legitimate 83+BE ports (the rest are mirrored):<br />
* '''Read values''' - 00h-07h and 10h-13h are original ports<br />
* '''Write values''' - 00h-07h, 10h-13h, 14h, and 16h are original ports</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:By_AddressCategory:83Plus:Ports:By Address2011-10-28T04:35:12Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports|Ports by Address/Number]]<br />
See also [[:Category:83Plus:Ports:By Name|list of ports by name]].<br />
<br />
Please read our page on [[Contributing]] before editing these pages!<br />
<br />
<br />
'''A note about 83+BE ports:''' On the 83+BE, many of the ports have been mirrored to the 00h-07h region. If a port is mirrored, when it is being read, take the bitwise-AND with 07h to find the actual port being accessed. All write to mirrored ports are ignored.<br />
<br />
Legitimate 83+BE ports (the rest are mirrored):<br />
* '''Read values''' - 00h-07h and 10h-13h are original ports<br />
* '''Write values''' - 00h-07h, 10h-13h, 14h, and 16h are original ports</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:1483Plus:Ports:142011-10-28T04:30:32Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By_Address:Protected|14 - Flash Control]] [[Category:83Plus:Ports:By_Address|14 - Flash Control]] [[Category:83Plus:Ports:By_Name|Flash Control]]<br />
{{Protected Port}}<br />
<br />
== Synopsis ==<br />
'''Port Number:''' 14h<br />
<br />
'''Function:''' Flash Write-Lock Control<br />
<br />
This port controls whether or not the Flash ROM chip will accept write/erase instructions.<br />
<br />
=== Read Values ===<br />
* '''83+ Basic only''': Mirror of [[83Plus:Ports:04|port 04h]].<br />
* '''83+ SE/84+ only''': Reads 0 if the flash is locked, 1 if the flash is unlocked.<br />
<br />
=== Write Values ===<br />
* Write 00h to lock the flash. Write 01h to unlock it.<br />
<br />
== Comments ==<br />
When the flash chip is locked, then write/erase instructions are rejected. In addition, protected pages cannot be read. There is only one protected page. On the normal 83+, this is page 1Eh. On the normal 84+, it is 3Eh. On the 83+ SE and 84+ SE it is 7Eh. This page holds the certification data, which includes ID number, validation number, application authorizations, public keys, and other related data.<br />
<br />
Other protected ports may be written to from any area (unprivledged ROM, RAM, etc) without requiring a special sequence once Flash is unlocked.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:9A83Plus:Ports:9A2011-10-28T04:26:25Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|9A - USB Read Endpoint Type/Address]] [[Category:83Plus:Ports:By Name|USB Read Endpoint Type/Address]]<br />
{{84P-Only Port|02}}<br />
== Synopsis ==<br />
'''Port Number:''' 9Ah<br />
<br />
'''Function:''' USB Read Endpoint Type/Address<br />
<br />
This port determines the endpoint address and transaction type to use when reading from a USB pipe.<br />
<br />
=== Read Values ===<br />
* Unknown<br />
<br />
=== Write Values ===<br />
* Bits 0-3: Source endpoint number (bEndpointAddress.)<br />
* Bits 4-5: Endpoint type (bmAttributes.)<br />
* Bits 6-7: No effect.<br />
<br />
== Comments ==<br />
Each of the USB controller's internal "pipes" (with the possible exception of pipe 0) can be used to send and receive bulk, interrupt, and/or isochronous data packets. This port determines which type of transaction, and which USB endpoint, should be used for data read from the current pipe. (The "current" pipe is determined by [[83Plus:Ports:8E|port 8E]].)<br />
<br />
The low 4 bits of this port are the USB endpoint address, corresponding to the low bits of the bEndpointAddress field in the endpoint descriptor. (Both the OS and USB8x will always use pipe ''n'' for reading from endpoint ''n''; i.e., the low bits of this port will be set to the same value as port 8E. This is probably a good convention to stick to when possible; the effects of remapping endpoints haven't been fully explored.)<br />
<br />
Bits 4-5 are the endpoint type, corresponding to bits 0-1 of the bmAttributes field in the endpoint descriptor:<br />
* 10h = isochronous<br />
* 20h = bulk<br />
* 30h = interrupt<br />
(The transaction type will affect the wire protocol used, and may affect how the controller chooses to schedule parallel transactions in host mode.)<br />
<br />
In addition to this port, you should also initialize [[83Plus:Ports:93|port 93]] (wMaxPacketSize), and possibly [[83Plus:Ports:9B|port 9B]] (bInterval), before requesting data from the pipe. Once the pipe is fully configured for reading, use [[83Plus:Ports:94|port 94]] to request data.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:9883Plus:Ports:982011-10-28T04:25:53Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|98 - USB Write Endpoint Type/Address]] [[Category:83Plus:Ports:By Name|USB Write Endpoint Type/Address]]<br />
{{84P-Only Port|00}}<br />
== Synopsis ==<br />
'''Port Number:''' 98h<br />
<br />
'''Function:''' USB Write Endpoint Type/Address<br />
<br />
This port determines the endpoint address and transaction type to use when writing to a USB pipe.<br />
<br />
=== Read Values ===<br />
* Unknown<br />
<br />
=== Write Values ===<br />
* Bits 0-3: Destination endpoint number (bEndpointAddress.)<br />
* Bits 4-5: Endpoint type (bmAttributes.)<br />
* Bits 6-7: No effect.<br />
<br />
== Comments ==<br />
Each of the USB controller's internal "pipes" (with the possible exception of pipe 0) can be used to send and receive bulk, interrupt, and/or isochronous data packets. This port determines which type of transaction, and which USB endpoint, should be used for data written to the current pipe. (The "current" pipe is determined by [[83Plus:Ports:8E|port 8E]].)<br />
<br />
The low 4 bits of this port are the USB endpoint address, corresponding to the low bits of the bEndpointAddress field in the endpoint descriptor. (Both the OS and USB8x will always use pipe ''n'' for writing to endpoint ''n''; i.e., the low bits of this port will be set to the same value as port 8E. This is probably a good convention to stick to when possible; the effects of remapping endpoints haven't been fully explored.)<br />
<br />
You don't need to use this port to set up pipe 0; I'm not sure whether endpoint remapping works at all with pipe 0.<br />
<br />
Bits 4-5 are the endpoint type, corresponding to bits 0-1 of the bmAttributes field in the endpoint descriptor:<br />
* 00h = control (hypothetical)<br />
* 10h = isochronous<br />
* 20h = bulk<br />
* 30h = interrupt<br />
(The transaction type will affect the wire protocol used, and may affect how the controller chooses to schedule parallel transactions in host mode.)<br />
<br />
In addition to this port, you should also initialize [[83Plus:Ports:90|port 90]] (wMaxPacketSize), and possibly [[83Plus:Ports:99|port 99]] (bInterval), before writing data to the pipe. Once the pipe is fully configured for writing, you can proceed to write data to the appropriate [[83Plus:Ports:A0|Ax port]], then use [[83Plus:Ports:91|port 91]] to send the packet.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:9683Plus:Ports:962011-10-28T04:25:28Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|96 - USB Data-Received Counter]] [[Category:83Plus:Ports:By Name|USB Data-Received Counter]]<br />
{{84P-Only Port|06}}<br />
== Synopsis ==<br />
'''Port Number:''' 96h (LSB), 97h (MSB, hypothetical)<br />
<br />
'''Function:''' USB Data-Received Counter<br />
<br />
This port shows the number of bytes left to read from a USB pipe.<br />
<br />
=== Read Values ===<br />
* Bits 0-7: Number of bytes left to read.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
When a data packet has been received - either an IN packet in host mode, or an OUT packet in peripheral mode - the contents of the packet are stored in an internal buffer in the USB controller. Each pipe has its own buffer; this port tells you how many bytes are currently in the queue for the current pipe. (The "current" pipe is determined by [[83Plus:Ports:8E|port 8E]].)<br />
<br />
The contents of the buffer can be retrieved using the appropriate [[83Plus:Ports:A0|Ax port]]. As you read bytes from the buffer, port 96 will count down to zero.<br />
<br />
Port 97 is probably the MSB; this should be tested. (Note that, for full-speed devices, the maximum size permitted for a single control, bulk, or interrupt data packet is 64 bytes - see sections 5.5 to 5.8 of the USB specification. Isochronous packets may be up to 1023 bytes.)</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:9383Plus:Ports:932011-10-28T04:25:06Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|93 - USB Read Packet Size]] [[Category:83Plus:Ports:By Name|USB Read Packet Size]]<br />
{{84P-Only Port|03}}<br />
== Synopsis ==<br />
'''Port Number:''' 93h<br />
<br />
'''Function:''' USB Read Packet Size<br />
<br />
This port controls the maximum packet size allowed for data read from a USB pipe.<br />
<br />
=== Read Values ===<br />
* Unknown<br />
<br />
=== Write Values ===<br />
* Bits 0-7: Maximum packet size for the current pipe, divided by 8.<br />
<br />
== Comments ==<br />
This port tells the USB controller the maximum allowed packet size for data read from the current pipe. (The "current" pipe is determined by [[83Plus:Ports:8E|port 8E]].)<br />
<br />
The value written to this port is the maximum packet size, or the wMaxPacketSize field in the endpoint descriptor, ''divided by 8''. For an endpoint with a wMaxPacketSize that isn't a multiple of 8, you should presumably round up.<br />
<br />
In host mode, it's important to know the maximum packet size for incoming endpoints, so that the USB controller can schedule transactions properly. I'm not sure what effect this port has in peripheral mode. In any case, it seems wise to configure this port, along with [[83Plus:Ports:9A|port 9A]] (bEndpointAddress / bmAttributes), and possibly [[83Plus:Ports:9B|port 9B]] (bInterval), before requesting any data from a pipe.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:9183Plus:Ports:912011-10-28T04:23:53Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|91 - USB Write Command/Status]] [[Category:83Plus:Ports:By Name|USB Write Command/Status]]<br />
{{84P-Only Port|01}}<br />
== Synopsis ==<br />
'''Port Number:''' 91h<br />
<br />
'''Function:''' USB Write Command/Status<br />
<br />
This port controls the current state of a USB pipe, and allows you to send and receive data packets.<br />
<br />
=== Read Values (control pipe) ===<br />
* Bit 0: Set if a packet has been received. Might also be set at other times.<br />
* Bit 1: Set if we currently have a packet queued to be sent.<br />
* Bit 2: Set if we have sent or received a STALL.<br />
* Bit 3: Unknown<br />
* Bit 4: Set if a an error in transmission has occurred (device not responding or electrical interference)<br />
* Bit 5: Unknown<br />
* Bit 6: Unknown<br />
* Bit 7: Unknown<br />
<br />
=== Write Values (control pipe) ===<br />
* Bit 1: Set to send the currently-buffered data.<br />
* '''Host mode only:'''<br />
** Bit 3: Set (along with bit 1) to send a SETUP packet.<br />
** Bit 5: Set to request a packet from the peripheral.<br />
* '''Peripheral mode only:'''<br />
** Bit 3: Set if the transfer will be complete after sending the current packet, if any.<br />
** Bit 5: Set to flag an error (STALL.)<br />
* Bit 6: Set to reset the pipe's toggle state to DATA1.<br />
* Other bits' effects are unknown, and should be set to 0.<br />
<br />
=== Read Values (bulk/interrupt/iso pipes) ===<br />
* Bit 0: Unknown<br />
* Bit 1: Unknown<br />
* Bit 2: Set in host mode if we have received a STALL. Might also be set in peripheral mode if we have sent a STALL.<br />
* Bit 3: Unknown<br />
* Bit 4: Set if the pipe is halted.<br />
* Bit 5: Set if a an error in transmission has occurred (device not responding or electrical interference)<br />
* Bit 6: Unknown<br />
* Bit 7: Unknown<br />
<br />
=== Write Values (bulk/interrupt/iso pipes) ===<br />
* Bit 0: Set to send the currently-buffered data.<br />
* Bit 3: Unknown, but sometimes used by the OS.<br />
* Bit 4: Set to halt the pipe.<br />
* Bit 6: Set (along with bit 3) to reset the pipe's toggle state to DATA0.<br />
* Other bits' effects are unknown, and should be set to 0.<br />
<br />
== Comments ==<br />
This port reports and controls the I/O state of the current pipe. (The current pipe is selected by [[83Plus:Ports:8E|port 8E]].) This port is used for sending and receiving data on control pipes, as well as for sending data on bulk, interrupt, and isochronous pipes. For receiving bulk/interrupt/iso data, see [[83Plus:Ports:94|port 94]].<br />
<br />
Not all of the bits of this port are understood, and more experimentation would be useful. The output values suggested below are the ones used by USB8x and the OS, but they may not be the only values that work.<br />
<br />
All of the notes below assume that [[83Plus:Ports:8E|port 8E]] is set appropriately. Also be aware that unless you have interrupts disabled, or you're using a USB hook to handle interrupts yourself, the system interrupt handler will get in the way of whatever you're trying to do.<br />
<br />
== Bulk and interrupt transfers ==<br />
The following notes apply to bulk and interrupt pipes; as seen above, the control pipe works quite differently. Isochronous pipes probably work similarly to bulk and interrupt pipes, but this also needs testing, since the low-level protocol is so different.<br />
<br />
Before using the pipe for bulk, interrupt, or isochronous transfers, be sure to configure it using ports [[83Plus:Ports:90|90]], [[83Plus:Ports:98|98]], and [[83Plus:Ports:99|99]].<br />
<br />
=== Resetting the pipe ===<br />
To reset the pipe (un-halt it, and, for bulk and interrupt pipes, reset the toggle state), write a value of '''48h''' to port 91. In peripheral mode, you are expected to do this whenever you receive a Set Configuration request, and whenever you receive a Clear Feature (ENDPOINT_HALT) request (even if the endpoint wasn't halted to begin with.) If you don't, the next packet you send may be lost.<br />
<br />
In host mode, you should reset the pipe whenever you send a Set Configuration request or a Clear Feature (ENDPOINT_HALT) request. USB8x and the OS don't do this, presumably because they only ever send one Set Configuration request after turning on the USB controller, and never send Clear Feature requests.<br />
<br />
=== Halting the pipe (peripheral mode) ===<br />
In peripheral mode, to indicate an error condition on the pipe, or in response to a Set Feature (ENDPOINT_HALT) request, write a value of '''10h''' to port 91. This will cause the controller to send a STALL in response to any IN request on that endpoint.<br />
<br />
=== Sending data ===<br />
To send data to the pipe, first write the data bytes - at most ''wMaxPacketSize'' of them - to the appropriate [[83Plus:Ports:A0|Ax port]], then write a value of '''01h''' to port 91.<br />
<br />
The USB controller will attempt to send the data as soon as it has an opportunity. When the packet is sent, or an error occurs, the appropriate bit of [[83Plus:Ports:82|port 82]] will be set (and an interrupt will be generated.) You can then check port 91 to see what happened:<br />
* Bit 5 will be set if a low-level error occurred. This probably means that the destination endpoint doesn't exist, the device isn't configured, or the device was unplugged.<br />
* '''Host mode only:''' Bit 2 will be set if the destination endpoint is halted (the peripheral device is signalling an error condition.) You will need either to reset the endpoint using a Clear Feature (ENDPOINT_HALT) request, or reset the entire device, in order to proceed.<br />
* Some other types of errors will be reported by [[83Plus:Ports:86|port 86]] instead.<br />
* Otherwise, you can assume the packet was transferred successfully.<br />
<br />
After sending a series of data packets, the OS writes a value of '''08h''' to port 91. I don't know what effect this has.<br />
<br />
== Control transfers (host mode) ==<br />
The following notes apply to pipe zero in host mode, and would probably also apply to any non-zero control pipes.<br />
<br />
A control transfer consists of 3 "stages" - Setup, Data, and Status. For more information about these stages, see section 8.5.2 (1.1) / 8.5.3 (2.0) of the USB specification. Note, in particular, that Data and Status packets need to be handled slightly differently, due to the DATA0/DATA1 toggling behavior.<br />
<br />
=== Sending a setup packet ===<br />
To send a Setup packet, first write the eight data bytes to [[83Plus:Ports:A0|port A0]], then write a value of '''0Ah''' to port 91. As with bulk transactions, the USB controller will attempt to send the data as soon as it has an opportunity. When the packet is sent, or an error occurs, bit 0 of [[83Plus:Ports:82|port 82]] will be set (and an interrupt will be generated.) You can then check port 91 to see what happened:<br />
* Hypothetically, bit 2 would be set if the device rejected the packet (which is not permitted by the USB specification.)<br />
* Bit 4 will be set if a low-level error occurred.<br />
* Some other types of errors will be reported by [[83Plus:Ports:86|port 86]] instead.<br />
* Otherwise, you can assume the packet was transferred successfully.<br />
<br />
=== Sending a data packet ===<br />
To send a "normal" packet (as part of the Data stage of an OUT transfer; note that this is a very uncommon thing to do), first write the data bytes - at most ''bMaxPacketSize0'' of them - to [[83Plus:Ports:A0|port A0]], then write a value of '''02h''' to port 91. This works the same as above, except that the peripheral is allowed to send a STALL response indicating an error; in that case, bit 2 of port 91 will be set.<br />
<br />
=== Sending a status packet ===<br />
To send a status packet (as the Status stage of an IN transfer), write a value of '''42h''' to port 91. This packet should always be empty, so you don't do anything with port A0. As with the above cases, [[83Plus:Ports:82|port 82]] will indicate when the transaction is completed, and port 91 will indicate any errors.<br />
<br />
=== Receiving a data packet ===<br />
To request a "normal" packet (as part of the Data stage of an IN transfer), write a value of '''20h''' to port 91. The USB controller will request data from the peripheral, several times if necessary, until it either receives a valid data packet, a STALL response, or a low-level error occurs. Once any of these things happens, bit 0 of [[83Plus:Ports:82|port 82]] will be set. You can then check port 91 to see what happened:<br />
* Bit 2 will be set if the device sent a STALL (indicating an invalid or unsupported control request.)<br />
* Bit 4 will be set if a low-level error occurred.<br />
* Some other types of errors will be reported by [[83Plus:Ports:86|port 86]] instead.<br />
* Otherwise, you can assume the packet was transferred successfully.<br />
<br />
If the packet was transferred successfully, [[83Plus:Ports:96|port 96]] will indicate the number of bytes received, which you can read from [[83Plus:Ports:A0|port A0]]. Note that neither USB8x nor the OS actually checks port 96; instead, they assume that the packet was the expected size. I don't know the reason for this, and it doesn't seem like a good idea in general.<br />
<br />
Remember that in many cases, the data to be transferred is larger than ''bMaxPacketSize0'', so you may need to receive several packets; stop only when you receive one that is smaller than ''bMaxPacketSize0''.<br />
<br />
=== Receiving a status packet ===<br />
To request a status packet (as the Status stage of an OUT transfer), write a value of '''60h''' to port 91. As with the above case, [[83Plus:Ports:82|port 82]] will indicate when the transaction is completed, and port 91 will indicate any errors. This packet should always be empty.<br />
<br />
== Control transfers (peripheral mode) ==<br />
The following notes apply to pipe zero in peripheral mode, and would probably also apply to any non-zero control pipes. A lot more experimentation would be helpful in this area.<br />
<br />
In peripheral mode, if you want to communicate with a standard USB host such as a PC, you must be able to handle all of the mandatory requests defined in section 9.4 of the USB specification. These include:<br />
* Set Address (&#8594; device)<br />
* Set Configuration (&#8594; device)<br />
* Set Interface (&#8594; interface)<br />
* Set Feature (ENDPOINT_HALT) (&#8594; endpoint)<br />
* Clear Feature (ENDPOINT_HALT) (&#8594; endpoint)<br />
* Get Status (&#8592; device, &#8592; interface, &#8592; endpoint)<br />
* Get Descriptor (&#8592; device)<br />
* Get Configuration (&#8592; device)<br />
* Get Interface (&#8592; interface)<br />
<br />
=== Receiving a setup packet ===<br />
When a setup packet is received, bit 0 of [[83Plus:Ports:82|port 82]] will be set (and an interrupt will be generated.) Bit 0 of port 91 will also be set. [[83Plus:Ports:96|Port 96]] indicates the size of the packet - always 8 for a setup packet - and you can read the packet contents from [[83Plus:Ports:A0|port A0]]. You must then decide what to do in response:<br />
<br />
=== Stalling ===<br />
If you receive an invalid or unsupported request, write a value of '''60h''' to port 91. This is a "protocol stall," and unlike halting a bulk or interrupt endpoint, is not considered a permanent error condition. I think the stall condition will be cleared automatically whenever a setup packet is received; this should be tested.<br />
<br />
=== Handling an IN request ===<br />
If the request is an IN request (bit 7 of ''bRequestType'' set), such as a Get Descriptor request, you are expected to send data back to the host. The ''wLength'' given in the setup packet indicates the maximum total number of bytes the host will accept; you can send fewer than this if you like. Every packet you send, except the last one, must be exactly ''bMaxPacketSize0'' bytes; when you send a packet that's smaller than this, the host will know that you're finished.<br />
<br />
Before sending any data packets, it might be necessary to write a value of '''40h''' to port 91 to clear the pipe's toggle state.<br />
<br />
Then, for each packet except the last one, write the data bytes to [[83Plus:Ports:A0|port A0]], then write a value of '''02h''' to port 91. For the final packet, use a value of '''0Ah''' instead (this will handle the Status stage as well.)<br />
<br />
When each data packet is sent, bit 0 of [[83Plus:Ports:82|port 82]] will be set and an interrupt will be generated.<br />
<br />
I'm not sure what happens if the host stops requesting data and moves on to the Status stage, or begins a new control request, earlier than expected. Possibly port 91 bit 4 would be set in this case.<br />
<br />
=== Handling a zero-length OUT request ===<br />
Most OUT requests (such as Set Address and Set Configuration) have zero length: all of the parameters are provided by the ''wValue'' and/or ''wIndex'' values in the setup packet. In these cases, after performing whatever changes are needed, write a value of '''48h''' to port 91 to acknowledge the request.<br />
<br />
A special case is Set Address: in that case, you must only change your address ''after'' the Status stage is completed. So when you receive a Set Address request, write 48h to port 91, wait until the Status stage finishes (bit 0 of port 82 is set), and ''then'' write the new device address to [[83Plus:Ports:80|port 80]].<br />
<br />
=== Handling an OUT request with data ===<br />
Some OUT requests, such as Set Descriptor, can include additional data after the setup packet. You would presumably need to write some value, possibly 00h, to port 91, to read the next packet in the sequence. This has not been tested.<br />
<br />
After receiving and handling the data, you would use a value of '''48h''', as above, to acknowledge the request.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:9083Plus:Ports:902011-10-28T04:23:27Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|90 - USB Write Packet Size]] [[Category:83Plus:Ports:By Name|USB Write Packet Size]]<br />
{{84P-Only Port|00}}<br />
== Synopsis ==<br />
'''Port Number:''' 90h<br />
<br />
'''Function:''' USB Write Packet Size<br />
<br />
This port controls the maximum packet size allowed for data packets written to a USB pipe.<br />
<br />
=== Read Values ===<br />
* Unknown<br />
<br />
=== Write Values ===<br />
* Bits 0-7: Maximum packet size for the current pipe, divided by 8.<br />
<br />
== Comments ==<br />
This port appears to be the analogue of [[83Plus:Ports:93|port 93]]. As such, it tells the USB controller the maximum allowed packet size for data written to the current pipe. (The "current" pipe is determined by [[83Plus:Ports:8E|port 8E]].)<br />
<br />
The value written to this port is the maximum packet size, or the wMaxPacketSize field in the endpoint descriptor, ''divided by 8''. For an endpoint with a wMaxPacketSize that isn't a multiple of 8, you should presumably round up, but take care never to write more bytes than the actual wMaxPacketSize.<br />
<br />
I'm not sure what effect this port actually has, in either host or peripheral mode. (Would the USB controller automatically split up a large transfer into multiple packets?) In any case, it seems wise to configure this port, along with [[83Plus:Ports:98|port 98]] (bEndpointAddress / bmAttributes), and possibly [[83Plus:Ports:99|port 99]] (bInterval), before writing any data to the pipe.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8F83Plus:Ports:8F2011-10-28T04:23:07Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|8F - VBus Control]] [[Category:83Plus:Ports:By Name|VBus Control]]<br />
{{84P-Only Port|07}}<br />
== Synopsis ==<br />
'''Port Number:''' 8F<br />
<br />
'''Function:''' VBus Control<br />
<br />
Using this port, you can control the VBus line and see its status.<br />
<br />
=== Read Values ===<br />
* Bit 0: Set if VBus is high. (Cutoff between 1.5 V and 3 V)<br />
* Bit 1: Unknown. Peripheral routines like this bit.<br />
* Bit 2: Set if calculator is host.<br />
* Bit 3: Reset if VBus is externally powered.<br />
* Bit 4: Set if VBus is externally powered.<br />
* Bit 5: Always 0<br />
* Bit 6: Set if calculator is successfully hosting a device. It gets set when the device turns on.<br />
* Bit 7: Reset if A-Type cable is currently inserted.<br />
<br />
=== Write Values ===<br />
* Bit 0: Set to power VBus. This will only stick if the USB controller ports are set up correctly. Most notably [[83Plus:Ports:4C|port 4C]] and [[83Plus:Ports:54|port 54]].<br />
* Bit 2: Unknown. Peripheral routines sometimes set this.<br />
* Bits 3-7: No effect<br />
<br />
== Comments ==<br />
If VBus is internally powered and you short circuit it, it will power down. <br />
<br />
Bit 6 is pretty strange, it's not as simple as VBus high, or even VBus supplying power. I lit an LED drawing 30 mA off of VBus and port 6 stayed off. But .5 sec after I plug in a USB device, it sets itself.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8E83Plus:Ports:8E2011-10-28T04:22:28Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|8E - USB Pipe Number]] [[Category:83Plus:Ports:By Name|USB Pipe Number]]<br />
{{84P-Only Port|06}}<br />
== Synopsis ==<br />
'''Port Number:''' 8Eh<br />
<br />
'''Function:''' USB Pipe Number<br />
<br />
This port controls which USB pipe is currently selected for I/O operations.<br />
<br />
=== Read Values ===<br />
* Always 0.<br />
<br />
=== Write Values ===<br />
* Pipe number (values 0 to 3 work; I'm not sure about other values.)<br />
<br />
== Comments ==<br />
The USB controller supports 4 (or possibly more) separate "pipes", which can be used to perform multiple USB transactions simultaneously. Pipe 0 is always used for control transactions (endpoint zero), and behaves strangely in many ways. The other pipes can be used for bulk, interrupt, and/or isochronous transactions; they are typically mapped to endpoints 1 to 3, but do not necessarily need to be.<br />
<br />
This port has no effect on its own; it merely determines which pipe is used by subsequent I/O operations. The following ports are affected by the currently-selected pipe:<br />
* [[83Plus:Ports:90|90]] and [[83Plus:Ports:93|93]] - maximum packet size<br />
* [[83Plus:Ports:91|91]] and [[83Plus:Ports:94|94]] - pipe command/status<br />
* [[83Plus:Ports:96|96]] (and possibly 97) - number of bytes received<br />
* [[83Plus:Ports:98|98]] and [[83Plus:Ports:9A|9A]] - endpoint address and type<br />
* [[83Plus:Ports:99|99]] and [[83Plus:Ports:9B|9B]] - polling interval</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8C83Plus:Ports:8C2011-10-28T04:22:04Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|8C-8D - USB Frame Counter]] [[Category:83Plus:Ports:By Name|USB Frame Counter]]<br />
{{84P-Only Port|04}}<br />
== Synopsis ==<br />
'''Port Number:''' 8Ch (LSB), 8Dh (MSB)<br />
<br />
'''Function:''' USB Frame Counter<br />
<br />
These ports show the current value of the USB frame counter.<br />
<br />
<br />
=== Read Values ===<br />
* Port 8C: Bits 0-7 of the frame counter.<br />
* Port 8D: Bits 8-10 of the frame counter.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
These two ports indicate the frame counter value used (presumably) in the most recently sent or received start-of-frame packet. (In normal operation, SOFs are sent by the host, once per millisecond, and contain an 11-bit counter value.) These ports can be used for timing, or simply as an indication that USB is working (since the USB controller will not generate SOFs unless a device is connected.)</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8A83Plus:Ports:8A2011-10-28T04:21:35Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|8A - USB Input-Enabled Pipes (continued)]] [[Category:83Plus:Ports:By Name|USB Input-Enabled Pipes (continued)]]<br />
{{84P-Only Port|02}}<br />
== Synopsis ==<br />
'''Port Number:''' 8Ah<br />
<br />
'''Function:''' USB Input-Enabled Pipes<br />
<br />
This port is a bitmap of which pipes in the A8h-AFh range are enabled for input. Similar to [[83Plus:Ports:89|port 89]]<br />
<br />
=== Read Values ===<br />
* Bit 0: Hypothetically, set if pipe 8 is enabled for input.<br />
* Bit 1: Hypothetically, set if pipe 9 is enabled for input.<br />
* Bit 2: Hypothetically, set if pipe A is enabled for input.<br />
* Bit 3: Hypothetically, set if pipe B is enabled for input.<br />
* Bit 4: Hypothetically, set if pipe C is enabled for input.<br />
* Bit 5: Hypothetically, set if pipe D is enabled for input.<br />
* Bit 6: Hypothetically, set if pipe E is enabled for input.<br />
* Bit 7: Hypothetically, set if pipe F is enabled for input.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
<br />
== Comments ==<br />
I'm not sure anything on this page has actually been tested, but it should be true.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8983Plus:Ports:892011-10-28T04:20:50Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|89 - USB Input-Enabled Pipes]] [[Category:83Plus:Ports:By Name|USB Input-Enabled Pipes]]<br />
{{84P-Only Port|01}}<br />
== Synopsis ==<br />
'''Port Number:''' 89h<br />
<br />
'''Function:''' USB Input-Enabled Pipes<br />
<br />
This port is a bitmap of which pipes in the A0h-A7h range are enabled for intput. Similar to [[83Plus:Ports:8A|port 8A]].<br />
<br />
=== Read Values ===<br />
* Bit 0: Probably always 0. (Just a guess)<br />
* Bit 1: Set if pipe 1 is enabled for input.<br />
* Bit 2: Set if pipe 2 is enabled for input.<br />
* Bit 3: Set if pipe 3 is enabled for input.<br />
* Bit 4: Hypothetically, set if pipe 4 is enabled for input.<br />
* Bit 5: Hypothetically, set if pipe 5 is enabled for input.<br />
* Bit 6: Hypothetically, set if pipe 6 is enabled for input.<br />
* Bit 7: Hypothetically, set if pipe 7 is enabled for input.<br />
<br />
=== Write Values ===<br />
* No effect</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8883Plus:Ports:882011-10-28T04:20:24Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|88 - USB Output-Enabled Pipes (continued)]] [[Category:83Plus:Ports:By Name|USB Output-Enabled Pipes (continued)]]<br />
{{84P-Only Port|00}}<br />
== Synopsis ==<br />
'''Port Number:''' 88h<br />
<br />
'''Function:''' USB Output-Enabled Pipes<br />
<br />
This port is a bitmap of which pipes in the A8h-AFh range are enabled for output. Similar to [[83Plus:Ports:87|port 87]]<br />
<br />
=== Read Values ===<br />
* Bit 0: Hypothetically, set if pipe 8 is enabled for output.<br />
* Bit 1: Hypothetically, set if pipe 9 is enabled for output.<br />
* Bit 2: Hypothetically, set if pipe A is enabled for output.<br />
* Bit 3: Hypothetically, set if pipe B is enabled for output.<br />
* Bit 4: Hypothetically, set if pipe C is enabled for output.<br />
* Bit 5: Hypothetically, set if pipe D is enabled for output.<br />
* Bit 6: Hypothetically, set if pipe E is enabled for output.<br />
* Bit 7: Hypothetically, set if pipe F is enabled for output.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
<br />
== Comments ==<br />
I'm not sure anything on this page has actually been tested, but it should be true.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8783Plus:Ports:872011-10-28T04:19:59Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|87 - USB Output-Enabled Pipes]] [[Category:83Plus:Ports:By Name|USB Output-Enabled Pipes]]<br />
{{84P-Only Port|07}}<br />
== Synopsis ==<br />
'''Port Number:''' 87h<br />
<br />
'''Function:''' USB Output-Enabled Pipes<br />
<br />
This port is a bitmap of which pipes in the A0h-A7h range are enabled for output. Similar to [[83Plus:Ports:88|port 88]].<br />
<br />
=== Read Values ===<br />
* Bit 0: Probably always 0. (Just a guess)<br />
* Bit 1: Set if pipe 1 is enabled for output.<br />
* Bit 2: Set if pipe 2 is enabled for output.<br />
* Bit 3: Set if pipe 3 is enabled for output.<br />
* Bit 4: Hypothetically, set if pipe 4 is enabled for output.<br />
* Bit 5: Hypothetically, set if pipe 5 is enabled for output.<br />
* Bit 6: Hypothetically, set if pipe 6 is enabled for output.<br />
* Bit 7: Hypothetically, set if pipe 7 is enabled for output.<br />
<br />
=== Write Values ===<br />
* No effect</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8683Plus:Ports:862011-10-28T04:19:38Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|86 - USB Miscellaneous Events]] [[Category:83Plus:Ports:By Name|USB Miscellaneous Events]]<br />
{{84P-Only Port|06}}<br />
== Synopsis ==<br />
'''Port Number:''' 86h<br />
<br />
'''Function:''' USB Miscellaneous Events<br />
<br />
This port reports when various device-level USB events occur.<br />
<br />
=== Read Values ===<br />
'''Reading from this port also clears it. Remember the value you read, because you can't go back and read it again.'''<br />
* Bit 0: Possibly set if the bus has been suspended (no activity for some length of time.)<br />
* Bit 1: Unknown; probably related to HNP and/or SRP.<br />
* Bit 2: Set if a bus reset has occurred (both D+ and D? pulled low for some length of time.)<br />
* Bit 3: Unknown.<br />
* Bit 4: Possibly set if a device has been connected (D+, or maybe D?, pulled high for some length of time.)<br />
* Bit 5: This usually indicates that something was unplugged.<br />
* Bit 6: Unknown; probably related to HNP.<br />
* Bit 7: Calculator cannot provide sufficient power. Usually caused by low batteries, although, some devices cause this every time.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
This port is used to report various bus events, which are not associated with any particular endpoint. Note that this port (probably) only works if [[83Plus:Ports:5B|port 5B]] bit 0 is set. [[83Plus:Ports:Port 8B|Port 8B]] might also act as a mask for this port (note that that port is normally set to A1h in host mode, and 05h in peripheral mode.)</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8583Plus:Ports:852011-10-28T04:19:04Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|85 - USB Read-Pipe Events (continued)]] [[Category:83Plus:Ports:By Name|USB Read-Pipe Events (continued)]]<br />
{{84P-Only Port|05}}<br />
== Synopsis ==<br />
'''Port Number:''' 85h<br />
<br />
'''Function:''' USB Read-Pipe Events<br />
<br />
This port reports when a USB transaction on a "read" pipe has finished. This port hypothetically hold the values for ports A8h-AFh. Similar to [[83Plus:Ports:84|port 84]].<br />
<br />
=== Read Values ===<br />
'''Reading from this port also clears it. Remember the value you read, because you can't go back and read it again.'''<br />
* Bit 0: Hypothetically, set if a read transaction has finished on pipe 8.<br />
* Bit 1: Hypothetically, set if a read transaction has finished on pipe 9.<br />
* Bit 2: Hypothetically, set if a read transaction has finished on pipe A.<br />
* Bit 3: Hypothetically, set if a read transaction has finished on pipe B.<br />
* Bit 4: Hypothetically, set if a read transaction has finished on pipe C.<br />
* Bit 5: Hypothetically, set if a read transaction has finished on pipe D.<br />
* Bit 6: Hypothetically, set if a read transaction has finished on pipe E.<br />
* Bit 7: Hypothetically, set if a read transaction has finished on pipe F.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
See [[83Plus:Ports:84|port 84]]. I'm not sure anything on this page has actually been tested, but it should be true.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8483Plus:Ports:842011-10-28T04:18:24Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|84 - USB Read-Pipe Events]] [[Category:83Plus:Ports:By Name|USB Read-Pipe Events]]<br />
{{84P-Only Port|04}}<br />
== Synopsis ==<br />
'''Port Number:''' 84h<br />
<br />
'''Function:''' USB Read-Pipe Events<br />
<br />
This port reports when a USB transaction on a "read" pipe has finished. This port hold the values for ports A1h-A7h. Similar to [[83Plus:Ports:85|port 85]]<br />
<br />
=== Read Values ===<br />
'''Reading from this port also clears it. Remember the value you read, because you can't go back and read it again.'''<br />
* Bit 0: Always 0.<br />
* Bit 1: Set if a read transaction has finished on pipe 1.<br />
* Bit 2: Set if a read transaction has finished on pipe 2.<br />
* Bit 3: Set if a read transaction has finished on pipe 3.<br />
* Bit 4: Hypothetically, set if a read transaction has finished on pipe 4.<br />
* Bit 5: Hypothetically, set if a read transaction has finished on pipe 5.<br />
* Bit 6: Hypothetically, set if a read transaction has finished on pipe 6.<br />
* Bit 7: Hypothetically, set if a read transaction has finished on pipe 7.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
This port is used to report the status of [[83Plus:Ports:94|port-94]] USB transactions. Note that this port only works if [[83Plus:Ports:5B|port 5B]] bit 0 is set. [[83Plus:Ports:Port 89|Port 89]] might also act as a mask for this port.<br />
<br />
After you write a command to [[83Plus:Ports:94|port 94]], the USB controller will attempt to perform the appropriate transaction for you. This may, of course, take some time (if the calculator is the host, you must wait for the peripheral to respond; if the calculator is the peripheral, you must wait for the host to ask you to speak.) If the calculator is host and the peripheral doesn't have any data to send (it sends a NAK), the controller will need to re-try the transaction, possibly several times. When the transaction actually finishes, a Z80 interrupt will be generated, and the appropriate bit of this port will be set.<br />
<br />
As a host, transactions are considered to have "finished" when the peripheral device has either sent a valid data packet, sent a STALL (indicating an error condition), or failed to reply. Which of these has occurred can be determined from [[83Plus:Ports:94|port 94]] (with [[83Plus:Ports:8E|port 8E]] set appropriately.) [[83Plus:Ports:96|Port 96]] tells you how many data bytes were received.<br />
<br />
As a peripheral, transactions are considered to have "finished" when a valid data packet has been received from the host, or possibly also when the host has tried to send a data packet and the calculator has replied with a STALL.<br />
<br />
Port-91 transactions (i.e., OUT transactions as host, IN transactions as peripheral, and all control transactions) are associated with [[83Plus:Ports:82|port 82]].<br />
<br />
Isochronous transactions haven't been tested, and might behave differently.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8383Plus:Ports:832011-10-28T04:18:03Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|83 - USB Write-Pipe Events (continued)]] [[Category:83Plus:Ports:By Name|USB Write-Pipe Events (continued)]]<br />
{{84P-Only Port|03}}<br />
== Synopsis ==<br />
'''Port Number:''' 83h<br />
<br />
'''Function:''' USB Write-Pipe Events <br />
<br />
This port reports when a USB transaction on a "write" pipe has finished. This port hypothetically holds the values for ports A8h-AFh. Similar to [[83Plus:Ports:82|port 82]]<br />
<br />
=== Read Values ===<br />
'''Reading from this port also clears it. Remember the value you read, because you can't go back and read it again.'''<br />
* Bit 0: Hypothetically, set if a write transaction has finished on pipe 8.<br />
* Bit 1: Hypothetically, set if a write transaction has finished on pipe 9.<br />
* Bit 2: Hypothetically, set if a write transaction has finished on pipe A.<br />
* Bit 3: Hypothetically, set if a write transaction has finished on pipe B.<br />
* Bit 4: Hypothetically, set if a write transaction has finished on pipe C.<br />
* Bit 5: Hypothetically, set if a write transaction has finished on pipe D.<br />
* Bit 6: Hypothetically, set if a write transaction has finished on pipe E.<br />
* Bit 7: Hypothetically, set if a write transaction has finished on pipe F.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
See [[83Plus:Ports:82|port 82]]. I'm not sure anything on this page has actually been tested, but it should be true.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8283Plus:Ports:822011-10-28T04:17:46Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|82 - USB Write-Pipe Events]] [[Category:83Plus:Ports:By Name|USB Write-Pipe Events]]<br />
{{84P-Only Port|02}}<br />
== Synopsis ==<br />
'''Port Number:''' 82h<br />
<br />
'''Function:''' USB Write-Pipe Events<br />
<br />
This port reports when a USB transaction on a "write" pipe has finished. This port holds the values for ports A0h-A7h. Similar to [[83Plus:Ports:83|port 83]].<br />
<br />
=== Read Values ===<br />
'''Reading from this port also clears it. Remember the value you read, because you can't go back and read it again.'''<br />
* Bit 0: Set if any transaction (read or write) has finished on pipe 0.<br />
* Bit 1: Set if a write transaction has finished on pipe 1.<br />
* Bit 2: Set if a write transaction has finished on pipe 2.<br />
* Bit 3: Set if a write transaction has finished on pipe 3.<br />
* Bit 4: Hypothetically, set if a write transaction has finished on pipe 4.<br />
* Bit 5: Hypothetically, set if a write transaction has finished on pipe 5.<br />
* Bit 6: Hypothetically, set if a write transaction has finished on pipe 6.<br />
* Bit 7: Hypothetically, set if a write transaction has finished on pipe 7.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
This port is used to report the status of [[83Plus:Ports:91|port-91]] USB transactions. Note that this port only works if [[83Plus:Ports:5B|port 5B]] bit 0 is set. [[83Plus:Ports:87|Port 87]] might also act as a mask for this port.<br />
<br />
After you write a command to [[83Plus:Ports:91|port 91]], the USB controller will attempt to perform the appropriate transaction for you. This may, of course, take some time (if the calculator is the host, you must wait for the peripheral to respond; if the calculator is the peripheral, you must wait for the host to ask you to speak.) If the calculator is host and the peripheral isn't ready (it sends a NAK), the controller will need to re-try the transaction, possibly several times. When the transaction actually finishes, a Z80 interrupt will be generated and the appropriate bit of this port will be set.<br />
<br />
As a host, control, bulk, and interrupt transactions are considered to have "finished" when the peripheral device has either sent an ACK (indicating the packet was received successfully), sent a STALL (indicating an error condition), or failed to reply. Which of the these has occurred can be determined from [[83Plus:Ports:91|port 91]] (with [[83Plus:Ports:8E|port 8E]] set appropriately.)<br />
<br />
As a peripheral, the transaction is considered to have "finished" when the host has requested, received, and acknowledged the data packet, or the host has requested a data packet and the calculator has replied with a STALL.<br />
<br />
For some bizarre reason, port 91 is also used for IN (as well as OUT/SETUP) control transactions as host, and OUT/SETUP (as well as IN) control transactions as peripheral. In these cases, port 82 bit 0 is set, and [[83Plus:Ports:96|port 96]] (with [[83Plus:Ports:8E|port 8E]] set to 0) tells you how many bytes were received.<br />
<br />
Port-94 transactions (i.e., iso/bulk/interrupt IN transactions as host, and OUT transactions as peripheral) are associated with [[83Plus:Ports:84|port 84]].<br />
<br />
Isochronous transactions haven't been tested, and probably behave somewhat differently.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:8083Plus:Ports:802011-10-28T04:17:30Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|80 - USB Device Address]] [[Category:83Plus:Ports:By Name|USB Device Address]]<br />
{{84P-Only Port|00}}<br />
== Synopsis ==<br />
'''Port Number:''' 80h<br />
<br />
'''Function:''' USB Device Address<br />
<br />
This port controls the current USB device address.<br />
<br />
=== Read Values ===<br />
* Bits 0-6: Current address<br />
* Bit 7: Always 0<br />
<br />
=== Write Values ===<br />
* Bits 0-6: New USB device address<br />
* Bit 7: Not used<br />
<br />
== Comments ==<br />
Since a USB system may have many devices sharing the same data lines, every peripheral device is assigned a unique 7-bit address to identify it. This port is used both to set the calculator's own address (when acting as a peripheral), and to set the address that the calculator is currently "speaking" to (when acting as a host.)<br />
<br />
Remember that when you send or receive a Set Address request, the status stage still uses the old address (see section 9.4.6 of the USB specification), so you shouldn't change this port until after the status stage is finished.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:60-7F83Plus:Ports:60-7F2011-10-28T04:16:37Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|60-7F - 40-5F Mirrors]] [[Category:83Plus:Ports:By Name|40-5F Mirrors]]<br />
== Synopsis ==<br />
'''Port Numbers:''' 60-7F<br />
<br />
'''Function:''' Mirrors of 40-5F<br />
<br />
These ports are all exact mirrors of ports 40-5F. Reading or writing to any of the ports is functionally equivalent to reading or writing to it's 40-5F counterpart.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:5783Plus:Ports:572011-10-28T04:15:40Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|57 - USB Line Event Mask]] [[Category:83Plus:Ports:By Name|USB Line Event Mask]]<br />
{{84P-Only Port|07}}<br />
== Synopsis ==<br />
'''Port Number:''' 57h<br />
<br />
'''Function:''' USB Line Event Mask<br />
<br />
This port controls whether interrupts should be generated when the USB lines change.<br />
<br />
=== Read Values ===<br />
* Bit 0: Set if D+-low events are enabled.<br />
* Bit 1: Set if D+-high events are enabled.<br />
* Bit 2: Set if D&#8722;-low events are enabled.<br />
* Bit 3: Set if D&#8722;-high events are enabled.<br />
* Bit 4: Set if ID-low events are enabled.<br />
* Bit 5: Set if ID-high events are enabled.<br />
* Bit 6: Set if Vbus-high events are enabled.<br />
* Bit 7: Set if Vbus-low events are enabled.<br />
<br />
=== Write Values ===<br />
* Bit 0: Set to allow D+-low events.<br />
* Bit 1: Set to allow D+-high events.<br />
* Bit 2: Set to allow D&#8722;-low events.<br />
* Bit 3: Set to allow D&#8722;-high events.<br />
* Bit 4: Set to allow ID-low events.<br />
* Bit 5: Set to allow ID-high events.<br />
* Bit 6: Set to allow Vbus-high events.<br />
* Bit 7: Set to allow Vbus-low events.<br />
<br />
== Comments ==<br />
This port allows you to trigger an interrupt when one of the USB lines changes from high to low, or low to high. For instance, if bit 6 of this port is set, an interrupt is generated when the Vbus line goes from low to high.<br />
<br />
When such an interrupt occurs, [[83Plus:Ports:55|port 55]] bit 2 will be cleared, and [[83Plus:Ports:56|port 56]] will indicate which event(s) caused the interrupt. To acknowledge the interrupt, clear the appropriate bit of port 57.<br />
<br />
An interrupt only occurs if the line changes while the corresponding bit of this port is set (e.g., if Vbus is already high, and you set bit 6, nothing will happen - Vbus would have to go low and then high again for an interrupt to be generated.)</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:5683Plus:Ports:562011-10-28T04:15:14Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|56 - USB Line Events]] [[Category:83Plus:Ports:By Name|USB Line Events]]<br />
{{84P-Only Port|06}}<br />
== Synopsis ==<br />
'''Port Number:''' 56h<br />
<br />
'''Function:''' USB Line Events<br />
<br />
This port reports which, if any, USB line interrupts have occurred.<br />
<br />
=== Read Values ===<br />
* Bit 0: Set if the D+ line has gone low.<br />
* Bit 1: Set if the D+ line has gone high.<br />
* Bit 2: Set if the D&#8722; line has gone low.<br />
* Bit 3: Set if the D&#8722; line has gone high.<br />
* Bit 4: Set if the ID line has gone low.<br />
* Bit 5: Set if the ID line has gone high.<br />
* Bit 6: Set if the Vbus line has gone '''high'''.<br />
* Bit 7: Set if the Vbus line has gone '''low'''.<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
This port reports when an interrupt has occurred due to one of the USB lines changing from high to low, or low to high.<br />
<br />
Normally, only a subset of the above events are actually enabled; [[83Plus:Ports:57|port 57]] controls which. For instance, when the calculator starts up, the OS initially monitors only the ID-low and Vbus-high events (the former to notify it when an A-cable is plugged in, the latter to notify it when a powered B-cable is plugged in.)<br />
<br />
To acknowledge a USB line interrupt, clear the corresponding bit of [[83Plus:Ports:57|port 57]] (and then set the bit again, if you want to get another interrupt the next time it happens.) If a line has changed state twice, and you've enabled both events, both bits will be set. The only way for bits in this port to be cleared is by clearing the corresponding bit of port 57.<br />
<br />
(If you want to see the ''current'' states of the USB lines, see [[83Plus:Ports:4D|port 4D]].)</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=83Plus:Ports:5583Plus:Ports:552011-10-28T04:14:45Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports:By Address|55 - USB Interrupt State]] [[Category:83Plus:Ports:By Name|USB Interrupt State]]<br />
{{84P-Only Port|05}}<br />
== Synopsis ==<br />
'''Port Number:''' 55h<br />
<br />
'''Function:''' USB Interrupt State<br />
<br />
This port reports which USB interrupts have occurred.<br />
<br />
<br />
=== Read Values ===<br />
* Bit 0: Normally set. Cleared for some (unknown, unusual) type of event.<br />
* Bit 1: Normally set.<br />
* Bit 2: Normally set. Cleared if a USB line interrupt has occurred.<br />
* Bit 3: Normally set.<br />
* Bit 4: Normally set. Cleared if a USB protocol interrupt has occurred.<br />
* Bit 5: Always 0<br />
* Bit 6: Always 0<br />
* Bit 7: Always 0<br />
<br />
=== Write Values ===<br />
* No effect<br />
<br />
== Comments ==<br />
Normally, the value of this port will be 1Fh. When a USB interrupt occurs, one or more of the bits will be cleared.<br />
<br />
USB line interrupts are triggered when one of the four functional USB lines changes from low to high or high to low. [[83Plus:Ports:57|Port 57]] controls when these interrupts occur. When a line interrupt occurs, [[83Plus:Ports:56|port 56]] tells you which of the lines has changed. Use port 57 to acknowledge the interrupt.<br />
<br />
USB protocol interrupts are triggered when (a) a USB device-level event occurs, such as a bus reset, or (b) a USB transaction finishes. [[83Plus:Ports:5B|Port 5B]] controls whether these interrupts occur. When one does, ports [[83Plus:Ports:82|82]], [[83Plus:Ports:84|84]], and [[83Plus:Ports:86|86]] (and possibly 83 and 85) will tell you what event(s) caused the interrupt. Reading from any of these ports also clears it and acknowledges the interrupt.<br />
<br />
Bit 0 indicates some other, and uncommon, type of event - possibly that the bus has been suspended. I think that this is also controlled by port 5B, and zeroing port 5B will acknowledge the interrupt. This should be tested.</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:By_AddressCategory:83Plus:Ports:By Address2011-10-28T04:11:26Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports|Ports by Address/Number]]<br />
See also [[:Category:83Plus:Ports:By Name|list of ports by name]].<br />
<br />
Please read our page on [[Contributing]] before editing these pages!<br />
<br />
'''A note about 83+BE ports:''' On the 83+BE, many of the ports have been mirrored to the 00h-07h region. If a port is mirrored, take the bitwise-AND with 07h to find the actual port being accessed. <br />
* '''Read values''' - all ports except 10h-13h have been mirrored<br />
* '''Write values''' - all ports except 10h-13h, 14h, and 16h have been mirrored</div>Thepenguin77https://wikiti.brandonw.net/index.php?title=Category:83Plus:Ports:By_AddressCategory:83Plus:Ports:By Address2011-10-28T04:11:08Z<p>Thepenguin77: </p>
<hr />
<div>[[Category:83Plus:Ports|Ports by Address/Number]]<br />
See also [[:Category:83Plus:Ports:By Name|list of ports by name]].<br />
<br />
Please read our page on [[Contributing]] before editing these pages!<br />
<br />
'''A note about 83+BE ports:''' On the 83+BE, many of the ports have been mirrored to the 00h-07h region If a port is mirrored, take the bitwise-AND with 07h to find the actual port being accessed. <br />
* '''Read values''' - all ports except 10h-13h have been mirrored<br />
* '''Write values''' - all ports except 10h-13h, 14h, and 16h have been mirrored</div>Thepenguin77