/******************************************************************************
*
* project name:  TIGCC Tools Suite
* file name:     ttbatt.c
* initial date:  30/01/2002
* authors:       Lionel Debroux (xdanger1@caramail.com)
*                Francesco Orabona (bremen79@infinito.it)
*                ExtendeD (ola.e-ml@wanadoo.fr)
*
* description:   battery state evaluation
*
* Credits go to Guillaume de Vivies (gdv@fr.fm) and Loic Minier (Lool@fr.fm)
* for the original HW1 source written for TEX and to Thomas Nussbaumer for
* the combined HW1/H2 version taken from battery.c, part of the TICT explorer.
*
* Bugfixing and size optimization done by Francesco Orabona (1.3)
* Additionally Bugfixing by ExtendeD (1.4)
*
* tigcc -Os -Wall -W -Wwrite-strings -fomit-frame-pointer ttbatt.c
*
* $Id: ttbatt.c,v 1.4 2002/02/28 10:52:44 tnussb Exp $
*
******************************************************************************/

#define USE_TI89
#define USE_TI92PLUS

#define OPTIMIZE_ROM_CALLS
#define NO_EXIT_SUPPORT
#define NO_AMS_CHECK
#include <tigcclib.h>

//----------------------------------------------------------------------------
// INFORMATIONS TAKEN FROM J89HW.TXT by Johan Eilert <johei804@student.liu.se>
//
// $600000 RW ($00)
//      :7      Keep clear (=0)
//      :6      Keep clear (=0)
//      :5-3    -
//      :2      Battery voltage level is *above* the trig level.
//              (see $600018).
//      :1-0    -
//
//$600018 RW ($0380)
//      :15-10  -
//      :9-7    Battery voltage trigger level (see $600000:2)
//              (HW2: must also enable batt checker at $70001D:3,0)
//                0: ~4.6V, 1: ~4.5V, 2: ~4.3V, 3: ~4.0V,
//                4: ~3.7V, 5: ~3.4V, 6: ~3.2V, (7: ~2.9V  calc resetted!)
//              Remember to wait a while (~250us) before reading from
//              $600000:2 to make sure that the hardware has stabilized.
//              Keep the trig level set to the lowest voltage (%111) when
//              its not in use (The keyboard does not work otherwise).
//              AMS displays "BATT" when the voltage drops below 4.3V and
//              4.0V, respectively.
//      :6-0    Keyboard col mask, bit =1 masks key column (vertical) from
//              being read at $60001B and generate interrupt on key pressed.
//      Note: Some interrupt handlers in AMS writes to this register, so it
//      is a very good idea to disable interrupts first!!!
//
//$70001D RW ($06)
//      :7      Toggles every FS (every time the LCD restarts at line 0)
//      :6-4    -
//      :3      Battery checker bit B (? ???)
//      :2      ? (set)
//      :1      Screen enable (clear this bit to shut down LCD)
//      :0      Battery checker bit A (? enable $600000:2)
//      The battery checker bits must both be set (AB=11) prior to checking
//      the voltage level with $600000:2.  Then, after use, bit B must be
//      cleared (AB=10) while the battery trig hardware settles to the
//      "rest" voltage value (%111).  Finally, both bits should be cleared.
//
//-----------------------------------------------------------------------------

/*===========================================================================*/
/* evaluates battery state (if argument is 0 it assumes HW1 else HW2)        */
/*                                                                           */
/* returns:                                                                  */
/*                                                                           */
/* 7 - full        battery state                                             */
/* 6 - ok          battery state                                             */
/* 5 - medium      battery state                                             */
/* 4 - low         battery state (battery symbol appears)                    */
/* 3 - very low    battery state (battery symbol darkened)                   */
/* 2 - starving    battery state (battery symbol darkened)                   */
/* 1 - almost dead battery state (battery symbol darkened)                   */
/* 0 - dead        battery state (calc resetted)                             */
/*                                                                           */
/* NOTE: The BATT symbol will be turned on by the AMS                        */
/*===========================================================================*/
unsigned short BatteryState(unsigned short is_hw_2);

// ExtendeD's routine
asm("BatteryState:\n"
"           tst.w   4(%sp)           | jump for HW1\n"
"           beq     _bat_h1_1\n"
"           lea     0x70001D,%a0\n"
"           move.b  (%a0),%d0\n"
"           ori.b   #9,%d0\n"
"           move.b  %d0,(%a0)\n"
"_bat_h1_1: moveq   #6,%d1\n"
"           lea     0x600018,%a1\n"
"_bat_loop: bsr.s   _bat_ini         | this initialization lacked in previous versions\n"
"           move.w  %d1,%d0\n"
"           lsl.w   #7,%d0\n"
"           move.w  %d0,(%a1)\n"
"           moveq   #0x6e,%d0\n"
"_bat_test: btst.b  #2,-0x18(%a1)\n"
"           dbeq    %d0,_bat_test\n"
"           beq.s   _bat_quit\n"
"           dbf     %d1,_bat_loop\n"
"_bat_quit: neg.w   %d1\n"
"           addq.w  #6,%d1\n"
"           tst.w   4(%sp)\n"
"           beq.s   _bat_h1_2        | jump for HW1\n"
"           and.b   #0xF7,(%a0)\n"
"           bsr.s   _bat_ini\n"
"           andi.b  #0xF6,(%a0)\n"
"_bat_h1_2: move.w  %d1,%d0\n"
"           rts\n"
"_bat_ini:  move.w  #0x380,(%a1)\n"
"           moveq   #52,%d0\n"
"_bat_wait: btst.b  #2,-0x18(%a1)\n"
"           dbeq    %d0,_bat_wait\n"
"           rts");


/*===========================================================================*/
/* battery state fetching routine                                            */
/*===========================================================================*/
void _main(void) {
    unsigned long hwpb, *rombase;
    unsigned short level;

    // For ExtendeD's routine
    static const char* msg_level[] = {
        "0/6 (around 2.9V, CALC RESETTED)",
        "0/6 (around 3.2V, CHANGE VERY QUICKLY)",
        "\x10 1/6 (around 3.4V, ALMOST DEAD)",
        "\x10\x10 2/6 (around 3.7V, VERY LOW)",
        "\x10\x10\x10 3/6 (around 4V, LOW)",
        "\x10\x10\x10\x10 4/6 (around 4.3V, MEDIUM)",
        "\x10\x10\x10\x10\x10 5/6 (around 4.5V, OK)",
        "\x10\x10\x10\x10\x10\x10 6/6 (above 4.6V, FULL)"};


    rombase = (unsigned long *)((*(unsigned long *)0xC8) & 0x600000);
    hwpb = rombase[65];
    OSSetSR(0x700); // there exists shorter ways, but I don't care for 3 or 4 bytes
    level = BatteryState(((unsigned short)(hwpb - (unsigned long)rombase  < 0x10000 &&
       *(unsigned short *)hwpb > 22 ? *(unsigned long *)(hwpb + 22) : 1) - 1L));
    OSSetSR(0); // there exists shorter ways, but I don't care for 3 or 4 bytes

    ST_eraseHelp();
    ST_helpMsg(msg_level[level]);
}

//#############################################################################
// Revision History
//#############################################################################
//
// $Log: ttbatt.c,v $
// Revision 1.4  2002/02/28 10:52:44  tnussb
// (1) using now bugfixed version from Extended
// (2) changed the string array to "static const" and compile now with
//     -fomit-frame-pointer to reduce the size further
//
// Revision 1.3  2002/02/21 09:42:01  tnussb
// uses now OSSetSR() again (instead of inline ASM)
//
// Revision 1.2  2002/02/11 08:37:52  tnussb
// (1) code further optimized by bremen
// (2) messages refined to report more details
//
// Revision 1.1  2002/02/07 09:53:13  tnussb
// initial version
//
