La mia piccola fusione fredda privata

Sperimentando la fusione fredda

Il contatore Geiger : main.c

Posted Sunday, April 19th, 2015

/********************************************************************
FileName:        main.c
Dependencies:    See INCLUDES section
Processor:        PIC18, PIC24, and PIC32 USB Microcontrollers
Hardware:        This demo is natively intended to be used on Microchip USB demo
boards supported by the MCHPFSUSB stack.  See release notes for
support matrix.  This demo can be modified for use on other hardware
platforms.
Complier:      Microchip C18 (for PIC18), C30 (for PIC24), C32 (for PIC32)
Company:        Microchip Technology, Inc.

Software License Agreement:

The software supplied herewith by Microchip Technology Incorporated
(the “Company”) for its PIC® Microcontroller is intended and
supplied to you, the Company’s customer, for use solely and
exclusively on Microchip PIC Microcontroller products. The
software is owned by the Company and/or its supplier, and is
protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the
user to criminal sanctions under applicable laws, as well as to
civil liability for the breach of the terms and conditions of this
license.

********************************************************************
File Description:

Change History:
Rev   Description
—-  —————————————–
2.6a  Added support for PIC24FJ256GB210

2.7   No change

2.8   Improvements to USBCBSendResume(), to make it easier to use.
2.9   Added event transfer terminated handler code, for improved MSD
error case handling.  Increased RAM reserved for the C software
stack on PIC18 devices.  The previous version did not allocate
enough RAM for the worst case scenario, when USB_INTERRUPTS mode
was used, causing potentially unexpected operation.

Riscrittura FW Contatore Geiger di Nuova Elettronica LX1710 CHE non è il massimo!
GD 2/3/2012

https://sites.google.com/site/diygeigercounter/home

http://allegedlyapparent.wordpress.com/radioactivity/radiation_units/ (conversione unità)

http://www.civildefensemuseum.com/southrad/conversion.html

http://digilander.libero.it/dadano1/Contatore%20geiger_3.htm (conversione Co60 e Cs137)
http://www.blackcatsystems.com/GM/converting_CPM_mRhr.html        (sensibilità)
********************************************************************/

/** INCLUDES *******************************************************/

#include <stdio.h>

#include <adc.h>
#include <uart.h>
#include <timer.h>
#include <ports.h>
#include <outcompare.h>
#include <incap.h>
#include <pps.h>

#include “USB.h”
#include “HardwareProfile.h”
#include “SD-SPI.h”
#include “FSIO.h”

#include <libpic30.h>

#include “usb_function_msd.h”
#include “usb_function_hid.h”
#include “contatoregeiger.h”
#include “lcd.h”
#include “swi2c.h”

/** CONFIGURATION **************************************************/

//  _CONFIG1(WDTPS_PS1 & FWPSA_PR32 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
//  _CONFIG2(POSCMOD_HS & I2C1SEL_PRI & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_DIV2 & IESO_OFF)
//  _CONFIG3(WPFP_WPFP0 & SOSCSEL_SOSC & WUTSEL_LEG & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
//  _CONFIG4(DSWDTPS_DSWDTPS3 & DSWDTOSC_LPRC & RTCOSC_SOSC & DSBOREN_OFF & DSWDTEN_OFF)

_CONFIG1(WDTPS_PS16 & FWPSA_PR32 & WINDIS_OFF & FWDTEN_OFF & ICS_PGx1 & GWRP_OFF & GCP_OFF & JTAGEN_OFF)
//        _CONFIG2(POSCMOD_HS & I2C1SEL_PRI & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_PRIPLL & PLL96MHZ_ON & PLLDIV_NODIV & IESO_ON)        // quarzo 4MHz
_CONFIG2(POSCMOD_HS & I2C1SEL_PRI & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_FRCPLL & PLL96MHZ_ON & PLLDIV_NODIV & IESO_ON)        // osc int
// il PLL però forse deve essere a DIV2 per usb… boh!
//        _CONFIG3(WPFP_WPFP0 & SOSCSEL_SOSC & WUTSEL_LEG & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)            SOSC??? secondari osc.. NO RB4!
_CONFIG3(WPFP_WPFP0 & SOSCSEL_IO & WUTSEL_LEG & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
_CONFIG4(DSWDTPS_DSWDTPS3 & DSWDTOSC_LPRC & RTCOSC_SOSC & DSBOREN_OFF & DSWDTEN_OFF)

/** VARIABLES ******************************************************/
#pragma udata

//The LUN variable definition is critical to the MSD function driver.  This
//  array is a structure of function pointers that are the functions that
//  will take care of each of the physical media.  For each additional LUN
//  that is added to the system, an entry into this array needs to be added
//  so that the stack can know where to find the physical layer functions.
//  In this example the media initialization function is named
//  “MediaInitialize”, the read capacity function is named “ReadCapacity”,
//  etc.
LUN_FUNCTIONS LUN[MAX_LUN + 1] = {
{
&MDD_MediaInitialize,
&MDD_ReadCapacity,
&MDD_ReadSectorSize,
&MDD_MediaDetect,
&MDD_SectorRead,
&MDD_WriteProtectState,
&MDD_SectorWrite
}
};

/* Standard Response to INQUIRY command stored in ROM     */
const ROM InquiryResponse inq_resp = {
0×00,        // peripheral device is connected, direct access block device
0×80,           // removable
0×04,         // version = 00=> does not conform to any standard, 4=> SPC-2
0×02,        // response is in format specified by SPC-2
0×20,        // n-4 = 36-4=32= 0×20
0×00,        // sccs etc.
0×00,        // bque=1 and cmdque=0,indicates simple queueing 00 is obsolete,
// but as in case of other device, we are just using 00
0×00,        // 00 obsolete, 0×80 for basic task queueing
{‘M’,'i’,'c’,'r’,'o’,'c’,'h’,'p’
},
// this is the T10 assigned Vendor ID
{‘M’,'a’,'s’,'s’,’ ‘,’S',’t',’o',’r',’a',’g',’e',’ ‘,’ ‘,’ ‘,’ ‘
},
{’0′,’0′,’0′,’1′
}
};

static ROM const char CopyrString[]= {‘C’,'o’,'n’,'t’,'a’,'t’,'o’,'r’,'e’,’ ‘,’G',’e',’i',’g',’e',’r',’ ‘,’N',’E',’/',’r',’e',’c',’o',’d',’e',’d',’ ‘,
‘v’,VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′, ‘ ‘,’0′,’6′,’/',’0′,’3′,’/',’1′,’5′, 0 };

//unsigned char ReceivedDataBuffer[64];
//unsigned char ToSendDataBuffer[64];
#define ReceivedDataBuffer hid_report_out
#define ToSendDataBuffer hid_report_in

USB_HANDLE USBOutHandle = 0;
USB_HANDLE USBInHandle = 0;

volatile BYTE Buf232PtrI,Buf232PtrO;
volatile BYTE Buf232[BUF_232_SIZE];
volatile struct COMM_STATUS CommStatus;

BYTE SDcardOK=FALSE,SDcardOn=FALSE,RS232On=FALSE,USBOn=FALSE,batteryState=0,ShieldOn=FALSE,/*GeigerOn=FALSE uso pin diretto!*/
Tube=LND712,Sensitivity=CO60,UnitaMisura=CPS /*DEBUG!*/ /*MILLIROENTGEN*/,ReadyOrSleep=READY,InAlert=FALSE;
BYTE batteryLevel=0;
WORD cpsVal=0,alarmThrs=10,recThrs=10,minValue=0,maxValue=0,medValue=0,stddevValue=0;
WORD cpsAvgs[10];
WORD cpsCounter=0;
WORD baudRate=BAUD_RATE;
extern volatile WORD tick10;
extern volatile BYTE divider1s,second_05,minute_1;
BYTE menuLevel=0,currSchermata=SCHERMATA_SPLASH,currSchermItem=0,enterData=0;
WORD lastTimeKB=0;
#ifdef USA_SW_RTC
volatile PIC24_RTCC_DATE currentDate;
volatile PIC24_RTCC_TIME currentTime;
#else
PIC24_RTCC_DATE currentDate;
PIC24_RTCC_TIME currentTime;
#endif

#define TickGet() (tick10)

/** PRIVATE PROTOTYPES *********************************************/
static void InitializeSystem(void);
int UserInit(void);
void USBDeviceTasks(void);
void ProcessIO(void);
void USBCBSendResume(void);

/** VECTOR REMAPPING ***********************************************/
#if defined(PROGRAMMABLE_WITH_USB_HID_BOOTLOADER)
/*
*    ISR JUMP TABLE
*
*    It is necessary to define jump table as a function because C30 will
*    not store 24-bit wide values in program memory as variables.
*
*    This function should be stored at an address where the goto instructions
*    line up with the remapped vectors from the bootloader’s linker script.
*
*  For more information about how to remap the interrupt vectors,
*  please refer to AN1157.  An example is provided below for the T2
*  interrupt with a bootloader ending at address 0×1400
*/
//        void __attribute__ ((address(0×1404))) ISRTable(){
//
//            asm(“reset”); //reset instruction to prevent runaway code
//            asm(“goto %0″::”i”(&_T2Interrupt));  //T2Interrupt’s address
//        }
#endif

/** DECLARATIONS ***************************************************/
#pragma code

/********************************************************************
* Function:        void main(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        Main program entry point.
*
* Note:            None
*******************************************************************/
FSFILE *logFile;
int main(void) {
//  unsigned int i;

InitializeSystem();

/*    TRISA=0;
while(1) {
LATA ^= 0xffff;
ClrWdt();
}*/

USBDeviceInit();
UserInit();

#if defined(USB_INTERRUPT)
USBDeviceAttach();
#endif

while(1) {

ClrWdt();

#if defined(USB_POLLING)
// Check bus status and service USB interrupts.
USBDeviceTasks(); // Interrupt or polling method.  If using polling, must call
// this function periodically.  This function will take care
// of processing and responding to SETUP transactions
// (such as during the enumeration process when you first
// plug in).  USB hosts require that USB devices should accept
// and process SETUP packets in a timely fashion.  Therefore,
// when using polling, this function should be called
// regularly (such as once every 1.8ms or faster** [see
// inline code comments in usb_device.c for explanation when
// "or faster" applies])  In most cases, the USBDeviceTasks()
// function does not take very long to execute (ex: <100
// instruction cycles) before it returns.
#endif

// Application-specific tasks.
// Application related code may be added here, or in the ProcessIO() function.
ProcessIO();        // See msd.c & msd.h

//if we are in the enumeration process then we don’t want to start initializing
// the FAT library.  It takes too
if((USBDeviceState < CONFIGURED_STATE) && (USBDeviceState > ATTACHED_STATE)) {
//      continue; no…
}

UserTasks();
} //end while

} //end main

/********************************************************************
* Function:        static void InitializeSystem(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        InitializeSystem is a centralize initialization
*                  routine. All required USB initialization routines
*                  are called from here.
*
*                  User application initialization routine should
*                  also be called from here.
*
* Note:            None
*******************************************************************/
WORD getBRGFromBaudRate(DWORD b) {
DWORD CLOSEST_UBRG_VALUE,BAUD_ACTUAL;
WORD BAUD_ERROR,BAUD_ERROR_PRECENT;

CLOSEST_UBRG_VALUE=((GetPeripheralClock()+8ul*b)/4/b-1);
//    CLOSEST_UBRG_VALUE=((GetPeripheralClock()+8ul*b)/(4)/b-1) /2;        // :2 !! NON SI CAPISCE MA E’ COSì! DIVERSO DA GB106 ECC
BAUD_ACTUAL=(GetPeripheralClock()/4/(CLOSEST_UBRG_VALUE+1));

BAUD_ERROR=((BAUD_ACTUAL > BAUD_RATE) ? BAUD_ACTUAL-BAUD_RATE : BAUD_RATE-BAUD_ACTUAL);
BAUD_ERROR_PRECENT=((BAUD_ERROR*100+BAUD_RATE/2)/BAUD_RATE);
if(BAUD_ERROR_PRECENT > 3) {
//UART frequency error is worse than 3%
}
else if(BAUD_ERROR_PRECENT > 2) {
//UART frequency error is worse than 2%
}

return (WORD)CLOSEST_UBRG_VALUE;
}

static void InitializeSystem(void) {
unsigned int Adcon3_reg, Adcon2_reg, Adcon1_reg;
unsigned int PinConfig,Scanselect;

ClrWdt();

AD1PCFG=0b1111011111111111;    // AN11/RB13

//Set up the LED as output
mInitAllLEDs();

//Set the push button input
mInitSwitch2();

TRISA = 0b0000000000000000;        // RTS/CTS (gestite in PPS); led; beep, geiger
TRISB = 0b1110110000011111;        // LCD, UART, PWM, USB D+-, Pot
TRISC = 0b0000001111111101;        // 4 pulsanti; SDcard
ODCA  = 0b0000000010000000;        // pnp per beep…

LATA = 0b0000000010000000;        // buzzer, geiger off; led off;
LATB = 0b0000000000000000;        // lcd=0; pwm, UART gestite da perif.
LATC = 0b0000000000101010;        // SDCS=1, ecc;

//On the PIC24FJ64GB004 Family of USB microcontrollers, the PLL will not power up and be enabled
//by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
//This allows the device to power up at a lower initial operating frequency, which can be
//advantageous when powered from a source which is not gauranteed to be adequate for 32MHz
//operation.  On these devices, user firmware needs to manually set the CLKDIV<PLLEN> bit to
//power up the PLL.
{
unsigned int pll_startup_counter = 600;
CLKDIVbits.PLLEN = 1;
while(pll_startup_counter–);
}

//Device switches over automatically to PLL output after PLL is locked and ready.
//    CLKDIVbits.RCDIV = 0;        // Set 1:1 8MHz FRC postscalar NO! uso 4 (v. anche CONFIG)

//    The USB specifications require that USB peripheral devices must never source
//    current onto the Vbus pin.  Additionally, USB peripherals should not source
//    current on D+ or D- when the host/hub is not actively powering the Vbus line.
//    When designing a self powered (as opposed to bus powered) USB peripheral
//    device, the firmware should make sure not to turn on the USB module and D+
//    or D- pull up resistor unless Vbus is actively powered.  Therefore, the
//    firmware needs some means to detect when Vbus is being powered by the host.
//    A 5V tolerant I/O pin can be connected to Vbus (through a resistor), and
//     can be used to detect when Vbus is high (host actively powering), or low
//    (host is shut down or otherwise not supplying power).  The USB firmware
//     can then periodically poll this I/O pin to know when it is okay to turn on
//    the USB module/D+/D- pull up resistor.  When designing a purely bus powered
//    peripheral device, it is not possible to source current on D+ or D- when the
//    host is not actively providing power on Vbus. Therefore, implementing this
//    bus sense feature is optional.  This firmware can be made to use this bus
//    sense feature by making sure “USE_USB_BUS_SENSE_IO” has been defined in the
//    HardwareProfile.h file.
#if defined(USE_USB_BUS_SENSE_IO)
tris_usb_bus_sense = INPUT_PIN; // See HardwareProfile.h
#endif

//    If the host PC sends a GetStatus (device) request, the firmware must respond
//    and let the host know if the USB peripheral device is currently bus powered
//    or self powered.  See chapter 9 in the official USB specifications for details
//    regarding this request.  If the peripheral device is capable of being both
//    self and bus powered, it should not return a hard coded value for this request.
//    Instead, firmware should check if it is currently self or bus powered, and
//    respond accordingly.  If the hardware has been configured like demonstrated
//    on the PICDEM FS USB Demo Board, an I/O pin can be polled to determine the
//    currently selected power source.  On the PICDEM FS USB Demo Board, “RA2″
//    is used for    this purpose.  If using this feature, make sure “USE_SELF_POWER_SENSE_IO”
//    has been defined in HardwareProfile.h, and that an appropriate I/O pin has been mapped
//    to it in HardwareProfile.h.
#if defined(USE_SELF_POWER_SENSE_IO)
tris_self_power = INPUT_PIN;    // See HardwareProfile.h
#endif

//********* Initialize Peripheral Pin Select (PPS) *************************
//  This section only pertains to devices that have the PPS capabilities.
//    When migrating code into an application, please verify that the PPS
//    setting is correct for the port pins that are used in the application.
PPSUnLock;
PPSInput (PPS_SDI1, PPS_RP20);      //    RC4

// Outputs
PPSOutput(PPS_RP19, PPS_SCK1OUT);        // RC3
PPSOutput(PPS_RP21, PPS_SDO1);        // RC5

// RS232
PPSOutput(PPS_RP14, PPS_U1TX);      // TXD RB14
PPSInput (PPS_U1RX, PPS_RP15);      // RXD RB15
// sono PPS anche questi? ! boh
//    #define m232_RTS             LATDbits.LATA0        // va al CTS di host
//    #define m232_CTS             PORTAbits.RA1        // va al RTS di host
PPSInput (PPS_U1CTS, PPS_RP6);      //
PPSOutput(PPS_RP5, PPS_U1RTS);     //

// PWM
PPSOutput(PPS_RP9, PPS_OC4);         //PWM RB9

PPSInput(PPS_IC1, PPS_RP4);      // Input Capture

PPSLock;

//enable a pull-up for the card detect, just in case the SD-Card isn’t attached
//  then lets have a pull-up to make sure we don’t think it is there.
//    CNPU1bits.CN6PUE = 1;  qua c’è

OpenTimer2(T2_ON & T2_IDLE_CON & T2_GATE_OFF & T2_PS_1_64 & T2_32BIT_MODE_OFF & T2_SOURCE_INT,
TMR2BASE);        //10Hz per timing
ConfigIntTimer2(T2_INT_PRIOR_4 & T2_INT_ON);
EnableIntT2;

OpenTimer3(T3_ON & T3_IDLE_CON & T3_GATE_OFF & T3_PS_1_64 & T3_SOURCE_INT,
TMR3BASE);        //100Hz per capture
//ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_OFF);

OpenCapture1(IC_IDLE_CON & IC_TIMER3_SRC & IC_INT_1CAPTURE & IC_EVERY_RISE_EDGE,
IC_CASCADE_DISABLE /*& IC_SYNC_ENABLE & IC_SYNC_TRIG_IN_TMR2*/);     //Configure Input Capture module
ConfigIntCapture1(IC_INT_ON & IC_INT_PRIOR_5);     //

#define PROPER_SPICON1  (0×0013 | 0×0120)   /* 1:1 primary prescale, 4:1 secondary prescale, CKE=1, MASTER mode */
#define ClearSPIDoneFlag()
/*    static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
{
while ((SPISTATbits.SPITBF == 1) || (SPISTATbits.SPIRBF == 0))
ClrWdt();
}*/

//    #define SPI_ON_BIT          (EEPROM_SPISTATbits.SPIEN)

SD_CS = 1;
SD_CS_TRIS = 0;     // Drive SPI EEPROM chip select pin

SPICLOCK = 0;    // Set SCK pin as an output
SPIIN = 1;    // Make sure SDI pin is an input
SPIOUT = 0;    // Set SDO pin as an output
// non necessari con PPS  ?? invece sì? boh

ClearSPIDoneFlag();
SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
SPICON2 = 0;
SPISTAT = 0;    // clear SPI
SPISTATbits.SPIEN = 1;
// sta roba serve o SD non va!! cazzo! spostare di là?

// UART
UARTTX_TRIS = 0;
UARTRX_TRIS = 1;
//        UMODE = 0×8000;            // Set UARTEN.  Note: this must be done before setting UTXEN

WORD UBRG = getBRGFromBaudRate(baudRate);

OpenUART1(UART_EN & UART_IDLE_CON & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT
& UART_IrDA_DISABLE & UART_MODE_SIMPLEX & UART_UEN_00 & UART_UXRX_IDLE_ONE & UART_BRGH_FOUR ,
UART_INT_TX_BUF_EMPTY & UART_SYNC_BREAK_DISABLED & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS
& UART_IrDA_POL_INV_ZERO  /*OCCHIO a buffer 232/485*/,
// attivare RTS CTS? !
UBRG);
EnableIntU1RX;
DisableIntU1TX;

PinConfig      =  ENABLE_AN0_DIG &            // Enable (AN2)-AN3 analog port
ENABLE_AN1_DIG &
ENABLE_AN2_DIG &            // PWM
ENABLE_AN3_ANA &
ENABLE_AN4_DIG &
ENABLE_AN5_DIG &    // 6,7,8 non ci sono
ENABLE_AN9_DIG &
ENABLE_AN10_DIG &
ENABLE_AN11_ANA;        // 12,13,14,15 non ci sono

Scanselect      =      ADC_SKIP_SCAN_AN0 &                  // Scan for AN0-AN3
ADC_SKIP_SCAN_AN1 &
ADC_SKIP_SCAN_AN2 /* ADC_SCAN_AN2 */ &
ADC_SKIP_SCAN_AN3 /*ADC_SCAN_AN3 */ &
ADC_SKIP_SCAN_AN4 &
ADC_SKIP_SCAN_AN5 &
ADC_SKIP_SCAN_AN9 &
ADC_SKIP_SCAN_AN10 &
ADC_SKIP_SCAN_AN11 ;

Adcon3_reg      =      ADC_SAMPLE_TIME_16 &                  // Sample for 10 time
ADC_CONV_CLK_SYSTEM  &      // system Clock
ADC_CONV_CLK_8Tcy;

Adcon2_reg      =      ADC_VREF_AVDD_AVSS &            // Vref at Vdd and Vss
ADC_SCAN_OFF /*ON*/ &                    // Enable scan for ADC
ADC_ALT_BUF_OFF &                // Disable alternate buffer
ADC_ALT_INPUT_OFF &            // Disable alternate input
ADC_INTR_2_CONV  /*ADC_INTR_EACH_CONV*/;      // 16 sample between interrupt

Adcon1_reg      =      ADC_MODULE_ON &                  // Enable module ADC
ADC_IDLE_CONTINUE &            // ADC run on idle mode
ADC_FORMAT_INTG &               // Output value integer format
ADC_CLK_AUTO &                  // ADC manual clock
//ADC_SAMP_ON &                  // ADC sampling simultaneous
ADC_AUTO_SAMPLING_ON;      // ADC auto sampling

OpenADC10(Adcon1_reg, Adcon2_reg,Adcon3_reg,PinConfig,Scanselect);      // Turn on ADC module
EnableADC1;

CM3CON=0;        // comparatori off (Rxpin) ?? boh

//    OpenOC4(OC_IDLE_CON & OC_SYSCLK_SRC /* & CMP_FAULT2_IN_DISABLE */ /* & OC_FAULT1_IN_DISABLE */ & OC_PWM_FAULT_CLEAR & OC_TRIG_CLEAR_SYNC & OC_CONTINUE_PULSE,
//        OC_FAULT_MODE_PWM_CYCLE & OC_PWM_FAULT_OUT_HIGH & OC_FAULT_PIN_UNCHANGE & OC_OUT_NOT_INVERT & OC_CASCADE_DISABLE /* & OC_SYNC_ENABLE */ & OC_UNTRIGGER_TIMER & OC_DIRN_TRIS & 0xffff /*OC_SYNC_TRIG_IN_CURR_OC*/,
//        256,128);
//    OpenOC4(OC_IDLE_CON & OC_TIMER2_SRC & OC_CONTINUE_PULSE,
//        TMR2BASE,TMR2BASE);
// CI SON GRAVI PROBLEMI nelle lib function per GA.. con GB sembra andare… in tutti i casi uso REGISTRI!

// messo in LCD

}//end InitializeSystem

int UserInit(void) {
//    int i;

LCDInit();
print_init();
LuceLCD=3;
aggLuceContrasto();

SDcardOK = FSInit();

//The log file is not open so let’s make sure the pointer is NULLed out
logFile = NULL;

//initialize the variable holding the handle for the last transmission
USBOutHandle = 0;
USBInHandle = 0;

return 1;
}

/********************************************************************
* Function:        void ProcessIO(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        This function is a place holder for other user
*                  routines. It is a mixture of both USB and
*                  non-USB tasks.
*
* Note:            None
*******************************************************************/
void ProcessIO(void) {
int i;

ClrWdt();
//    mLED_1_Toggle();

// User Application USB tasks
if((USBDeviceState < CONFIGURED_STATE) || (USBSuspendControl==1)) {
USBOn=FALSE;
return;
}

USBOn=TRUE;
if(!HIDRxHandleBusy(USBOutHandle)) {
switch(ReceivedDataBuffer[1]) {            // ReceivedDataBuffer[0] contiene 2 = OUTPUT_REPORT, se ESPLICITAMENTE DEFINITO

case CMD_NOP:
break;

case CMD_GETID:                        // restituisce ID ASCII ()
i=0;                        // puntatore alla stringa Copyright

do {
prepOutBuffer(CMD_GETID);                    // indicatore
memcpypgm2ram((void *)(ToSendDataBuffer+2),(void *)(((char *)CopyrString)+i),HID_INT_IN_EP_SIZE-2);
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
i+=HID_INT_IN_EP_SIZE-2;
} while(!memchr((void *)(ToSendDataBuffer+2),0,HID_INT_IN_EP_SIZE-2));

break;

case CMD_GETCAPABILITIES:                                // restituisce config.
prepOutBuffer(CMD_GETCAPABILITIES);                    // indicatore
ToSendDataBuffer[2]=VERNUMH;
ToSendDataBuffer[3]=VERNUML;

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_GETCONFIG:                                            // restituisce config.
case CMD_GETSTATUS:                                            // boh, lascio tutto per ora
prepOutBuffer(CMD_GETCONFIG);                    // indicatore
ToSendDataBuffer[2]=SDcardOK;
ToSendDataBuffer[3]=SDcardOn;
ToSendDataBuffer[4]=RS232On;
ToSendDataBuffer[5]=USBOn;
ToSendDataBuffer[6]=batteryState;
ToSendDataBuffer[7]=ShieldOn;
ToSendDataBuffer[8]=mGeigerON;
ToSendDataBuffer[9]=Tube;
ToSendDataBuffer[10]=Sensitivity;
ToSendDataBuffer[11]=UnitaMisura;
ToSendDataBuffer[12]=ReadyOrSleep;
ToSendDataBuffer[13]=InAlert;
ToSendDataBuffer[14]=batteryLevel;
ToSendDataBuffer[15]=menuLevel;
ToSendDataBuffer[16]=currSchermItem;
ToSendDataBuffer[17]=enterData;
ToSendDataBuffer[24]=LOBYTE(cpsCounter);
ToSendDataBuffer[25]=HIBYTE(cpsCounter);
ToSendDataBuffer[26]=LOBYTE(cpsVal);
ToSendDataBuffer[27]=HIBYTE(cpsVal);
ToSendDataBuffer[28]=LOBYTE(alarmThrs);
ToSendDataBuffer[29]=HIBYTE(alarmThrs);
ToSendDataBuffer[30]=LOBYTE(recThrs);
ToSendDataBuffer[31]=HIBYTE(recThrs);
ToSendDataBuffer[32]=LOBYTE(minValue);
ToSendDataBuffer[33]=HIBYTE(minValue);
ToSendDataBuffer[34]=LOBYTE(maxValue);
ToSendDataBuffer[35]=HIBYTE(maxValue);
ToSendDataBuffer[36]=LOBYTE(medValue);
ToSendDataBuffer[37]=HIBYTE(medValue);
ToSendDataBuffer[38]=LOBYTE(stddevValue);
ToSendDataBuffer[39]=HIBYTE(stddevValue);
ToSendDataBuffer[40]=LOBYTE(baudRate);
ToSendDataBuffer[41]=HIBYTE(baudRate);

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_SETSTATUS:                                            // imposta
prepOutBuffer(CMD_SETSTATUS);                    // indicatore
SDcardOK=ReceivedDataBuffer[2];
SDcardOn=ReceivedDataBuffer[3];
RS232On=ReceivedDataBuffer[4];
//                USBOn=ReceivedDataBuffer[5];         :)
batteryState=ReceivedDataBuffer[6];        // inutile ma lascio per test
ShieldOn=ReceivedDataBuffer[7];
mGeigerON=ReceivedDataBuffer[8];
Tube=ReceivedDataBuffer[9];
Sensitivity=ReceivedDataBuffer[10];
UnitaMisura=ReceivedDataBuffer[11];
ReadyOrSleep=ReceivedDataBuffer[12];        // e fare sleep?
InAlert=ReceivedDataBuffer[13];
menuLevel=ReceivedDataBuffer[15];
currSchermItem=ReceivedDataBuffer[16];
enterData=ReceivedDataBuffer[17];
alarmThrs=MAKEWORD(ReceivedDataBuffer[28],ReceivedDataBuffer[29]);
recThrs=MAKEWORD(ReceivedDataBuffer[30],ReceivedDataBuffer[31]);
//                minValue=MAKEWORD(ReceivedDataBuffer[30],ReceivedDataBuffer[31]);
//                maxValue=MAKEWORD(ReceivedDataBuffer[30],ReceivedDataBuffer[31]);
//                medValue=MAKEWORD(ReceivedDataBuffer[30],ReceivedDataBuffer[31]);
//                stddevValue=MAKEWORD(ReceivedDataBuffer[30],ReceivedDataBuffer[31]);
baudRate=MAKEWORD(ReceivedDataBuffer[32],ReceivedDataBuffer[33]);

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_TEST:                            // test: accendo/spengo led in base a b0
mLED_1=ReceivedDataBuffer[2] & 1;
break;

case CMD_BEEP:
prepOutBuffer(CMD_BEEP);
mBeepON=0;
Delay_mS(100);
mBeepON=1;

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_LCD:
prepOutBuffer(CMD_LCD);
if(ReceivedDataBuffer[2] & 1)
LCDCls();
if(ReceivedDataBuffer[3] & 1)        // ferma visualizzazione sua
currSchermata=PRIMA_SCHERMATA_VISUALIZZAZIONE+5;
if(ReceivedDataBuffer[2] & 0×80) {
LCDWrite((char *)ReceivedDataBuffer+4);        // lascio spazio per altri display
LCDWrite((char *)ReceivedDataBuffer+28);
}
else {
LCDPutChar(ReceivedDataBuffer[4]);
}

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_WRITEEEPROM:                    // programmazione EEprom (blocchi SEMPRE da 16 BYTE, con USB nuovo/2005):
prepOutBuffer(CMD_WRITEEEPROM);            // indicatore
memcpy((void *)I2CBuffer,(void *)(ReceivedDataBuffer+5),16);

if(!(ReceivedDataBuffer[2] & 0×80)) {            // addr a 8 opp. 16? (b6:0 = # BYTEs)
// lo_addr
I2CWritePage(ReceivedDataBuffer[3],ReceivedDataBuffer[2] & 0x1f);                    // gestire ev. errore?
}

else {
// lo_addr & hi_addr
I2CWritePage16(MAKEWORD(ReceivedDataBuffer[3],ReceivedDataBuffer[4]),ReceivedDataBuffer[2] & 0x1f);                // gestire ev. errore?
}
USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_READEEPROM:            // lettura EEprom: 2 BYTE lo/hi addr. (blocchi SEMPRE da 16 BYTE, con USB nuovo/2005):
prepOutBuffer(CMD_READEEPROM);            // indicatore

if(!(ReceivedDataBuffer[2] & 0×80)) {            // addr a 8 opp. 16? (b6:0 = # BYTEs)
// lo_addr
I2CRead8Seq(ReceivedDataBuffer[3],ReceivedDataBuffer[2] & 0x1f);
}
else {
I2CRead16Seq(MAKEWORD(ReceivedDataBuffer[3],ReceivedDataBuffer[4]),ReceivedDataBuffer[2] & 0x1f);            // lo_addr
}

memcpy((void *)ToSendDataBuffer+2,(void *)I2CBuffer,16);

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_READRTC:            // lettura RTC
prepOutBuffer(CMD_READRTC);            // indicatore

#ifndef USA_SW_RTC
currentTime.l = PIC24RTCCGetTime();
currentDate.l = PIC24RTCCGetDate();
ToSendDataBuffer[3]=from_bcd(currentDate.mday);        // UNIFORMARE CON SKYUSB!
ToSendDataBuffer[4]=from_bcd(currentDate.mon);
ToSendDataBuffer[5]=from_bcd(currentDate.year);
ToSendDataBuffer[6]=from_bcd(currentTime.hour);
ToSendDataBuffer[7]=from_bcd(currentTime.min);
ToSendDataBuffer[8]=from_bcd(currentTime.sec);
#else
ToSendDataBuffer[3]=currentDate.mday;        // UNIFORMARE CON SKYUSB!
ToSendDataBuffer[4]=currentDate.mon;
ToSendDataBuffer[5]=currentDate.year;
ToSendDataBuffer[6]=currentTime.hour;
ToSendDataBuffer[7]=currentTime.min;
ToSendDataBuffer[8]=currentTime.sec;

#endif

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_WRITERTC:                    // programmazione RTC
prepOutBuffer(CMD_WRITERTC);            // indicatore

i=ReceivedDataBuffer[3];        // UNIFORMARE CON SKYUSB e GSMDEV!
currentDate.mday=i;
i=ReceivedDataBuffer[4];
currentDate.mon=i;
i=ReceivedDataBuffer[5];
currentDate.year=i;            // -2000
i=ReceivedDataBuffer[6];
currentTime.hour=i;
i=ReceivedDataBuffer[7];
currentTime.min=i;
i=ReceivedDataBuffer[8];
currentTime.sec=i;

#ifndef USA_SW_RTC
PIC24RTCCSetDate(MAKEWORD(to_bcd(currentDate.year),0),MAKEWORD(to_bcd(currentDate.mday),to_bcd(currentDate.mon)));        // BCD…
PIC24RTCCSetTime(MAKEWORD(to_bcd(currentTime.hour),0),MAKEWORD(to_bcd(currentTime.sec),to_bcd(currentTime.min)));        // BCD…
#endif

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();
break;

case CMD_RESET_IF:                        // RESET (occhio a Enum. USB)
Reset();
break;

case CMD_DEBUG_ECHO:                        // ECHO
prepOutBuffer(CMD_DEBUG_ECHO);
memcpy((void *)(ToSendDataBuffer+2),(void *)(ReceivedDataBuffer+2),
//                        min(HID_INT_IN_EP_SIZE,HID_INT_OUT_EP_SIZE)-2);
HID_INT_OUT_EP_SIZE-2);

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();

break;
}
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);
}

MSDTasks();

}    //end ProcessIO

void prepOutBuffer(BYTE t) {                    // entra W=IDENTificatore

clearOutBuffer();
ToSendDataBuffer[0]=1 /*SKYNET_REPORT_ID_INPUT*/;                    // dev’essere per forza 1! (ossia ID report di input)
// .. contiene xxx_REPORT_ID_INPUT, se metto esplicitamente un REPORT_ID
ToSendDataBuffer[1]=t;
}

void clearOutBuffer(void) {

memset(ToSendDataBuffer,0,64 /*BUF_SIZE_USB*/);
}

void prepStatusBuffer(BYTE t) {

prepOutBuffer(CMD_GETSTATUS);                // indicatore
ToSendDataBuffer[2]=t;
}

void UserTasks(void) {
WORD n;
DWORD n2;
int i;
static BYTE cnt,oldmGeigerON=0;
static WORD tKBD;
char buffer[32];

if((TickGet() – tKBD) >= 2) {
tKBD = TickGet();
scanKBD();            //200mS è ok… o mettere in un IRQ?? (v.sgta)
handleKBD();
}

if(second_05) {
second_05=0;

cnt++;

updLCD();

if(!mBeepON)
mBeepON=1;
else
mBeepON=!(cpsVal > alarmThrs);        //attivo basso; suono a intermittenza
InAlert=cpsVal > alarmThrs;
mAlert=InAlert;

if(cnt & 1) {            // ogni 1sec

cpsVal=cpsCounter;
cpsCounter=0;

minValue=min(cpsVal,minValue);        // fatto così non ha molto senso xché parte da 0… forse farlo su ultimi 10 sec!
maxValue=max(cpsVal,maxValue);

for(i=9; i; i–)
cpsAvgs[i]=cpsAvgs[i-1];
cpsAvgs[0]=cpsVal;

n2=0;
for(i=0; i<10; i++)
n2+=cpsAvgs[i];
medValue=n2/10;

if(lastTimeKB) {
if((TickGet()-lastTimeKB) > (10*10)) {        // dopo 10 sec torna a luce normale
if(!enterData) {        //
//                    if(ValoriInEEprom.LCDluce != LuceLCD) {
LuceLCD=3 /*ValoriInEEprom.LCDluce*/;
aggLuceContrasto();
}
//                    }
}
if((TickGet()-lastTimeKB) > (60*10)) {        // dopo 2 minuti torna a scherm. iniz.
currSchermata=(ReadyOrSleep==READY) ? SCHERMATA_PRINCIPALE : SCHERMATA_SPLASH;
menuLevel=0;
currSchermItem=0;
enterData=0;
lastTimeKB=0;
}
}
if(!BusyADC10()) {        // non deve succedere
batteryLevel=ReadADC10(0) >> 2;        // R/R 10K/4K7 => 2V con 6V => 620; soglia a 5.4 => 558; solo 8bit
batteryState=batteryLevel>113;
SetChanADC10(ADC_CH0_NEG_SAMPLEB_VREFN & ADC_CH0_NEG_SAMPLEA_VREFN
& ADC_CH0_POS_SAMPLEA_AN11 & ADC_CH0_POS_SAMPLEB_AN11);
ConvertADC10();
}

if(!SDcardOK) {
if(MDD_MediaDetect())   // forse era compreso..
SDcardOK = FSInit();
}
else {
if(!MDD_MediaDetect())
SDcardOK = FALSE;
}

if(RS232On || USBOn || SDcardOn) {
sprintf(buffer,”#%06u%02u%02u%02u%02u%02u%02u%c%c%c%c%c%c%c@Rn”,
cpsVal,currentDate.year,currentDate.mon,currentDate.mday,
currentTime.hour,currentTime.min,currentTime.sec,
InAlert ? ‘A’ : ‘.’,
batteryState ? ‘B’ : ‘L’,
oldmGeigerON == mGeigerON /*mode cambio dati*/ ? ‘.’ : ‘C’,
cpsVal>recThrs ? ‘T’ : ‘.’,
Tube==LND712 ? ‘L’ : ‘S’,
ShieldOn ? ‘U’ : ‘.’,
Sensitivity==CO60 ? ‘x’ : ‘y’
);
oldmGeigerON=mGeigerON;
if(RS232On) {
putsUART1((WORD *)buffer);        // cast x funzione che rompe le palle!
}
if(SDcardOK && SDcardOn) {

//We don’t want the USB and the MDD to try to write to the file at the same time.  The simplest way to
//  block this is not to allow the demo application to write to the file while it is connected to the USB
if(USBDeviceState >= DEFAULT_STATE) {        // era MINORE ma credo fosse sbagliato..
//Let’s do a soft detach to insure that the PC isn’t trying to
//  write the files the same time we are.
LUNSoftDetach(0);

logFile = FSfopen(“geigerNE.csv”,FS_WRITE);
if(logFile != NULL) {
FSfwrite((const void*)&buffer,1,sizeof(buffer),logFile);
FSfclose(logFile);
}
//          mLED_1_On();
logFile = NULL;

//Now that we are done writing to the drive we can reattach
//  so that the PC can read the files that we just wrote.
LUNSoftAttach(0);
}
//        mLED_1_Off();
}
if(USBOn) {

prepOutBuffer(CMD_GETLOG);
strcpy((char *)&ToSendDataBuffer[2],buffer);

USBInHandle = HIDTxPacket(HID_EP,(BYTE*)ToSendDataBuffer,HID_INT_IN_EP_SIZE);
while(HIDTxHandleBusy(USBInHandle))        // QUA DOPO! (xché il buffer è usato “live”)
#if defined(USB_POLLING)
USBDeviceTasks()
#endif
; //USBDeviceTasks();

}
}
}        // print_tobuffer

}        // second_05

}

/****************************************************************************
Function:
DWORD   PIC24RTCCGetDate( void )

Description:
This routine reads the date from the RTCC module.

Precondition:
The RTCC module has been initialized.

Parameters:
None

Returns:
DWORD in the format <xx><YY><MM><DD>

Remarks:
To catch roll-over, we do two reads.  If the readings match, we return
that value.  If the two do not match, we read again until we get two
matching values.

For the PIC32MX, we use library routines, which return the date in the
PIC32MX format.
***************************************************************************/

DWORD PIC24RTCCGetDate( void ) {
DWORD_VAL   date1;
DWORD_VAL   date2;

do {
while(RCFGCALbits.RTCSYNC);

RCFGCALbits.RTCPTR0 = 1;
RCFGCALbits.RTCPTR1 = 1;
date1.w[1] = RTCVAL;
date1.w[0] = RTCVAL;

RCFGCALbits.RTCPTR0 = 1;
RCFGCALbits.RTCPTR1 = 1;
date2.w[1] = RTCVAL;
date2.w[0] = RTCVAL;

} while (date1.Val != date2.Val);

return date1.Val;
}

/****************************************************************************
Function:
DWORD   PIC24RTCCGetTime( void )

Description:
This routine reads the time from the RTCC module.

Precondition:
The RTCC module has been initialized.

Parameters:
None

Returns:
DWORD in the format <xx><HH><MM><SS>

Remarks:
To catch roll-over, we do two reads.  If the readings match, we return
that value.  If the two do not match, we read again until we get two
matching values.

For the PIC32MX, we use library routines, which return the time in the
PIC32MX format.
***************************************************************************/

DWORD PIC24RTCCGetTime( void ) {
DWORD_VAL   time1;
DWORD_VAL   time2;

do {
while(RCFGCALbits.RTCSYNC);

RCFGCALbits.RTCPTR0 = 1;
RCFGCALbits.RTCPTR1 = 0;
time1.w[1] = RTCVAL;
time1.w[0] = RTCVAL;

RCFGCALbits.RTCPTR0 = 1;
RCFGCALbits.RTCPTR1 = 0;
time2.w[1] = RTCVAL;
time2.w[0] = RTCVAL;

} while (time1.Val != time2.Val);

return time1.Val;
}

/****************************************************************************
Function:
void PIC24RTCCSetDate( WORD xx_year, WORD month_day )

Description:
This routine sets the RTCC date to the specified value.

Precondition:
The RTCC module has been initialized.

Parameters:
WORD xx_year    – BCD year in the lower byte
WORD month_day  – BCD month in the upper byte, BCD day in the lower byte

Returns:
None

Remarks:
For the PIC32MX, we use library routines.
***************************************************************************/

void PIC24RTCCSetDate( WORD xx_year, WORD month_day ) {

UnlockRTCC();
RCFGCALbits.RTCPTR0 = 1;
RCFGCALbits.RTCPTR1 = 1;
RTCVAL = xx_year;
RTCVAL = month_day;
}

/****************************************************************************
Function:
void PIC24RTCCSetTime( WORD weekDay_hours, WORD minutes_seconds )

Description:
This routine sets the RTCC time to the specified value.

Precondition:
The RTCC module has been initialized.

Parameters:
WORD weekDay_hours      – BCD weekday in the upper byte, BCD hours in the
lower byte
WORD minutes_seconds    – BCD minutes in the upper byte, BCD seconds in
the lower byte

Returns:
None

Remarks:
For the PIC32MX, we use library routines.
***************************************************************************/

void PIC24RTCCSetTime( WORD weekDay_hours, WORD minutes_seconds) {

UnlockRTCC();
RCFGCALbits.RTCPTR0 = 1;
RCFGCALbits.RTCPTR1 = 0;
RTCVAL = weekDay_hours;
RTCVAL = minutes_seconds;
}

/****************************************************************************
Function:
void UnlockRTCC( void )

Description:
This function unlocks the RTCC so we can write a value to it.

Precondition:
None

Parameters:
None

Return Values:
None

Remarks:
For the PIC32MX, we use library routines.
***************************************************************************/

#define RTCC_INTERRUPT_REGISTER IEC3
#define RTCC_INTERRUPT_VALUE    0×2000

void UnlockRTCC( void ) {
BOOL interruptsWereOn;

interruptsWereOn = FALSE;
if((RTCC_INTERRUPT_REGISTER & RTCC_INTERRUPT_VALUE) == RTCC_INTERRUPT_VALUE) {
interruptsWereOn = TRUE;
RTCC_INTERRUPT_REGISTER &= ~RTCC_INTERRUPT_VALUE;
}

// Unlock the RTCC module
__asm__ (“mov #NVMKEY,W0″);
__asm__ (“mov #0×55,W1″);
__asm__ (“mov #0xAA,W2″);
__asm__ (“mov W1,[W0]“);
__asm__ (“nop”);
__asm__ (“mov W2,[W0]“);
__asm__ (“bset RCFGCAL,#13″);
__asm__ (“nop”);
__asm__ (“nop”);

if(interruptsWereOn) {
RTCC_INTERRUPT_REGISTER |= RTCC_INTERRUPT_VALUE;
}
}

BYTE to_bcd(BYTE n) {

return (n % 10) | ((n / 10) << 4);
}

BYTE from_bcd(BYTE n) {

return (n & 15) + (10*(n >> 4));
}

// —————————————————————————————
void EEscrivi_(BYTE *addr,BYTE n) {

//FARE! forse
/*    #if defined(EEPROM_CS_TRIS)
XEEBeginWrite((WORD)addr+sizeof(AppConfig)+1);
XEEWrite(n);
XEEEndWrite();
#else
SPIFlashBeginWrite((WORD)addr);
SPIFlashWriteArray(&n, 1);
#endif
*/
}

// ******************************************************************************************************
// ************** USB Callback Functions ****************************************************************
// ******************************************************************************************************
// The USB firmware stack will call the callback functions USBCBxxx() in response to certain USB related
// events.  For example, if the host PC is powering down, it will stop sending out Start of Frame (SOF)
// packets to your device.  In response to this, all USB devices are supposed to decrease their power
// consumption from the USB Vbus to <2.5mA each.  The USB module detects this condition (which according
// to the USB specifications is 3+ms of no bus activity/SOF packets) and then calls the USBCBSuspend()
// function.  You should modify these callback functions to take appropriate actions for each of these
// conditions.  For example, in the USBCBSuspend(), you may wish to add code that will decrease power
// consumption from Vbus to <2.5mA (such as by clock switching, turning off LEDs, putting the
// microcontroller to sleep, etc.).  Then, in the USBCBWakeFromSuspend() function, you may then wish to
// add code that undoes the power saving things done in the USBCBSuspend() function.

// The USBCBSendResume() function is special, in that the USB stack will not automatically call this
// function.  This function is meant to be called from the application firmware instead.  See the
// additional comments near the function.

/******************************************************************************
* Function:        void USBCBSuspend(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        Call back that is invoked when a USB suspend is detected
*
* Note:            None
*****************************************************************************/
void USBCBSuspend(void) {

//Example power saving code.  Insert appropriate code here for the desired
//application behavior.  If the microcontroller will be put to sleep, a
//process similar to that shown below may be used:

//ConfigureIOPinsForLowPower();
//SaveStateOfAllInterruptEnableBits();
//DisableAllInterruptEnableBits();
//EnableOnlyTheInterruptsWhichWillBeUsedToWakeTheMicro();    //should enable at least USBActivityIF as a wake source
//Sleep();
//RestoreStateOfAllPreviouslySavedInterruptEnableBits();    //Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.
//RestoreIOPinsToNormal();                                    //Preferrably, this should be done in the USBCBWakeFromSuspend() function instead.

//IMPORTANT NOTE: Do not clear the USBActivityIF (ACTVIF) bit here.  This bit is
//cleared inside the usb_device.c file.  Clearing USBActivityIF here will cause
//things to not work as intended.

#if defined(__C30__)
#if 0
U1EIR = 0xFFFF;
U1IR = 0xFFFF;
U1OTGIR = 0xFFFF;
IFS5bits.USB1IF = 0;
IEC5bits.USB1IE = 1;
U1OTGIEbits.ACTVIE = 1;
U1OTGIRbits.ACTVIF = 1;
Sleep();
#endif
#endif
}

/******************************************************************************
* Function:        void _USB1Interrupt(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        This function is called when the USB interrupt bit is set
*                    In this example the interrupt is only used when the device
*                    goes to sleep when it receives a USB suspend command
*
* Note:            None
*****************************************************************************/
#if 0
void __attribute__ ((interrupt)) _USB1Interrupt(void) {
#if !defined(self_powered)
if(U1OTGIRbits.ACTVIF) {
IEC5bits.USB1IE = 0;
U1OTGIEbits.ACTVIE = 0;
IFS5bits.USB1IF = 0;

//USBClearInterruptFlag(USBActivityIFReg,USBActivityIFBitNum);
USBClearInterruptFlag(USBIdleIFReg,USBIdleIFBitNum);
//USBSuspendControl = 0;
}
#endif
}
#endif

/******************************************************************************
* Function:        void USBCBWakeFromSuspend(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        The host may put USB peripheral devices in low power
*                    suspend mode (by “sending” 3+ms of idle).  Once in suspend
*                    mode, the host may wake the device back up by sending non-
*                    idle state signalling.
*
*                    This call back is invoked when a wakeup from USB suspend
*                    is detected.
*
* Note:            None
*****************************************************************************/
void USBCBWakeFromSuspend(void) {

// If clock switching or other power savings measures were taken when
// executing the USBCBSuspend() function, now would be a good time to
// switch back to normal full power run mode conditions.  The host allows
// a few milliseconds of wakeup time, after which the device must be
// fully back to normal, and capable of receiving and processing USB
// packets.  In order to do this, the USB module must receive proper
// clocking (IE: 48MHz clock must be available to SIE for full speed USB
// operation).
}

/********************************************************************
Function:        void USBCB_SOF_Handler(void)

Description:     The USB host sends out a SOF packet to full-speed
devices every 1 ms. This interrupt may be useful
for isochronous pipes. End designers should
implement callback routine as necessary.

PreCondition:    None

Parameters:      None

Return Values:   None

Remarks:         None
*******************************************************************/
void USBCB_SOF_Handler(void) {
// No need to clear UIRbits.SOFIF to 0 here.
// Callback caller is already doing that.
}

/*******************************************************************
* Function:        void USBCBErrorHandler(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        The purpose of this callback is mainly for
*                  debugging during development. Check UEIR to see
*                  which error causes the interrupt.
*
* Note:            None
*******************************************************************/
void USBCBErrorHandler(void) {
// No need to clear UEIR to 0 here.
// Callback caller is already doing that.

// Typically, user firmware does not need to do anything special
// if a USB error occurs.  For example, if the host sends an OUT
// packet to your device, but the packet gets corrupted (ex:
// because of a bad connection, or the user unplugs the
// USB cable during the transmission) this will typically set
// one or more USB error interrupt flags.  Nothing specific
// needs to be done however, since the SIE will automatically
// send a “NAK” packet to the host.  In response to this, the
// host will normally retry to send the packet again, and no
// data loss occurs.  The system will typically recover
// automatically, without the need for application firmware
// intervention.

// Nevertheless, this callback function is provided, such as
// for debugging purposes.
}

/*******************************************************************
* Function:        void USBCBCheckOtherReq(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        When SETUP packets arrive from the host, some
*                     firmware must process the request and respond
*                    appropriately to fulfill the request.  Some of
*                    the SETUP packets will be for standard
*                    USB “chapter 9″ (as in, fulfilling chapter 9 of
*                    the official USB specifications) requests, while
*                    others may be specific to the USB device class
*                    that is being implemented.  For example, a HID
*                    class device needs to be able to respond to
*                    ”GET REPORT” type of requests.  This
*                    is not a standard USB chapter 9 request, and
*                    therefore not handled by usb_device.c.  Instead
*                    this request should be handled by class specific
*                    firmware, such as that contained in usb_function_hid.c.
*
* Note:            None
*******************************************************************/
void USBCBCheckOtherReq(void) {

USBCheckHIDRequest();
USBCheckMSDRequest();
}//end

/*******************************************************************
* Function:        void USBCBStdSetDscHandler(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        The USBCBStdSetDscHandler() callback function is
*                    called when a SETUP, bRequest: SET_DESCRIPTOR request
*                    arrives.  Typically SET_DESCRIPTOR requests are
*                    not used in most applications, and it is
*                    optional to support this type of request.
*
* Note:            None
*******************************************************************/
void USBCBStdSetDscHandler(void)
{
// Must claim session ownership if supporting this request
}//end

/*******************************************************************
* Function:        void USBCBInitEP(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        This function is called when the device becomes
*                  initialized, which occurs after the host sends a
*                     SET_CONFIGURATION (wValue not = 0) request.  This
*                    callback function should initialize the endpoints
*                    for the device’s usage according to the current
*                    configuration.
*
* Note:            None
*******************************************************************/
void USBCBInitEP(void) {

#if (MSD_DATA_IN_EP == MSD_DATA_OUT_EP)
USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
#else
USBEnableEndpoint(MSD_DATA_IN_EP,USB_IN_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
USBEnableEndpoint(MSD_DATA_OUT_EP,USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
#endif

//enable the HID endpoint
USBEnableEndpoint(HID_EP,USB_IN_ENABLED|USB_OUT_ENABLED|USB_HANDSHAKE_ENABLED|USB_DISALLOW_SETUP);
//Re-arm the OUT endpoint for the next packet
USBOutHandle = HIDRxPacket(HID_EP,(BYTE*)&ReceivedDataBuffer,64);

USBMSDInit();
}

/********************************************************************
* Function:        void USBCBSendResume(void)
*
* PreCondition:    None
*
* Input:           None
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        The USB specifications allow some types of USB
*                     peripheral devices to wake up a host PC (such
*                    as if it is in a low power suspend to RAM state).
*                    This can be a very useful feature in some
*                    USB applications, such as an Infrared remote
*                    control    receiver.  If a user presses the “power”
*                    button on a remote control, it is nice that the
*                    IR receiver can detect this signalling, and then
*                    send a USB “command” to the PC to wake up.
*
*                    The USBCBSendResume() “callback” function is used
*                    to send this special USB signalling which wakes
*                    up the PC.  This function may be called by
*                    application firmware to wake up the PC.  This
*                    function will only be able to wake up the host if
*                  all of the below are true:
*
*                    1.  The USB driver used on the host PC supports
*                        the remote wakeup capability.
*                    2.  The USB configuration descriptor indicates
*                        the device is remote wakeup capable in the
*                        bmAttributes field.
*                    3.  The USB host PC is currently sleeping,
*                        and has previously sent your device a SET
*                        FEATURE setup packet which “armed” the
*                        remote wakeup capability.
*
*                  If the host has not armed the device to perform remote wakeup,
*                  then this function will return without actually performing a
*                  remote wakeup sequence.  This is the required behavior,
*                  as a USB device that has not been armed to perform remote
*                  wakeup must not drive remote wakeup signalling onto the bus;
*                  doing so will cause USB compliance testing failure.
*
*                    This callback should send a RESUME signal that
*                  has the period of 1-15ms.
*
* Note:            This function does nothing and returns quickly, if the USB
*                  bus and host are not in a suspended condition, or are
*                  otherwise not in a remote wakeup ready state.  Therefore, it
*                  is safe to optionally call this function regularly, ex:
*                  anytime application stimulus occurs, as the function will
*                  have no effect, until the bus really is in a state ready
*                  to accept remote wakeup.
*
*                  When this function executes, it may perform clock switching,
*                  depending upon the application specific code in
*                  USBCBWakeFromSuspend().  This is needed, since the USB
*                  bus will no longer be suspended by the time this function
*                  returns.  Therefore, the USB module will need to be ready
*                  to receive traffic from the host.
*
*                  The modifiable section in this routine may be changed
*                  to meet the application needs. Current implementation
*                  temporary blocks other functions from executing for a
*                  period of ~3-15 ms depending on the core frequency.
*
*                  According to USB 2.0 specification section 7.1.7.7,
*                  “The remote wakeup device must hold the resume signaling
*                  for at least 1 ms but for no more than 15 ms.”
*                  The idea here is to use a delay counter loop, using a
*                  common value that would work over a wide range of core
*                  frequencies.
*                  That value selected is 1800. See table below:
*                  ==========================================================
*                  Core Freq(MHz)      MIP         RESUME Signal Period (ms)
*                  ==========================================================
*                      48              12          1.05
*                       4              1           12.6
*                  ==========================================================
*                  * These timing could be incorrect when using code
*                    optimization or extended instruction mode,
*                    or when having other interrupts enabled.
*                    Make sure to verify using the MPLAB SIM’s Stopwatch
*                    and verify the actual signal on an oscilloscope.
*******************************************************************/
void USBCBSendResume(void) {
static WORD delay_count;

//First verify that the host has armed us to perform remote wakeup.
//It does this by sending a SET_FEATURE request to enable remote wakeup,
//usually just before the host goes to standby mode (note: it will only
//send this SET_FEATURE request if the configuration descriptor declares
//the device as remote wakeup capable, AND, if the feature is enabled
//on the host (ex: on Windows based hosts, in the device manager
//properties page for the USB device, power management tab, the
//”Allow this device to bring the computer out of standby.” checkbox
//should be checked).
if(USBGetRemoteWakeupStatus() == TRUE) {
//Verify that the USB bus is in fact suspended, before we send
//remote wakeup signalling.
if(USBIsBusSuspended() == TRUE) {
USBMaskInterrupts();

//Clock switch to settings consistent with normal USB operation.
USBCBWakeFromSuspend();
USBSuspendControl = 0;
USBBusIsSuspended = FALSE;  //So we don’t execute this code again,
//until a new suspend condition is detected.

//Section 7.1.7.7 of the USB 2.0 specifications indicates a USB
//device must continuously see 5ms+ of idle on the bus, before it sends
//remote wakeup signalling.  One way to be certain that this parameter
//gets met, is to add a 2ms+ blocking delay here (2ms plus at
//least 3ms from bus idle to USBIsBusSuspended() == TRUE, yeilds
//5ms+ total delay since start of idle).
delay_count = 3600U;
do {
delay_count–;
} while(delay_count);

//Now drive the resume K-state signalling onto the USB bus.
USBResumeControl = 1;       // Start RESUME signaling
delay_count = 1800U;        // Set RESUME line for 1-13 ms
do {
delay_count–;
} while(delay_count);
USBResumeControl = 0;       //Finished driving resume signalling

USBUnmaskInterrupts();
}
}
}

/*******************************************************************
* Function:        BOOL USER_USB_CALLBACK_EVENT_HANDLER(
*                        USB_EVENT event, void *pdata, WORD size)
*
* PreCondition:    None
*
* Input:           USB_EVENT event – the type of event
*                  void *pdata – pointer to the event data
*                  WORD size – size of the event data
*
* Output:          None
*
* Side Effects:    None
*
* Overview:        This function is called from the USB stack to
*                  notify a user application that a USB event
*                  occured.  This callback is in interrupt context
*                  when the USB_INTERRUPT option is selected.
*
* Note:            None
*******************************************************************/
BOOL USER_USB_CALLBACK_EVENT_HANDLER(USB_EVENT event, void *pdata, WORD size) {

switch(event) {
case EVENT_TRANSFER:
//Add application specific callback task or callback function here if desired.
break;
case EVENT_SOF:
USBCB_SOF_Handler();
break;
case EVENT_SUSPEND:
USBCBSuspend();
break;
case EVENT_RESUME:
USBCBWakeFromSuspend();
break;
case EVENT_CONFIGURED:
USBCBInitEP();
break;
case EVENT_SET_DESCRIPTOR:
USBCBStdSetDscHandler();
break;
case EVENT_EP0_REQUEST:
USBCBCheckOtherReq();
break;
case EVENT_BUS_ERROR:
USBCBErrorHandler();
break;
case EVENT_TRANSFER_TERMINATED:
//Add application specific callback task or callback function here if desired.
//The EVENT_TRANSFER_TERMINATED event occurs when the host performs a CLEAR
//FEATURE (endpoint halt) request on an application endpoint which was
//previously armed (UOWN was = 1).  Here would be a good place to:
//1.  Determine which endpoint the transaction that just got terminated was
//      on, by checking the handle value in the *pdata.
//2.  Re-arm the endpoint if desired (typically would be the case for OUT
//      endpoints).

//Check if the host recently did a clear endpoint halt on the MSD OUT endpoint.
//In this case, we want to re-arm the MSD OUT endpoint, so we are prepared
//to receive the next CBW that the host might want to send.
//Note: If however the STALL was due to a CBW not valid condition,
//then we are required to have a persistent STALL, where it cannot
//be cleared (until MSD reset recovery takes place).  See MSD BOT
//specs v1.0, section 6.6.1.
if(MSDWasLastCBWValid() == FALSE) {
//Need to re-stall the endpoints, for persistent STALL behavior.
USBStallEndpoint(MSD_DATA_IN_EP, IN_TO_HOST);
USBStallEndpoint(MSD_DATA_OUT_EP, OUT_FROM_HOST);
}
else {
//Check if the host cleared halt on the bulk out endpoint.  In this
//case, we should re-arm the endpoint, so we can receive the next CBW.
if((USB_HANDLE)pdata == USBGetNextHandle(MSD_DATA_OUT_EP, OUT_FROM_HOST)) {
USBMSDOutHandle = USBRxOnePacket(MSD_DATA_OUT_EP, (BYTE*)&msd_cbw, MSD_OUT_EP_SIZE);
}
}
break;
default:
break;
}

return TRUE;
}

// tastiera/lcd —————————————————————————————-
/*volatile*/ BYTE kbScanCode;            // il num. progressivo del tasto scandito

/*volatile*/ BYTE kbKeys[4];            // stato dei tasti        (max 4=MAX_TASTI_CONTEMPORANEI contemp.)
BYTE kbKeysOld[4];                // stato dei tasti old

BYTE KBInit(void) {

TRISC |= 0b0000001111000000;
EnablePullUpCN17;            // pull-up
EnablePullUpCN18;
EnablePullUpCN19;
EnablePullUpCN20;

return 1;
}

void scanKBD(void) {
WORD kbtemp;

kbKeys[0]=0;
kbKeys[1]=0;
kbKeys[2]=0;
kbKeys[3]=0;

kbScanCode=1;            // parto da 1!! (se no lo zero=non valido taglierebbe via ROW0:COL0)
kbtemp=0b1000000;

do {
ClrWdt();

__delay_us(10);                                // ritardino…

if(!(PORTC & kbtemp))
checkKey(/*kbScanCode*/);

kbScanCode++;
//        bcf     STATUS,C                    ; entra 0
kbtemp <<= 1;
} while(!(kbtemp & 0b10000000000));                // quando ne ho fatte 4…

FLAGS |= (1 << TRIGK);

//        }            // NOSCANK
}

BYTE checkKey(void) {
BYTE *p;
BYTE n;

p=kbKeys;
for(n=0; n<4; n++) {
ClrWdt();
if(!*p) {                            //    cerco un posto vuoto x metterci lo scan code
*p=kbScanCode;
goto checkKey_fine;
}
p++;
}

#ifdef USA_KB_BUZZER
// suonare male!
mBeepON=0;

__delay_ms(20);                                 // ritardo almeno 20mSec

mBeepON=1;
#endif

return 0;
// non ho più posto (max 4 tasti contemporanei!) dare errore!! (tutti 0×1)

checkKey_fine:

return 1;                                    //
}

void kbEmptyBuf(void) {

kbKeys[0]=0;
}

const struct LCD_ITEM_GROUP lcdItems[ULTIMA_SCHERMATA_PROGRAMMAZIONE-PRIMA_SCHERMATA_PROGRAMMAZIONE] =
{
10,1,0,0,1,(WORD *)&ShieldOn,1,            //size=0 e val min/max 0..1 indicano ON/OFF!
0,0,0,0,0,0,0,        // non usata

10,0,2,0,31,(WORD *)&currentDate,2,
10,1,2,0,24,(WORD *)&currentTime,2,

0,0,0,0,0,NULL,0,        // non usata
8,1,1,0,1,(WORD *)&Tube,1,

0,0,0,0,0,NULL,0,        // non usata
9,1,1,0,2,(WORD *)&Sensitivity,1,

9,1,1,0,4,(WORD *)&UnitaMisura,1,
0,0,0,0,0,NULL,0,        // non usata

10,1,0,0,1,(WORD *)&SDcardOn,1,
0,0,0,0,0,NULL,0,        // non usata

10,0,0,0,1,(WORD *)&RS232On,1,
10,1,0,0,1,(WORD *)&USBOn,1,

0,0,0,0,0,NULL,0,        // non usata
1,1,5,0,65535,(WORD *)&alarmThrs,2,

0,0,0,0,0,NULL,0,        // non usata
1,1,5,0,65535,(WORD *)&recThrs,2,

14,1,0,0,1,(WORD*)&ReadyOrSleep,1,
0,0,0,0,0,NULL,0,        // non usata

12,1,5,110,65535,(WORD *)&baudRate,2,
0,0,0,0,0,NULL,0,        // non usata

12,0,2,0,15,(WORD *)&LuceLCD,1,
12,1,2,0,15,(WORD *)&ContrLCD,1,

14,1,1,0,1,(WORD*)NULL,1,        //x FORMATTAZIONE, gestire!
0,0,0,0,0,NULL,0,        // non usata

};

const char *Schermate[2*(ULTIMA_SCHERMATA_PROGRAMMAZIONE-SCHERMATA_SPLASH)] = {        //

“  Cyberdyne/NE  “,     /* 0 */
“Contatore Geiger”,

“                “,     // 1
“          mR/h  “,

“  High:         “,     // 2
“  Low:          “,

“Media:          “,     // 3
“Dev.Std:        “,

“Stato:          “,     // 4
“            MB  “,

“                “,     // 5 versione/data
“                “,

“    (VT-100)    “,     // 6 emulazione terminale seriale
“                “,

“  Schermo:      “,     // 7
“                “,

“                “,     // 8 data/ora
“                “,

” Modello tubo:  “,     // 9
“                “,

” Sensibilita’:  “,     // 10
“                “,

” Unita’ misura: “,     // 11
“                “,

“   SDcard:      “,     // 12
“                “,

“   RS232:       “,     // 13
“   USB:         “,

“Soglia allarme: “,     // 14
“                “,

“Soglia registr.:”,     // 15
“                “,

” Stato:         “,     // 16 ready/sleep
“                “,

“  Baud rate:    “,     // 17
“                “,

” Luce:          “,     // 18
” Contrasto:     “,

“Formatt. SDcard?”,     // 19
“                “,

// reset?
// PIN per accedere a programmazione?
};

void handleKBD(void) {
BYTE i;
DWORD n;
static BYTE oldk=0;
static DWORD Valore;
static BYTE sizeValore,posValore;
struct LCD_ITEM *lcdItemPtr;

enum TASTI {
TASTO_SET=1,
TASTO_LEFT=2,
TASTO_RIGHT=3,
TASTO_MODE=4
};

// i tasti multipli sono in pos. successive di kbKeys…

if((i=kbKeys[0])) {
if(i != oldk) {
oldk=i;
//            LCDprintDec(kbKeys[0]);

lastTimeKB=TickGet();

LuceLCD=15;
aggLuceContrasto();

switch(menuLevel) {
case MENU_IDLE:        // SCHERMATA_SPLASH idle, qualsiasi tasto
menuLevel=MENU_VISUALIZZAZIONE;
currSchermata=SCHERMATA_PRINCIPALE;
currSchermItem=0;
enterData=0;
break;

case MENU_VISUALIZZAZIONE:
switch(i) {
case TASTO_SET:
currSchermata=PRIMA_SCHERMATA_PROGRAMMAZIONE;
menuLevel=MENU_PROGRAMMAZIONE;
break;
case TASTO_LEFT:
if(currSchermata > PRIMA_SCHERMATA_VISUALIZZAZIONE)
currSchermata–;
//                        menuLevel=1;
break;
case TASTO_RIGHT:
if(currSchermata < ULTIMA_SCHERMATA_VISUALIZZAZIONE)
currSchermata++;
//                        menuLevel=3;        // entrare in programmazione come facevano loro??
break;
case TASTO_MODE:
ReadyOrSleep=READY;
mGeigerON= !mGeigerON;
break;
}
break;

case MENU_PROGRAMMAZIONE:
lcdItemPtr=(struct LCD_ITEM *)&lcdItems[(currSchermata-PRIMA_SCHERMATA_PROGRAMMAZIONE)];
lcdItemPtr+=(currSchermItem);
switch(i) {
case TASTO_SET:
if(enterData) {        // conferma valore
switch(currSchermata) {
case PRIMA_SCHERMATA_PROGRAMMAZIONE+11:     // lcd
//                                    EEscriviValori();
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+12:     // format
if(0)        //finire
FSformat(0,rand(),”NEGeiger”);
break;
default:
switch(lcdItemPtr->varSize) {
case 1:
if(lcdItemPtr->valMin==0 && lcdItemPtr->valMax==1)
*((BYTE *)lcdItemPtr->var)=Valore & 1;
else
*((BYTE *)lcdItemPtr->var)=Valore & 0xff;
break;
case 2:
//                                            if((currSchermata >= PRIMA_SCHERMATA_PROGRAMMAZIONE+7 && currSchermata <= PRIMA_SCHERMATA_PROGRAMMAZIONE+8))        // gestisco decimi in soglie
//                                                *lcdItemPtr->var=Valore*10;
//                                            else
*lcdItemPtr->var=Valore;
break;
}
//SaveAppConfig();
break;
}
//                            switch(currSchermItem) {
//                                }
enterData=0;
LCDCursor(0);
}
else {
//                            if(currSchermata != PRIMA_SCHERMATA_PROGRAMMAZIONE+12 /* lingua no!*/) {
// gestire schermate particolari
if(1 || currSchermItem) {        // se su campo numerico modificabile, ci “entro” FINIRE!
enterData=1;
sizeValore=lcdItemPtr->size; posValore=sizeValore ? sizeValore-1 : 0;        // sulle unità o on/off
switch(lcdItemPtr->varSize) {
case 1:
if(lcdItemPtr->valMin==0 && lcdItemPtr->valMax==1)
Valore=*((BYTE *)lcdItemPtr->var) ? 1 : 0;
else
Valore=*((BYTE *)lcdItemPtr->var);
break;
case 2:
//                                            if((currSchermata >= PRIMA_SCHERMATA_PROGRAMMAZIONE+7 && currSchermata <= PRIMA_SCHERMATA_PROGRAMMAZIONE+8))        // gestisco decimi in soglie…
//                                                Valore=*lcdItemPtr->var/10;        //
//                                            else
Valore=*lcdItemPtr->var;        //
break;
}
LCDX=lcdItemPtr->x+posValore;        // sulle unità
LCDXY(currSchermItem);
LCDCursor(1);
}
else {                                    // se no esco
currSchermata=SCHERMATA_PRINCIPALE;
menuLevel=MENU_IDLE;        // o main?
}
//                                }
//                            else {
//                                ValoriInEEprom.LCDlingua=currSchermItem;
//                                EEscriviValori();
//                                goto esci_top;
//                                }

}
break;
case TASTO_RIGHT:
if(enterData) {
switch(currSchermata) {
case PRIMA_SCHERMATA_PROGRAMMAZIONE+2:        // tubo
LCDPutCharXY(9,currSchermItem,’ ‘);
if(currSchermItem > 0)
currSchermItem–;
LCDPutCharXY(9,currSchermItem,’>’);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+3:        // sensibilità
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+4:         // unità misura
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+12:     // formatt
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+11:     // lcd
break;
default:
if(lcdItemPtr->valMin==0 && lcdItemPtr->valMax==1) {
Valore=!Valore;
case_4_1_b:
LCDWriteBool(lcdItemPtr->x,currSchermItem,Valore);
}
else {
i=sizeValore-posValore;
n=1;
while(–i>0)
n*=10;
if((Valore+n)<=lcdItemPtr->valMax)            // 4 cifre max??
Valore+=n;
else {
//                                ErrorBeep();
}
LCDWriteNum(lcdItemPtr->x,currSchermItem,Valore,lcdItemPtr->size);
}
case_4_1:
LCDX=lcdItemPtr->x+posValore;        //
LCDXY(currSchermItem);
break;
}
}
else {
switch(currSchermata) {
case PRIMA_SCHERMATA_PROGRAMMAZIONE+11:        // lcd, xché ha 2 item (forse) FINIRE!
if(currSchermItem) {
//                                    LCDX=lcdItems[currSchermata-PRIMA_SCHERMATA_PROGRAMMAZIONE-1].item[currSchermItem-1 /*1 based*/].x-1;        // prompt subito a sx del valore
LCDPutCharXY(lcdItemPtr->x-1,currSchermItem,’ ‘);
}
if(currSchermItem > 0)
currSchermItem–;
// else far comparire un “OK” o simbolo per dire che si può uscire e confermare?
case4_1_1:
if(currSchermItem) {    // servirà, qua?? !FINIRE
LCDPutCharXY(lcdItems[currSchermata-PRIMA_SCHERMATA_PROGRAMMAZIONE-1].item[currSchermItem-1 /*1 based*/].x-1,        /* prompt subito a sx del valore*/
currSchermItem,’>’);
}
break;
default:
if(currSchermata < (ULTIMA_SCHERMATA_PROGRAMMAZIONE-1 /*lcd no!*/)) {
currSchermata++;
// cerco il 1° item
if(lcdItems[currSchermata-PRIMA_SCHERMATA_PROGRAMMAZIONE].item[0].varSize)
currSchermItem=0;
else
currSchermItem=1;
}
break;
}
}
break;
case TASTO_LEFT:
if(enterData) {
switch(currSchermata) {
case PRIMA_SCHERMATA_PROGRAMMAZIONE+2:        // tubo
LCDPutCharXY(9,currSchermItem,’ ‘);
if(currSchermItem > 0)
currSchermItem–;
LCDPutCharXY(9,currSchermItem,’>’);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+3:        // sensibilità
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+4:         // unità misura
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+12:     // formatt
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+11:     // lcd
break;
default:
if(lcdItemPtr->valMin==0 && lcdItemPtr->valMax==1) {
Valore=!Valore;
goto case_4_1_b;
}
else {
i=sizeValore-posValore;
n=1;
while(–i>0)
n*=10;
if(Valore>=n && (Valore-n)>lcdItemPtr->valMin)
Valore-=n;
else {
//                                ErrorBeep();
}
goto case_4_1;
}
break;
}
}
else {
switch(currSchermata) {
case PRIMA_SCHERMATA_PROGRAMMAZIONE+11:        // lcd , v.sopra
if(currSchermItem) {
//                                    LCDX=lcdItems[currSchermata-PRIMA_SCHERMATA_PROGRAMMAZIONE-1].item[currSchermItem-1 /*1 based*/].x-1;        // prompt subito a sx del valore
LCDPutCharXY(lcdItemPtr->x-1,currSchermItem,’ ‘);
}
if(currSchermItem > 0)
currSchermItem–;
// else far comparire un “OK” o simbolo per dire che si può uscire e confermare?
goto case4_1_1;
break;
default:
if(currSchermata > PRIMA_SCHERMATA_PROGRAMMAZIONE && currSchermata != PRIMA_SCHERMATA_PROGRAMMAZIONE+11 /* da lcd no!*/) {
currSchermata–;
currSchermItem=0;
}
break;
}
}
break;
case TASTO_MODE:
if(enterData) {
if(posValore>0) {        //
LCDPutChar(14);
posValore–;
}
}
else {
LCDCursor(0);// mmm non dovrebbe servire…
currSchermata=SCHERMATA_PRINCIPALE;
menuLevel=MENU_IDLE;        // o main?
}
break;
#if 0
//no, questo qua semplicemente non c’è
case TASTO_RIGHT:
if(enterData) {
if(posValore<(sizeValore-1)) {        //
LCDPutChar(15);
posValore++;
}
}
else {
if(currSchermata < (ULTIMA_SCHERMATA_PROGRAMMAZIONE-2 /*lcd e lingua no!*/)) {
currSchermata++;
currSchermItem=0;
}
}
break;
#endif
}
break;

}
}
kbEmptyBuf();
}
else {
oldk=-1;
}

}

/*****************************************************************************
Function:
BYTE void uitoa(WORD Value, char * Buffer)            modifiche GD gen 2011!

Summary:
Converts an unsigned integer to a decimal string.

Description:
Converts a 16-bit unsigned integer to a null-terminated decimal string.

Precondition:
None

Parameters:
Value    - The number to be converted
Buffer    - Pointer in which to store the converted string

Returns:
# of digits written
***************************************************************************/
BYTE uitoa(WORD Value, char *Buffer) {
BYTE i;
WORD Digit;
WORD Divisor;
BOOL Printed = FALSE;
char *oldBuffer=Buffer;

if(Value)    {
for(i=0, Divisor = 10000; i < 5u; i++) {
Digit = Value/Divisor;
if(Digit || Printed) {
*Buffer++ = ’0′ + Digit;
Value -= Digit*Divisor;
Printed = TRUE;
}
Divisor /= 10;
}
}
else {
*Buffer++ = ’0′;
}

*Buffer = 0;

return Buffer-oldBuffer;
}

void LCDWriteNum(BYTE x,BYTE y,WORD n,signed char size) {
char buffer[10];

LCDX=x;
LCDXY(y);
size-=uitoa(n,buffer);
if(size>0) {
while(size–)
LCDPutBlank();
}
LCDWrite(buffer);
}

void LCDWriteStr(BYTE x,BYTE y,char *str) {

LCDX=x;
LCDXY(y);
LCDWrite(str);
}

void LCDWriteBool(BYTE x,BYTE y,BYTE n) {

LCDX=x;
LCDXY(y);
LCDWrite(n ? “ON ” : “OFF”);        // lo spazio finale serve!
}

void LCDPutCharXY(BYTE x,BYTE y,char c) {

LCDX=x;
LCDXY(y);
LCDPutChar(c);
}

void updLCD(void) {
char buffer[18];
short int i;
static BYTE oldSchermata=-1;
WORD n;
DWORD n2;

if(oldSchermata != currSchermata) {            //cache
LCDCls();        // o usare home?
for(i=0; i<2; i++) {
LCDWrite(Schermate[currSchermata*2+i]);
}
}

if(!enterData) {
switch(currSchermata) {
case SCHERMATA_SPLASH:
//        case SCHERMATA_PRINCIPALE:
break;
case PRIMA_SCHERMATA_VISUALIZZAZIONE:
sprintf(buffer,”%s  %s %c%c%c%c%c%c%c%c”,SDcardOK ? “   ” : “SDe”,InAlert ? “Al” : “  “,
ShieldOn ? ‘#’ : ‘ ‘,Tube == LND712 ? ‘L’ : ‘S’,
recThrs>0 ? ‘x81′ : ‘ ‘,alarmThrs>0 ? ‘x82′ : ‘ ‘,
(RS232On || USBOn) ? ‘x83′ : ‘ ‘,SDcardOn>0 ? ‘x84′ : ‘ ‘,
batteryState ? ‘x85′ : ‘x86′,
mGeigerON ? ‘x87′ : ‘ ‘
);
LCDWriteStr(0,0,buffer);
//http://www.blackcatsystems.com/GM/converting_CPM_mRhr.html
switch(Sensitivity) {
case CS137:        //1080 CPM = 1mR/hour
n2=(cpsVal*60000)/1080;
break;
case CO60:        //1200 CPM = 1mR/hour
n2=(cpsVal*60000)/1200;        //
break;
case RA226:
n2=(cpsVal*60000)/1000;        // finire!
break;
}
switch(UnitaMisura) {
// REM e ROENTGEN sono la stessa cosa o quasi, dicono…
//http://allegedlyapparent.wordpress.com/radioactivity/radiation_units/
//http://www.civildefensemuseum.com/southrad/conversion.html
case MILLIROENTGEN:        // 100 rem = 1 sievert (Sv) ; 0.01 Sv = 1 rem; 10000 uSv = 1000 mrem; 10uSv = 1mrem
sprintf(buffer,”%4.3f”,(n2)/(1000.0));        // (v.sotto) estrapolo da /sec a /min; *10
break;
case CPS:
sprintf(buffer,”%5.1f”,cpsVal/10.0);
break;
case UGY:            // 100 rad = 1 gray (Gy) 0.01 Gy = 1 rad; siccome rem e Rad sono quasi uguali… esce lo stesso dei uSv!
sprintf(buffer,”%5.3f”,(n2)/100.0);
break;
case USV:        //For my Geiger Counter, 100 CPM = 1 MicroSievert of Exposure Per Hour (1 uSv/hr)
sprintf(buffer,”%5.3f”,(n2)/100.0);        // estrapolo da /sec a /min
break;
case UCKG:    //1R = 2.58 X 10-4 C kg-1 => 1 C/Kg = 1mRem/.258 => 1uC/Kg = 1mRem/.258 (c’è un dubbio tra C/Kg e uC/Kg … boh..)
sprintf(buffer,”%5.4f”,(n2)/(1000.0)/0.258);
break;
}
LCDWriteStr(2,1,buffer);
LCDWriteStr(10,1,UnitaMisura==MILLIROENTGEN ? “mR/h ” :
(UnitaMisura==CPS ? “Cps  ” :
(UnitaMisura==UGY ? “uGy  ” :
(UnitaMisura==USV ? “uSv  ” : “uC/Kg”
))));
break;
case PRIMA_SCHERMATA_VISUALIZZAZIONE+1:
LCDWriteNum(8,0,maxValue,4);
LCDWriteNum(8,1,minValue,4);
break;
case PRIMA_SCHERMATA_VISUALIZZAZIONE+2:
LCDWriteNum(8,0,medValue,4);
LCDWriteNum(8,1,stddevValue,4);
break;
case PRIMA_SCHERMATA_VISUALIZZAZIONE+3:
LCDWriteStr(8,0,ReadyOrSleep ? “ATTIVO” : “STANDBY”);
if(oldSchermata != currSchermata) {        // solo primo giro
if(SDcardOK) {
FS_DISK_PROPERTIES disk_properties;
disk_properties.new_request = TRUE;
//smontare USB se è connesso?
do {
FSGetDiskProperties(&disk_properties);        // fino a 7 secondi per 1GB, dice!! occhio…
ClrWdt();
} while (disk_properties.properties_status == FS_GET_PROPERTIES_STILL_WORKING);
n2=8*disk_properties.results.sector_size*disk_properties.results.free_clusters;
// mah.. 1 cluster= 8 settori? !
}
else
n2=0;
LCDWriteNum(8,1,n2/1048576,4);        //MB liberi
}
break;
case PRIMA_SCHERMATA_VISUALIZZAZIONE+4:
LCDWriteStr(0,0,(char *)CopyrString+28);        // “v.xx..
break;

case PRIMA_SCHERMATA_VISUALIZZAZIONE+5:        // un banale terminale.. :)
if(RS232On) {        //boh?
while(Buf232PtrO != Buf232PtrI) {
LCDPutChar(Buf232[Buf232PtrO]);
Buf232PtrO++;
Buf232PtrO &= (BUF_232_SIZE-1);
}
}
break;

case PRIMA_SCHERMATA_PROGRAMMAZIONE:
LCDWriteBool(10,0,ShieldOn);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+1:
LCDWriteNum(5,0,currentDate.mday,2);
LCDWriteNum(8,0,currentDate.mon,2);
LCDWriteNum(11,0,currentDate.year,2);
LCDWriteNum(5,1,currentTime.hour,2);
LCDWriteNum(8,1,currentTime.min,2);
LCDWriteNum(11,1,currentTime.sec,2);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+2:
LCDWriteStr(8,1,Tube==LND712 ? “LND712″ : “SBM-20″);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+3:
LCDWriteStr(9,1,Sensitivity==CO60 ? “Co60″ : (Sensitivity==RA226 ? “Ra226″ : “Cs137″));
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+4:
LCDWriteStr(9,1,UnitaMisura==MILLIROENTGEN ? “mR/h ” :
(UnitaMisura==CPS ? “Cps  ” :
(UnitaMisura==UGY ? “uGy  ” :
(UnitaMisura==USV ? “uSv  ” : “uC/Kg”
))));
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+5:
LCDWriteBool(10,0,SDcardOn);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+6:
LCDWriteBool(10,0,RS232On);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+7:
LCDWriteNum(1,1,alarmThrs,5);
LCDWriteStr(8,1,”mR/h”);            // è fissa o no?? CPS o ?
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+8:
LCDWriteNum(1,1,recThrs,5);
LCDWriteStr(8,1,”mR/h”);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+9:    //boh?? PARAMETRI..?
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+10:
LCDWriteNum(4,1,baudRate,5);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+11:
LCDWriteNum(10,0,LuceLCD,2);
LCDWriteNum(10,1,8 /*ContrastoLCD */,2);
break;
case PRIMA_SCHERMATA_PROGRAMMAZIONE+12:
// formattare SD?
break;

case ULTIMA_SCHERMATA_PROGRAMMAZIONE:        // gestita tutta di là
//            LCDWrite(“Uscite:”);
break;

}
}

oldSchermata = currSchermata;            // messo qua  x consentire eventi “solo 1 volta” come SDcard
}

/** EOF main.c ***************************************************************/
#if 0
ICInit();

unsigned int period ;          //config1=0;// ,config2=0;

//iPPSInput(IN_FN_PPS_IC1,IN_PIN_PPS_RP2);  //This chip does not suppost PPS

Int_flag = 0; //Initialize interrupt flag

/* Input Capture Interrupt Enabled with interrupt priority set to 4 Input capture unit uses Timer 1 as source of count Input capture in every falling edge IC cascade disabled Interrupt on first capture Stop IC during Idle Mode */

//ConfigIntCapture1(IC_INT_ON |IC_INT_PRIOR_4);     //I tried with these and even without just using the function

//config1 = IC_IDLE_STOP | IC_TIMER2_SRC | IC_INT_1CAPTURE | IC_EVERY_RISE_EDGE;
//config2 = IC_CASCADE_DISABLE ;//| IC_SYNC_ENABLE | IC_SYNC_TRIG_IN_TMR2;

T2CON = 0×8000;

OpenCapture1(config1);                                           //Configure Input Capture module

while(!Int_flag);                                                        //wait till two succssive falling edges
period = timer_second_edge – timer_first_edge;      //calculate the time between two successive falling edges

Interrupt_Count = 0;
count = 0;

CloseCapture1();                                                        //disable the Input Capture module

while(1);

return(0);

}

// Interrupt service routine for Input Capture

void __attribute__((interrupt,no_auto_psv)) _IC1Interrupt(void)
{
Interrupt_Count++; //Number Input Capture counts
if(Interrupt_Count == 1)
ReadCapture1(&timer_first_edge); //Read the Time count for first capture of signal

else if(Interrupt_Count == 2)
{

ReadCapture1(&timer_second_edge);                //read the time count for second capture signal
Int_flag = 1;                                                        //On two captured signals set the flag

}
IC1_Clear_Intr_Status_Bit; //Interrupt status clear
}

void ICInit(void)
{
IPC0bits.IC1IP = 4; /*set low priority*/
CNEN1bits.CN9IE=1;
IFS0bits.IC1IF = 0;    /*Reset INT1 interrupt flag */
IEC0bits.IC1IE = 1;    /*Enable INT1 Interrupt Service Routine */
IC1CON = 0x00B3; // Turn on Input Capture 1 Module
}
#endif

/*
Example:
Baseline (8 hours) 14 CPM
Food (4 hours) 15 CPM – Most likely little to no contamination.

Baseline (8 hours) 14 CPM
Food (4 hours) 18 CPM – Perhaps some contamination.

Remember, when checking food, some foods are naturally radioactive. This is safe and not dangerous. Any foods high in potassium might read higher. Bananas, potatoes, tomatoes, etc. Also, Brazil Nuts contain small amounts of radium. These are all safe.

The big worry is surface contamination. Radioactive material in food is often passed through the body with little harm. A well washed food is often made safe.

Tips and Extra’s

My normal ranges are 7 CPM — 28 CPM (14 normally).
Anything less than 100 CPM is generally quite safe.

For my Geiger Counter, 100 CPM = 1 Micro Seivert of Exposre Per Hour (1 uSv/hr)

CPM = Counters Per Minute
uSv/hr = Micro Sieverts Per hour
mSv/hr = Milli Sieverts Per hour
mR = miliroentgens per hour
mrem = milirems per hour

For my Geiger Counter, the conversion from uSv/hr to CPM is:
uSv/hr = CPM / 100 (For my Geiger Counter)
25 CPM = 25/100 = 0.25 uSv/hr

Roentgen = REM

These two are the same for most applications. They are actually different, but they are interchangeable for most instances.
Example: 23mR = 23mrem

1 Seivert / 1000 = 1 mSv
1 mSv / 1000 = 1 uSv
1 uSv / 1000 = 1 nSv

Websites:
My website:

http://anti-proton.com

GeigerCounters.com

http://www.geigercounters.com/AboutGgr.htm

USA Enviromental Protection Agency — determine your annual exposure

http://www.epa.gov/radiation/understand/calculate.html

Conversion Equivalence
1 curie = 3.7 x 1010
disintegrations per second         1 becquerel =
1 disintegration per second
1 millicurie (mCi)     =     37 megabecquerels (MBq)
1 rad     =     0.01 gray (Gy)
1 rem     =     0.01 sievert (Sv)
1 roentgen (R)     =     0.000258 coulomb/kilogram (C/kg)
1 megabecquerel (MBq)     =     0.027 millicuries (mCi)
1 gray (Gy)     =     100 rad
1 sievert (Sv)     =     100 rem
1 coulomb/kilogram (C/kg)     =     3,880 roentgens

Conversion Factors
To convert from                 To                                             Multiply by
Curies (Ci)                         becquerels (Bq)                                 3.7 x 1010
millicuries (mCi)             megabecquerels (MBq)                         37
microcuries (µCi)             megabecquerels (MBq)                         0.037
millirads (mrad)                 milligrays (mGy)                                 0.01
millirems (mrem)                 microsieverts (µSv)                         10
milliroentgens (mR)         microcoulombs/kilogram (µC/kg)     0.258

becquerels (Bq)                 curies (Ci)                                         2.7 x 10-11
megabecquerels (MBq)         millicuries (mCi)                             0.027
megabecquerels (MBq)         microcuries (µCi)                             27
milligrays (mGy)                 millirads (mrad)                                 100
microsieverts (µSv)         millrems (mrem)                                 0.1
microcoulombs/kilogram (µC/kg)         milliroentgens (mR)     3.88
*/