📄 ist.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#include <windows.h>
#include <windev.h>
#include <types.h>
#include <memory.h>
#include <winuserm.h>
#include <string.h>
#include <nkintr.h>
#include <ceddk.h>
#include <pmimpl.h>
#include <pmpolicy.h>
#include <battery.h>
#include <bulverde_base_regs.h>
#include <plato.h>
#include <xllp_gpio.h>
#include <xllp_clkmgr.h>
#include <xllp_ost.h>
#include <xllp_i2c.h>
#include "bsp_cfg.h"
#include "pcf50606.h"
#include "pmdriver.h"
#include "power_i2c.h"
#ifndef SHIP_BUILD
extern DBGPARAM dpCurSettings;
#endif
#define IST_PRIORITY256 100
static SYSTEM_POWER_STATUS_EX2 gPowerStatus;
BOOL gfACOnline = FALSE;
static BOOL gfBatteryCharging = FALSE;
static BOOL gfRTCSyncThreadRunning = FALSE;
static void
SynchronizeRTCTime(PPCF50606 pPCF50606);
DWORD WINAPI
SynchronizeRTCThread(PPCF50606 pPCF50606);
static void
RestartCharger(PPCF50606 pPCF50606);
static void
StopCharger(PPCF50606 pPCF50606);
static void
RemoveCharger(PPCF50606 pPCF50606);
static void
BatteryFull(PPCF50606 pPCF50606);
static void
BatteryEmpty(PPCF50606 pPCF50606);
static void
SendPowerChangeMessage(HANDLE pMsgQueue);
static DWORD
ComputeVoltageAverage(PPCFBATTERY pPcfBattery);
static void GetBatteryVoltage(PPCF50606 pPCF50606)
{
// ADC Start for BATVOLT, no external sync
pPCF50606->pcfRegisterCache[ADCC2] = ADCC2_ADCMUX_M(SEL_BATVOLT_RES) |
ADCC2_ADCSYNC_M(NO_SYNC) |
ADCC2_START;
PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
ADCC2,
pPCF50606->pcfRegisterCache+ADCC2,
1);
// Read Battery voltage from PCF50606
PDD_I2CRead(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
ADCS1,
pPCF50606->pcfRegisterCache+ADCS1,
2);
pPCF50606->pcfBattery.dwCurrentBatteryVoltage =
((pPCF50606->pcfRegisterCache[ADCS1] << 2) | (pPCF50606->pcfRegisterCache[ADCS2] & 0x3));
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF50606: Raw Battery Voltage: 0x%x\r\n"),
pPCF50606->pcfBattery.dwCurrentBatteryVoltage));
pPCF50606->pcfBattery.dwCurrentBatteryVoltage =
(pPCF50606->pcfBattery.dwCurrentBatteryVoltage * 6000) >> 10;
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF50606: Calculated Battery Voltage: %dmV\r\n"),
pPCF50606->pcfBattery.dwCurrentBatteryVoltage));
}
#ifdef _DEBUG
static void PrintBatteryTemp(PPCF50606 pPCF50606)
{
DWORD dwPCFBatteryTemp;
// ADC Start for BATTEMP, no external sync
pPCF50606->pcfRegisterCache[ADCC1] = ADCC1_TRATSET |
ADCC1_NTCSWAOFF;
pPCF50606->pcfRegisterCache[ADCC2] = ADCC2_ADCMUX_M(SEL_BATTEMP_RAT) |
ADCC2_ADCSYNC_M(NO_SYNC) |
ADCC2_START;
PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
ADCC1,
pPCF50606->pcfRegisterCache+ADCC1,
2);
//wait for reading to stabilize
XllpOstDelayMicroSeconds((P_XLLP_OST_T)pPCF50606->v_pOstRegs, 100);
PDD_I2CRead(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
ADCS1,
pPCF50606->pcfRegisterCache+ADCS1,
2);
dwPCFBatteryTemp =
((pPCF50606->pcfRegisterCache[ADCS1] << 2) | (pPCF50606->pcfRegisterCache[ADCS2] & 0x3));
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF50606: Battery Temp Raw: 0x%x\r\n"),
dwPCFBatteryTemp));
dwPCFBatteryTemp = (dwPCFBatteryTemp*10000)/(1023-dwPCFBatteryTemp);
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF50606: Battery Temp Resistance: %d Ohms\r\n"),
dwPCFBatteryTemp));
}
static void PrintMBCState(PPCF50606 pPCF50606)
{
// Read Battery voltage from PCF50606
PDD_I2CRead(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
MBCC1,
pPCF50606->pcfRegisterCache+MBCC1,
4);
DEBUGMSG(ZONE_VERBOSE, (TEXT("\nMain Battery Charger (MBC)Regs\r\n")));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: MBCC1: %x\r\n"),
pPCF50606->pcfRegisterCache[MBCC1]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: MBCC2: %x\r\n"),
pPCF50606->pcfRegisterCache[MBCC2]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: MBCC3: %x\r\n"),
pPCF50606->pcfRegisterCache[MBCC3]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: MBCS1: %x\r\n"),
pPCF50606->pcfRegisterCache[MBCS1]));
DEBUGMSG(ZONE_VERBOSE, (TEXT("\r\n")));
}
static void PrintInterruptStatus(PPCF50606 pPCF50606)
{
//only print the cached values
DEBUGMSG(ZONE_VERBOSE, (TEXT("\nPCF Interupts Status Regs\r\n")));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: INT1: %x\r\n"),
pPCF50606->pcfRegisterCache[INT1]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: INT1M: %x\r\n"),
pPCF50606->pcfRegisterCache[INT1M]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: INT2: %x\r\n"),
pPCF50606->pcfRegisterCache[INT2]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: INT2M: %x\r\n"),
pPCF50606->pcfRegisterCache[INT2M]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: INT3: %x\r\n"),
pPCF50606->pcfRegisterCache[INT3]));
DEBUGMSG(ZONE_VERBOSE, (TEXT(" PCF50606: INT3M: %x\r\n"),
pPCF50606->pcfRegisterCache[INT3M]));
DEBUGMSG(ZONE_VERBOSE, (TEXT("\r\n")));
}
#endif
INT WINAPI PCF50606IntrThread(PPCF50606 pPCF50606)
{
DWORD bytesReturned;
DWORD dwTimeout;
DWORD dwPCFMessage;
DWORD dwErr;
DWORD wakeSrcKeyPad = SYSINTR_KEYPAD;
SYSTEMTIME sysRTCTime;
const BYTE *RTCRegs = pPCF50606->pcfRegisterCache+RTCSC;
PPCFBATTERY pPcfBattery = &pPCF50606->pcfBattery;
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF50606IntrThread starting...\r\n")));
// Set thread's priority
CeSetThreadPriority(GetCurrentThread(), IST_PRIORITY256);
// Polling mode with interrupt enabled only for events
// Let the first run happen soon so that the battery driver gets a voltage reading.
dwTimeout = 1;
while(1)
{
if(WaitForSingleObject(pPCF50606->hevPCF50606Event, dwTimeout) == WAIT_OBJECT_0)
{
// Actually received interrupt, stop polling
InterruptDone(SYSINTR_PCF50606);
}
else
{
// Poll every 'x' seconds
dwTimeout = PCF50606_MAINTENANCE_POLLING_INTERVAL;
}
// Read Interrupt controller register 1,2,3 from PCF50606
bytesReturned = PDD_I2CRead(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
INT1,
pPCF50606->pcfRegisterCache+INT1,
3);
// Reset PCF message
dwPCFMessage = 0;
#ifdef _DEBUG
PrintInterruptStatus(pPCF50606);
#endif
if(pPCF50606->pcfRegisterCache[INT2] & INT2_CHGERR)
{
RETAILMSG(ZONE_ERROR, (TEXT("PCF50606: Charger Error\r\n")));
bytesReturned = PDD_I2CRead(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
MBCS1,
pPCF50606->pcfRegisterCache+MBCS1,
1);
if(MBCS1_TBATSTAT_M(MBCS1_TEMP_OK) != (pPCF50606->pcfRegisterCache[MBCS1] & MBCS1_TBATSTAT_M(MBCS1_TEMP_MASK)))
{
// Plato does not have temprature monitoring hardware so this error must be invalid
RETAILMSG(ZONE_ERROR, (TEXT("PCF50606: Invalid Temprature Error, Restarting Charger\r\n")));
StartCharger(pPCF50606);
}
}
// Query INT register #1
///////////////////////////////////////////////
// Has ONKEY been pressed or released (doubles up as the END key)
///////////////////////////////////////////////
if(pPCF50606->pcfRegisterCache[INT1] & INT1_ONKEYF)
{
// key released
keybd_event((BYTE) VK_TEND, 0x46, KEYEVENTF_KEYUP, 0);
}
if(pPCF50606->pcfRegisterCache[INT1] & INT1_ONKEYR)
{
// key pressed
keybd_event((BYTE) VK_TEND, 0x46, 0, 0);
}
///////////////////////////////////////////////
// Has ONKEY been pressed for 1 sec
///////////////////////////////////////////////
if(pPCF50606->pcfRegisterCache[INT1] & INT1_ONKEY1S)
{
// Power OFF/ON key held down for one second. Initiate clean shutdown.
//
// First reset the 8 second timer so that system has enough time to
// shutdown properly (or recover from an error)
pPCF50606->pcfRegisterCache[OOCC1] |= OOCC1_TOTRST;
bytesReturned = PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
OOCC1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -