So let me make sure I have this right: if I turn this into a flash app, there are two benefits.
1. I don't need OFFSCRPT, because I can just do bcall(_PowerOff) and the app will continue running after the calculator is turned on.
2. It is easier to use a RawKeyHook.
Are either of these incorrect?
The reason for using an app is because the app will be stored on a flash page at the same location all the time, so when your Raw Key Hook runs it knows exactly where to run its code from. I'm not sure how to get it to run from RAM either. There are a couple things to keep in mind when writing a flash app, however. The first is that flash can't be overwritten the same way as RAM, your variables won't work if you store them in the program. It won't crash, it just won't update the value because that's not how flash works. The other is you can't use _PutS to draw a string unless the string is in RAM. The reason for this is that your app is in flash, in the bank stored at $4000-$7FFF, which is also where the bcall code will get loaded. The calculator uses what are called pages since we only have access to 16 bit registers, which can't access the calc's entire memory (think about it, how many bytes of flash are there? what's the max value a 16-bit number can hold?). Fortunately, the solution is pretty simple. The _PutC bcall will do all the work for you, you just need to check for the final 0. So something like:

Code:
;hl holds the string to display, null terminated
_PutSApp:
    ld a,(hl)
    inc hl
    or a
     ret z            ; exit the routine if the next character is a 0
    bcall(_PutC)
    jr _PutSApp


To answer your questions:
1. You could use _PowerOff in your current program to accomplish the same thing, the only thing is that you would have to run it every time you wanted to lock your calculator. With an application you could write a proper offscript which sets up the RawKeyHook for you.
2. For what you want, i think the OffScrpt + RawKeyHook combo is the best. I'm not really sure what the issue with OnScrpt is, i've never bothered messing with either of them before now.

EDIT: Changed the _PutS to _PutC, sorry!
Sorry, but I am still slightly confused.
Quote:
1. You could use _PowerOff in your current program to accomplish the same thing, the only thing is that you would have to run it every time you wanted to lock your calculator. With an application you could write a proper offscript which sets up the RawKeyHook for you.

Do you mean that, aside from the RawKeyHook, my program could work perfectly as a program, not an app? I'm just curious: I am anyway going to turn this into an app. Although one day, if I find a way to run a RawKeyHook from RAM, I can convert this back into a program.

In the sample code you gave, you wrote bcall(_PutS). Did you mean bcall(_PutC)? Also, how do I get the string to an area of scrap RAM? Would I use some code like this:

Code:
ld hl,scrapram
ld (hl),asciicodeoffirstletter
inc hl
ld (hl),asciicodeofsecondletter
inc hl

Or is there some more efficient way?

EDIT1: I just realized a dangerous disadvantage of making this an app. If I forget the password or the app malfunctions, I cannot simply take out the batteries or press the reset button, because that would only clear RAM, and this would be stored in flash. Unless I am incorrect about battery removal/the reset button not working, I am not going to take the risk of running this as an app.

EDIT2: I have optimized/corrected my code, and it has gone back to crashing unless I press CLEAR, creating the AppVar (205 bytes), and crashing when I turn the calculator off (which is to be expected, because I don't have the RawKeyHook).

EDIT3: Isn't it possible to have a program in RAM that stores the RawKeyHook in Archive? Wouldn't that solve the problem?

EDIT4: Ignore Edit 3, I just realized how stupid I am.
I solved your problem a long time ago.

EDIT: Nope, I solved it for the 83 and 84+
scAFwATLxpKzRCmVaHv wrote:

Do you mean that, aside from the RawKeyHook, my program could work perfectly as a program, not an app? I'm just curious: I am anyway going to turn this into an app. Although one day, if I find a way to run a RawKeyHook from RAM, I can convert this back into a program.

No, it just means that you could potentially avoid having to mess with key hooks and Offscripts....

scAFwATLxpKzRCmVaHv wrote:
In the sample code you gave, you wrote bcall(_PutS). Did you mean bcall(_PutC)? Also, how do I get the string to an area of scrap RAM? Would I use some code like this:

Code:
ld hl,scrapram
ld (hl),asciicodeoffirstletter
inc hl
ld (hl),asciicodeofsecondletter
inc hl

Or is there some more efficient way?

Yes, I believe chickendude means PutC in this case. It is just to make sure that you don't go over a page boundary, and if you do it that way, there is no point in copying it to RAM. I would use something like ldi, and if the current address holds a 0, then quit.

Something like this can copy a null-terminated string to RAM:

Code:
 ld de,SafeRAMPlace
 ld hl,String
CopyToRAM:
 ld a,(hl)
 ldi
 or a
 jr nz,CopyToRAM
Yeah, it should've been _PutC, sorry about that. The reason you have to do it that way is because your string is stored on a flash page (in your app). When the bcall is loaded, the flash page the bcall is on gets loaded into the memory bank where your flash page was ($4000-$7FFF). So if your string is at $413F in your app, it will load whatever's at $413F on the flash page the bcall is on, so who knows what it will read. _PutC works because it doesn't read a value from RAM, it draws whatever is in A. To copy your string into RAM, you would do something like:

Code:
    ld hl,string
    ld de,saferamlocation
    ld bc,30    ;max size you think your string will be
    ldir
To display it, you can do "ld hl,saferamlocation \ bcall(_PutS)". The RAM page ($8000-$BFFF) won't get switched out unless you manually do it, so there won't be any problems.

Also, don't worry about not being able to get back into your calc. If you take the batteries out a RAM clear will set things back to normal. (EDIT: ie, delete your offscrpt appvar)

Having it as a program would be much simpler because as Mateo said you don't need to worry about key hooks and all that, just manually run the program whenever you want to lock your calc.

If you are really determined to have this work every time you turn the calc off, the only way i see is writing an app. Honestly, i don't think it's worth it as this doesn't really teach you much about assembly, just about bcalls and how the OS operates, but if that's what you're more interested in (learning how to work alongside the OS rather than programming games) then it could be a good exercise.
I am still confused. I apologize for constantly mentioning the program vs. app decision, but it is a big one: converting my program into an app would take a long time, so I need to be sure that it is worth it.

What I am still confused about is this:
Quote:
Having it as a program would be much simpler because as Mateo said you don't need to worry about key hooks and all that, just manually run the program whenever you want to lock your calc.

Why don't I need key hooks and all that in a program? Doesn't GetKey freeze
Quote:
the system since interrupts have been disabled
by OFFSCRPT regardless of whether it is a program or an app? Meaning I would need a RawKeyHook either way? Or have I been misinterpreting the need for a RawKeyHook this entire time?
You don't need hooks in the program because when you want to lock your calc, instead of pressing [2nd] + [On] you would run your program. Your program would turn the calc off with _PowerOff and continue execution when you turn the calc back on. Since your program is running the entire time (you aren't in the OS like with your previous method, you're still running your program's code), you don't need to worry about a key hook/offscrpt. Those're only to steal execution back from the OS.

Regarding the second bit, i'm not sure if you know what interrupts are. When they are enabled, every so often (at regular intervals or when certain events happen, like pressing the [On] key or inserting a link cable) the calculator will interrupt your code to run what is called an interrupt. That's how things like the run indicator work, through an interrupt, they run in the background. Apparently interrupts are disabled before calling your OFFSCRPT. If your OFFSCRPT code contains a _GetKey bcall, _GetKey's code contains a halt. What halt does is halt execution until the next interrupt comes. However, since interrupts are disabled, the halt will wait forever since no interrupt will ever come. The only solution is taking out a battery.

The point of the OFFSCRPT is to create a RawKeyHook which will run immediately upon turning the calc back on. It's sort of a hacky alternative to using onscrpt (which supposedly is not very reliable? I've never tried it so i couldn't say). So yes, if you take the offscrpt route, you will need a raw key hook. The raw key hook will contain the code you actually want to run when the calc turns back on, the offscrpt will only handle the creation of that RawKeyHook. With a flash app, this code can stay in your flash application.

EDIT: It's also worth noting that you should remove your raw key hook so that it doesn't constantly run whenever you press a key. It will get installed when the calc turns off, and removed when you regain access to your calc. If you've still got questions, let me know. I'd be happy to help you get the framework set up for an app/raw key hook combo, and then you can fill in the code. Are you using spasm?
The reason I was confused is that bcall(_PowerOff) doesn't continue execution when the calculator is turned back on. The program execution ends upon a bcall(_PowerOff). At least, it does on the color edition. That was why, at the beginning of this thread, I tried code to turn off the calculator in a way that would resume program execution when the calculator is turned back on. And it turned out to be too complicated to properly turn off the calculator without bcall(_PowerOff), hence the start of the whole OFFSCRPT business.

Thus, whether I use a program or an app, I need an OFFSCRPT and RawKeyHook. According to you, the reason to use an app is to have a place to safely store the RawKeyHook. However, if I write the program such that I run it to lock my calculator, the RawKeyHook only needs to be safe temporarily, so I can safely store it in an area of RAM like, say, plotSScreen (since this program does not use graphing at all).

Thus--and correct me if I have been incorrect pertaining to anything in this post--I do need an OFFSCRPT and RawKeyHook, but I can still make this a program, not an app.
Ah, i didn't know that about _PowerOff. The problem is none of us here (Mateo and i) know how to run a raw key hook from RAM. Running it from a flash application is simple enough, but running it from RAM appears to be much more complicated. I tried several different ideas but wasn't able to get my code to actually run. That's the reason for writing an app. For one, it will be much more stable and two much simpler. Just "in a,(6)" to get the current flash page.
Makes me wonder if it would be possible to instead of doing _PowerOff, if it would be possible to alter the APD timer, and have it shut down that way. I've not tried that, and it would probably exit the program as well, but it might be worth a shot... A TSR might also be another option: http://tutorials.eeems.ca/ASMin28Days/lesson/day23.html

Using the TSR, you might be able to check the state of the [ON] key flag before the OS does, (Or just directly run the program), in which case you might be able to take control, turn off the LCD since that draws power (Either through port manipulation, or by the following bcalls I haven't tested yet, but could be useful...) And then just wait for the user to press a button to turn it back on. It might take me a little while to make this work, but I can try.

The other option would be to make it an APP, which I do know how work with better. Also, I have a nice template for creating APPS if you would like that more, so that way you don't have to spend too much time on it. Well, that's my brainstorm process, let me know what you prefer. Smile
The App route is defintely perferable, as we should be able to get that to work right
BTW: I also assumed that _PowerOff did that as well, until I took a look at the documentation. Oops. Sad


Code:
_BacklightPowerOnInit   .equ   555Dh
_BacklightExitPowerSave   .equ   5560h
_BacklightEnterPowerSave   .equ   5563h
_BacklightAdjust2x   .equ   5566h


Also, I apologize for the long roundabout way that this went, I just don't have that much inner knowledge of the workings of the OS. I would like to help more, but I am afraid that I am somewhat limited in my knowledge. Sad I'll try and ask Kerm and others who will definitely be able to provide more assistance. Smile
MateoConLechuga wrote:
Makes me wonder if it would be possible to instead of doing _PowerOff, if it would be possible to alter the APD timer, and have it shut down that way. I've not tried that, and it would probably exit the program as well, but it might be worth a shot... A TSR might also be another option: http://tutorials.eeems.ca/ASMin28Days/lesson/day23.html

Using the TSR, you might be able to check the state of the [ON] key flag before the OS does, (Or just directly run the program), in which case you might be able to take control, turn off the LCD since that draws power (Either through port manipulation, or by the following bcalls I haven't tested yet, but could be useful...) And then just wait for the user to press a button to turn it back on. It might take me a little while to make this work, but I can try.

The other option would be to make it an APP, which I do know how work with better. Also, I have a nice template for creating APPS if you would like that more, so that way you don't have to spend too much time on it. Well, that's my brainstorm process, let me know what you prefer. Smile
The App route is defintely perferable, as we should be able to get that to work right
BTW: I also assumed that _PowerOff did that as well, until I took a look at the documentation. Oops. Sad


Code:
_BacklightPowerOnInit   .equ   555Dh
_BacklightExitPowerSave   .equ   5560h
_BacklightEnterPowerSave   .equ   5563h
_BacklightAdjust2x   .equ   5566h


Also, I apologize for the long roundabout way that this went, I just don't have that much inner knowledge of the workings of the OS. I would like to help more, but I am afraid that I am somewhat limited in my knowledge. Sad I'll try and ask Kerm and others who will definitely be able to provide more assistance. Smile

I know that on the non-CSE 83+/84+ calculators you can alter "apdTimer" & "apdSubTimer" to manually APD the calculator (I experimented this when fixing a bug in AB5). It didn't exit the program - turning the calculator on simply resumed execution where it left off. The catch was that the LCD contents were saved to "saveSScreen", so you can't have any sensitive data stored there.

On the 83+ series, apdTimer resets to $74 whenever a key is pressed. apdSubTimer continually counts down from $FF to $00; each time it reaches $00, it decrements apdTimer by 1. If a key is pressed, the cycle starts again. If apdTimer reaches $00, the calculator APDs.

I'm not sure how the 84+CSE works when it APDs in regards to saving the LCD contents - there's one way to find out though Smile

The equates for the mentioned APD RAM areas on the TI-84+CSE are:
apdSubTimer .equ 8456h
apdTimer .equ 8457h
Thanks James! I'll give that I try at some point and see if I can do that. This would mean that the program route is also a viable option, if this works the way I hope it does. Razz Since the APD is interrupt-based, that would mean that many things could also be fixed... (Mateo ponders)

Well, Mateo finished pondering and wishes he had reached this topic sooner... Neutral

So, looking at your very first post, it looks like you just wanted a way to turn off the calculator and turn it back on while maintaining your program's state? I think this was preferable, if I remember correctly. Now we can avoid all the KeyHook craziness and OffScript oddness and focus on getting things done... I think...
So, here's the code that I have working right now; just run it, the calculator turns off, Press the [ON] key to turn it back on, and from there you can do whatever you like. The _GetKey call is in there because it is very useful when working with the APD; take a look at its documentation for more information. Hope this helps! Smile

EDIT: If the password fails, just jump back to the PasswordProgram label, which will take care of everything again.

Code:
.nolist
   #include "ti84pcse.inc"
   #define MathPrintFlags1 $44
   #define MathPrintActive 5
.list
   .org UserMem-2
   .db tExtTok,tAsm84CCmp

PasswordProgram:
   ei
   bcall(_EnableAPD)  ; Make sure it's actually working
   ld a,1
   ld (apdTimer),a
   ld (apdSubTimer),a
   res MathPrintActive,(iy+MathPrintFlags1)
   bcall(_maybe_ClrScrnFull)   ; I don't know what you have it defined as, but this is what it is for me in my include file. Change it to whatever clears the screen
   bcall(_HomeUp)
   ld hl,PressText
   bcall(_PutS)
   bcall(_NewLine)
   bcall(_NewLine)
   bcall(_PutS)
   bcall(_GetKey)
   bcall(_NewLine)
   di         
   
               ; This is where you can put in your password getting code and stuff

   ei
   ret
   
PressText:
   .db "Calculator Locked.",0
   .db "Press Enter...",0


Also, because chickendude had the original idea:
chickendude wrote:
Also, another option might be installing an interrupt (again, not generally something you will be messing with in your first project). I see in ti83plus.inc that there is an "apdtimer" equate, i wonder if that's where the OS counts down for the APD (auto-powerdown)? If there's also an equate for the CSE that would be great, perhaps you could check if it = a certain value (for example, 3) then take control of the calc before it actually APDs. When the calc turns back on, ask for the password then reset the APD value.


So yes, you could also implement a custom interrupt or TSR which will execute when your calculator powers down as well. Razz (A little bit too advanced though for this program, but I imagine it could be possible.)
Before I start with my questions again, let me thank you all for your very major help in this project. I am very grateful.

MateoConLechuga/chickendude/JamesV, y'all's (or whatever the English second person plural genitive pronoun is) solution worked perfectly. I am concerned about only one thing. Does the APD power-off completely turn off the calculator, or is the calculator in some special mode caused by APD that isn't as power-saving as a normal power-off?

Actually, I am concerned about one more thing, more important than my aforementioned concern: I am able to press ON during the program to get into the calculator anyway. I thought that the "di" instruction in MateoConLechuga's code would solve that problem, but apparently it doesn't. So how do I disable the ON-interrupt during a program?

Here is my modified version of MateoConLechuga's code, in case that helps. Actually, never mind: it's pretty much the exact same as his code. But whatever:

Code:
.nolist
   #include "ti84pcse.inc"
   #define MathPrintFlags1 $44
   #define MathPrintActive 5
.list
   .org UserMem-2
   .db tExtTok,tAsm84CCmp

PasswordProgram:
   ei
   bcall(_EnableAPD)
   ld a,1
   ld (apdTimer),a
   ld (apdSubTimer),a
   res MathPrintActive,(iy+MathPrintFlags1)
   bcall(_ClrScrnFull)
   bcall(_HomeUp)
   ld hl,PressText
   bcall(_PutS)
   bcall(_NewLine)
   bcall(_NewLine)
   bcall(_PutS)
   di
   bcall(_GetKey)
   ei
   bcall(_NewLine)
   ret
PressText:
   .db "Calculator locked.",0
   .db "Press enter...",0
You really don't want to disable interrupts before going into _GetKey, that will freeze your calc. _GetKey has a halt instruction which waits for the next interrupt. Since interrupts are disabled, it will wait forever. Also, at least on the 83+ series, _GetKey can be a good way for RAM leaks (pressing [2nd] + [On] will exit the program without clearing up all the RAM). A RAM clear will fix that, though. I would recommend NOT using _GetKey and using either _GetCSC or direct input. However, since these do not pause execution to wait for a key, you need to put them in a loop:

Code:
waitKey:
    bcall(_GetCSC)
    inc a       ;i believe _getcsc returns $FF if no key was pressed, it might be 0
     jr z,waitKey  ;.. i haven't used it in a long time ;)
    ret


Btw, in your code, you don't do any key checking so pressing any key should continue after _GetKey.

Regarding the power usage, the calc is never completely turned off. If it did that you would lose your RAM every time the calc turned off. The RAM needs some power to keep it alive, that's what the backup battery is for on the 83+ series. I don't know enough about the hardware behind the calc to say much more, just that i think you can assume that it will consume very little power that way. What your calc should do is turn off the LCD then go into a halt instruction. Halt puts the calc in low-power mode and waits for an interrupt. Here it will be waiting for an on interrupt telling it to turn the calc back on.
scAFwATLxpKzRCmVaHv wrote:
Before I start with my questions again, let me thank you all for your very major help in this project. I am very grateful.

MateoConLechuga/chickendude/JamesV, y'all's (or whatever the English second person plural genitive pronoun is) solution worked perfectly. I am concerned about only one thing. Does the APD power-off completely turn off the calculator, or is the calculator in some special mode caused by APD that isn't as power-saving as a normal power-off?

As chickendude said, using _GetKey is generally a bad habit in assembly programs; _getcsc inside a loop to wait for a keypress is better Smile

If it's any help, you can find a copy here of a program I wrote years ago called Lock83+ that essentially did what you're trying to do here, albeit for the TI-83+. The source code is included (although there could be some horrible techniques in there, I wrote it ~15 years ago Razz ).
Yes, I agree with all of the above the _GetKey is not the best option to use. However, it is used merely to demonstrate the different options available. The output for _GetKey is more numerous than _GetCSC, and can be useful in figuring out some things. I would recommend that you don't use it however, as it could lead to some potential problems. As for the power down, it is pretty much just like when you leave your calculator on and it turns off for you, so there is a pretty good percentage of power conserved.

The reason I disabled the interrupts for that bit is because want to prevent the APD from executing while the program is running. It's not really all that necessary, however.

EDIT: Also, why do you want to disable the [ON] interrupt? Wouldn't that mean you couldn't turn on your calculator?
Quote:
EDIT: Also, why do you want to disable the [ON] interrupt? Wouldn't that mean you couldn't turn on your calculator?

I want to disable the ON interrupt after the calculator is turned on (in which case APD should, indeed, be disabled after the calculator has turned on again). That way, the password program actually protects my calculator: otherwise, people could just press ON and stop the program, thus getting access to my calculator. So do any of you know a good way to disable the ON interrupt, or do I have to use ports?

I shall continue using GetKey unless it does crash the calculator when I complete the program. Since you are experts, it probably will, but still, I just want to be absolutely sure that I have to use GetCSC. I don't need to worry about memory leaks, because I am smart enough not to turn the calculator off during GetKey, and if I publish this program, I will include a warning not to do so in the readme.

Quote:
What your calc should do is turn off the LCD then go into a halt instruction. Halt puts the calc in low-power mode and waits for an interrupt. Here it will be waiting for an on interrupt telling it to turn the calc back on.

So is that the same thing that the calculator does when a user presses 2nd + OFF? So essentially, what I am asking is: is what happens
Quote:
when you leave your calculator on and it turns off for you
the same as what happens when you manually turn your calculator off?
scAFwATLxpKzRCmVaHv wrote:
I want to disable the ON interrupt after the calculator is turned on (in which case APD should, indeed, be disabled after the calculator has turned on again). That way, the password program actually protects my calculator: otherwise, people could just press ON and stop the program, thus getting access to my calculator. So do any of you know a good way to disable the ON interrupt, or do I have to use ports?
The [ON] key will only be a problem if you use _GetKey; using _GetCSC will avoid this (_GetCSC doesn't read the [ON] key).

Quote:
I shall continue using GetKey unless it does crash the calculator when I complete the program. Since you are experts, it probably will, but still, I just want to be absolutely sure that I have to use GetCSC. I don't need to worry about memory leaks, because I am smart enough not to turn the calculator off during GetKey, and if I publish this program, I will include a warning not to do so in the readme.
Just be prepared that if you do publish the program in this state - even with a warning in the readme - it's quite possible you'll get emails from annoyed users who have had to reset their calculator because they didn't read the readme properly. Sad, but often the case Razz

Quote:
Quote:
What your calc should do is turn off the LCD then go into a halt instruction. Halt puts the calc in low-power mode and waits for an interrupt. Here it will be waiting for an on interrupt telling it to turn the calc back on.

So is that the same thing that the calculator does when a user presses 2nd + OFF? So essentially, what I am asking is: is what happens when you leave your calculator on and it turns off for you the same as what happens when you manually turn your calculator off?
I believe that in terms of power consumption, pressing [2nd]+[ON] to turn the calculator off is the same as the calculator turning off via APD, although Kerm, BrandonW or DrDnar would probably know 100% (I can't see why it would be different though).
scAFwATLxpKzRCmVaHv wrote:
I shall continue using GetKey unless it does crash the calculator when I complete the program. Since you are experts, it probably will, but still, I just want to be absolutely sure that I have to use GetCSC. I don't need to worry about memory leaks, because I am smart enough not to turn the calculator off during GetKey, and if I publish this program, I will include a warning not to do so in the readme.
The problem with this is that it effectively nulls the usefulness of your program. Pressing [2nd] + [On] will exit the program (without the _DelMem to free up the RAM allocated to run your program) and turn the calc off. When you turn it back on, you'll be at the homescreen, effectively bypassing your password protection. _GetCSC is also really simple to use, it scans the entire keyboard for you, just ignoring [On]. It also registers [2nd] as a keypress, so you won't get the up arrow cursor with _GetCSC.

I also think that it should be the same amount of power consumption since the LCD will be turned off and executing a halt instruction, but one of the hardware gurus would know for certain.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 2 of 5
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement