La mia piccola fusione fredda privata

Sperimentando la fusione fredda

Archive for the ‘Senza categoria’ Category

Updates 2016

Posted Saturday, June 11th, 2016

Professors Leif Holmlid and Sveinn Olafsson cold fusion research since 2003 results in dozens of  their competent reports in mainstream journals: Rich Murray 2016.06.10

 

Today I happened to look into cold fusion research, which I have kept tabs on since March 1989, and found that, finally, some real tangible vigorous scientific progress is happening since 2003 with a few competent physicists from Iceland and Norway, in a small system that allows a high level of control and repetition and a variety of readily provable and surprising results, along with an adequate theory –

 

will probably mean unlimited free safe energy from small to huge systems that are inherently safe, light-weight, low-cost, non-polluting –

 

so I am finding and joining some forums about it, with up to 1800 members, with people I already know, and writing up a summary review for my own pleasure and my blog…

https://www.lenr-forum.com/forum/  1800 members

 

 

[ gives a translation of a newspaper story in Norway ]

 

2016  April  03  COLD FUSION

Real, Revolutionary, and Ready.

Says Leading Scandinavian Newspaper

 

Aftenposten, a mainstream newspaper in Norway is publishing on Cold Fusion.

 

Here is a ‘translation patched up with contextual English/Physics parlance’ of the April 2, 2016, Norwegian report that features an interview with physicist Sindre Zeiner-Gundersen, who revealed details of an operating experimental cold fusion device in Norway, generating 20 times more energy than required to activate it !

 

According to Scandinavian physicists, ‘cold fusion’ happens due to the formation of ultra-dense hydrogen/deuterium as described in the widely acclaimed work and theoretical understanding by Professor Sveinn Olafsson (Sindre’s Phd. supervisor in Iceland) and Norway’s Professor Leif Holmlid.

 

Finally a proven testable theory for cold fusion that occurs in microscopic “stars” inside ordinary metals!

 

[ many photos and details in a very enthusiastic, lively, multi-faceted article... ]

photos, excellent brief summary, lists many key papers... ]

 

 

 2016 April 04    Holmlid and Olafsson  on Rydberg Fusion

 long, detailed color slide show on research since 2011

 

[ slide show also available via:

 

 

Tags:

“cold fusion”, muons, olafsson, homlid, rydberg fusion, rydberg matter, slides, stanford

 

Professor Sveinn Olafsson of Iceland has shared this presentation of his and Professor Leif Homlid’s work with Rydberg hydrogen and ‘cold fusion’

 

Get your Geek On if you like physics outside of the box…

 

Cold fusion now has a proven testable mainstream theory explaining why it occurs and has occurred as originally announced in March 1989…

 

The skeptics, nare-do-wells, and dogmatics are revealed as fools or worse!

Welcome to the end of the fossil fuel age.

These slides are from a talk delivered at Stanford, spring 2016, walk through the Rydberg fusion experiments and data.

 

This work offers both a demonstrably tested and proven theory for cold fusion as well as detailed description of the work and how it relates to other cold fusion studies going back to the March 1989 announcement of Fleischmann and Pons in Utah.

 

One startling discovery in this work is the observation of the emission of muons !

The key condition that enables this ‘cold fusion’ to occur is the development of ultra-dense Rydberg hydrogen that forms on command within microscopic domains inside of metals.

 

This ultra-dense hydrogen/deuterium is said to be at a density 1000 times that found in the center of our Sun, perhaps attaining the density of a neutron star, quark soup !

 

With the nuclei squashed so closely together, fusion readily takes place and can be stimulated to become prolific by being simply illuminated with an ordinary green laser.

This cold fusion occurs at a temperature that is very cold compared to that of normal hot fusion and in a very unexpected neutron free form.

 

For those of us who were friends of the late great and much maligned Martin Fleischmann, we can remember well his speaking all those years ago of hydrogen density in his experiment far in excess of that of metallic hydrogen and indeed of the role of ‘deep Dirac levels’ and Poynting vector mysteries !

 

All, elements of a new age of science from outside the box.

Imagine how much better the world would be today if the mis- and dis-information campaign against cold fusion had not been so successfully waged for the past quarter of a century !

 

Vastly reduced fossil fuel emissions would have put climate change under control and infinite low cost energy would have allowed trillions to be spent on the betterment of mankind, to say nothing of the elimination of 25 years of ‘oil wars’ and the millions of people violently killed.

 

Read more about the new age of cold fusion by linking here…  or scroll down for the geeky bits !

Welcome to the end of the fossil fuel age and the beginning of the age of cold fusion !

 

You might catch a session at the April 2016 APS meeting in Salt Lake City on this topic.

 

APS April Meeting 2016

Saturday–Tuesday, April 16–19, 2016; Salt Lake City, Utah

Session E11: Energy Research and Applications

3:30 PM–5:18 PM, Saturday, April 16, 2016

Room: 250C

 

Abstract: E11.00009 : Rydberg phases of Hydrogen and low energy nuclear reactions

5:06 PM–5:18 PM

 

Authors:

Sveinn Olafsson

(Faculty of Physical Sciences, University of Iceland, Reykjavik, Iceland)

 

Leif Holmlid

(Atmospheric Science, Department of Chemistry and Molecular Biology, University of Gothenburg, SE-412 96 Goteborg, Sweden)

 

For over the last 26 years the science of cold fusion/LENR has been researched around the world with slow pace of progress.

Modest quantity of excess heat and signatures of nuclear transmutation and helium production have been confirmed in experiments and theoretical work has only resulted in a large flora of inadequate theoretical scenarios.

Here we review current state of research in Rydberg matter of Hydrogen that is showing strong signature of nuclear processes.

 

In the presentation, experimental behavior of Rydberg matter of hydrogen is described.

An extensive collaboration effort of surface physics, catalysis, atomic physics, solid state physics, nuclear physics and quantum information is needed to tackle the surprising experimental results that have so far been obtained.

 

Rydberg matter of Hydrogen is the only known state of matter that is able to bring huge collections of protons to so short distances and for so long time, that tunneling becomes a reasonable process for making low energy nuclear reactions.

 

Nuclear quantum entanglement can also become realistic processes at these conditions.

 

 

by L Holmlid — ‎2013  25-page report

MeV/u from laser-induced fusion in ultra-dense deuterium.

Leif Holmlid. Department of Chemistry and Molecular Biology, University of Gothenburg, SE-412 96.

 

 

Replicable cold fusion experiment: heat/helium ratio, Abd ul-Rahman Lomax, Current Science 104(4) 574-7, 2015.02.25 free pdfs of 34 papers: Rich Murray 2015.02.24

http://rmforall.blogspot.com/2015/02/replicable-cold-fusion-experiment.html

 

Abd ul-Rahman Lomax abd@lomaxdesign.com [newvortex] 

4:59 PM (5 hours ago) Tuesday. 2015.02.24

 

to newvortex

 

The entire journal:

http://www.currentscience.ac.in/php/toc.php?vol=108&issue=04

 

The special section alone, 34 papers:

 

http://www.currentscience.ac.in/php/feat.php?feature=Special%20Section:%20Low%20Energy%20Nuclear%20Reactions&featid=10094

 

And, of course, my paper: “Replicable cold fusion experiment:

heat/helium ratio”

http://www.currentscience.ac.in/Volumes/108/04/0574.pdf

 

All the papers in that section may be discussed on Wikversity:

https://en.wikiversity.org/wiki/Cold_fusion/Current_Science

 

https://en.wikipedia.org/wiki/Current_Science

 

Some general information about this.

Current Science is a multidisciplinary journal established in 1932, published by the Current Science Association in collaboration with the

Indian Academy of Sciences.

 

Last year, the editors of the section solicited papers from researchers in the field of LENR. These papers went through two reviews, first by the special section editors and then, if the editors decided to forward the paper, by a normal peer reviewer assigned by Current Science.

 

The anonymous reviewer of my paper was familiar with physics and not with cold fusion, and was skeptical at first. Yes, I modified my paper extensively in response to his critique and it is, no doubt, better for it. Apparently, he was convinced, he gave a glowing recommendation for publication.

There are some very good papers in this collection, and others that are brief reports on activity in various nations or organizations.

I specially recommend McKubre’s paper, “Cold fusion: comments on the state of scientific proof”

 

http://www.currentscience.ac.in/Volumes/108/04/0495.pdf

 

But there are *many* excellent papers.

 

One might notice that we are not being shy about using the term “cold fusion.”  Times change.

It’s fusion, get over it.

(“Fusion” is a result, not a mechanism. The mechanism is a mystery.)

 

Posted by: Abd ul-Rahman Lomax 

“As a matter of course, every soul citizen of Earth has a priority to quickly find and positively share evidence for healthy and safe food, drink, environment, and society.”


 

within the fellowship of service,


by Rich Murray

Alive and kicking

Posted Tuesday, May 5th, 2015

foto di gruppo

Posted Sunday, April 19th, 2015

Il contatore Geiger : usb_descriptors.c

Posted Sunday, April 19th, 2015

/********************************************************************
FileName:         usb_descriptors.c
Dependencies:    See INCLUDES section
Processor:        PIC18 or PIC24 USB Microcontrollers
Hardware:        The code is natively intended to be used on the following
hardware platforms: PICDEM™ FS USB Demo Board,
PIC18F87J50 FS USB Plug-In Module, or
Explorer 16 + PIC24 USB PIM.  The firmware may be
modified for use on other USB platforms by editing the
HardwareProfile.h file.
Complier:      Microchip C18 (for PIC18) or C30 (for PIC24)
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.

*********************************************************************
-usb_descriptors.c-
——————————————————————-
Filling in the descriptor values in the usb_descriptors.c file:
——————————————————————-

[Device Descriptors]
The device descriptor is defined as a USB_DEVICE_DESCRIPTOR type.
This type is defined in usb_ch9.h  Each entry into this structure
needs to be the correct length for the data type of the entry.

[Configuration Descriptors]
The configuration descriptor was changed in v2.x from a structure
to a BYTE array.  Given that the configuration is now a byte array
each byte of multi-byte fields must be listed individually.  This
means that for fields like the total size of the configuration where
the field is a 16-bit value “64,0,” is the correct entry for a
configuration that is only 64 bytes long and not “64,” which is one
too few bytes.

The configuration attribute must always have the _DEFAULT
definition at the minimum. Additional options can be ORed
to the _DEFAULT attribute. Available options are _SELF and _RWU.
These definitions are defined in the usb_device.h file. The
_SELF tells the USB host that this device is self-powered. The
_RWU tells the USB host that this device supports Remote Wakeup.

[Endpoint Descriptors]
Like the configuration descriptor, the endpoint descriptors were
changed in v2.x of the stack from a structure to a BYTE array.  As
endpoint descriptors also has a field that are multi-byte entities,
please be sure to specify both bytes of the field.  For example, for
the endpoint size an endpoint that is 64 bytes needs to have the size
defined as “64,0,” instead of “64,”

Take the following example:
// Endpoint Descriptor //
0×07,                       //the size of this descriptor //
USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
_EP02_IN,                   //EndpointAddress
_INT,                       //Attributes
0×08,0×00,                  //size (note: 2 bytes)
0×02,                       //Interval

The first two parameters are self-explanatory. They specify the
length of this endpoint descriptor (7) and the descriptor type.
The next parameter identifies the endpoint, the definitions are
defined in usb_device.h and has the following naming
convention:
_EP<##>_<dir>
where ## is the endpoint number and dir is the direction of
transfer. The dir has the value of either ‘OUT’ or ‘IN’.
The next parameter identifies the type of the endpoint. Available
options are _BULK, _INT, _ISO, and _CTRL. The _CTRL is not
typically used because the default control transfer endpoint is
not defined in the USB descriptors. When _ISO option is used,
addition options can be ORed to _ISO. Example:
_ISO|_AD|_FE
This describes the endpoint as an isochronous pipe with adaptive
and feedback attributes. See usb_device.h and the USB
specification for details. The next parameter defines the size of
the endpoint. The last parameter in the polling interval.

——————————————————————-
Adding a USB String
——————————————————————-
A string descriptor array should have the following format:

rom struct{byte bLength;byte bDscType;word string[size];}sdxxx={
sizeof(sdxxx),DSC_STR,<text>};

The above structure provides a means for the C compiler to
calculate the length of string descriptor sdxxx, where xxx is the
index number. The first two bytes of the descriptor are descriptor
length and type. The rest <text> are string texts which must be
in the unicode format. The unicode format is achieved by declaring
each character as a word type. The whole text string is declared
as a word array with the number of characters equals to <size>.
<size> has to be manually counted and entered into the array
declaration. Let’s study this through an example:
if the string is “USB” , then the string descriptor should be:
(Using index 02)
rom struct{byte bLength;byte bDscType;word string[3];}sd002={
sizeof(sd002),DSC_STR,’U',’S',’B'};

A USB project may have multiple strings and the firmware supports
the management of multiple strings through a look-up table.
The look-up table is defined as:
rom const unsigned char *rom USB_SD_Ptr[]={&sd000,&sd001,&sd002};

The above declaration has 3 strings, sd000, sd001, and sd002.
Strings can be removed or added. sd000 is a specialized string
descriptor. It defines the language code, usually this is
US English (0×0409). The index of the string must match the index
position of the USB_SD_Ptr array, &sd000 must be in position
USB_SD_Ptr[0], &sd001 must be in position USB_SD_Ptr[1] and so on.
The look-up table USB_SD_Ptr is used by the get string handler
function.

——————————————————————-

The look-up table scheme also applies to the configuration
descriptor. A USB device may have multiple configuration
descriptors, i.e. CFG01, CFG02, etc. To add a configuration
descriptor, user must implement a structure similar to CFG01.
The next step is to add the configuration descriptor name, i.e.
cfg01, cfg02,.., to the look-up table USB_CD_Ptr. USB_CD_Ptr[0]
is a dummy place holder since configuration 0 is the un-configured
state according to the definition in the USB specification.

********************************************************************/

/*********************************************************************
* Descriptor specific type definitions are defined in:
* usb_device.h
*
* Configuration options are defined in:
* usb_config.h
********************************************************************/
#ifndef __USB_DESCRIPTORS_C
#define __USB_DESCRIPTORS_C

/** INCLUDES *******************************************************/
#include “usb.h”
#include “usb_function_msd.h”
#include “usb_function_hid.h”
#include “contatoregeiger.h”

/** CONSTANTS ******************************************************/

/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc={
0×12,    // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE,                // DEVICE descriptor type
0×0200,                 // USB Spec Release Number in BCD format
0×00,                   // Class Code
0×00,                   // Subclass code
0×00,                   // Protocol code
USB_EP0_BUFF_SIZE,          // Max packet size for EP0, see usb_config.h
0x115f,                 // Vendor ID: Cyberdyne/ADPM
0×0261,                 // Product ID: Geiger (mass storage + HID)
0×0001,                 // Device release number in BCD format
0×01,                   // Manufacturer string index
0×02,                   // Product string index
0×03,                   // Device serial number string index
0×01                    // Number of possible configurations
};

/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
9,    // Size of this descriptor in bytes
USB_DESCRIPTOR_CONFIGURATION,                // CONFIGURATION descriptor type
0×40,0×00,          // Total length of data for this cfg
2,                      // Number of interfaces in this cfg
1,                      // Index value of this configuration
0,                      // Configuration string index
_DEFAULT | _SELF,               // Attributes, see usb_device.h
50,                     // Max power consumption (2X mA)

/* Interface Descriptor */
9,   // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
MSD_INTF_ID,                      // Interface Number
0,                      // Alternate Setting Number
2,                      // Number of endpoints in this intf
MSD_INTF,               // Class code
MSD_INTF_SUBCLASS,      // Subclass code
MSD_PROTOCOL,             // Protocol code
0,                      // Interface string index

/* Endpoint Descriptor */
7,
USB_DESCRIPTOR_ENDPOINT,
_EP01_IN,_BULK,
MSD_IN_EP_SIZE,0×00,
0×01,

7,
USB_DESCRIPTOR_ENDPOINT,
_EP01_OUT,
_BULK,
MSD_OUT_EP_SIZE,0×00,
0×01,

/* Interface Descriptor */
0×09,//sizeof(USB_INTF_DSC),   // Size of this descriptor in bytes
USB_DESCRIPTOR_INTERFACE,               // INTERFACE descriptor type
HID_INTF_ID,                      // Interface Number
0,                      // Alternate Setting Number
2,                      // Number of endpoints in this intf
HID_INTF,               // Class code
0,     // Subclass code
0,     // Protocol code
0,                      // Interface string index

/* HID Class-Specific Descriptor */
0×09,//sizeof(USB_HID_DSC)+3,    // Size of this descriptor in bytes RRoj hack
DSC_HID,                // HID descriptor type
0×11,0×01,                 // HID Spec Release Number in BCD format (1.11)
0×00,                   // Country Code (0×00 for Not supported)
HID_NUM_OF_DSC,         // Number of class descriptors, see usbcfg.h
DSC_RPT,                // Report descriptor type
HID_RPT01_SIZE,0×00,//sizeof(hid_rpt01),      // Size of the report descriptor

/* Endpoint Descriptor */
0×07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
HID_EP | _EP_IN,                   //EndpointAddress
_INTERRUPT,                       //Attributes
0×40,0×00,                  //size
0×01,                        //Interval

/* Endpoint Descriptor */
0×07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT,    //Endpoint Descriptor
HID_EP | _EP_OUT,                   //EndpointAddress
_INTERRUPT,                       //Attributes
0×40,0×00,                  //size
0×01                        //Interval
};

//Class specific descriptor – HID
ROM struct{BYTE report[HID_RPT01_SIZE];} hid_rpt01={
{
0×06, 0×00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
0×09, 0×01,                    // USAGE (Vendor Usage 1)
0xa1, 0×01,                    // COLLECTION (Application)
// ——– common global items ———
0×15, 0×00,                    //   LOGICAL_MINIMUM (0)
0×26, 0xff, 0×00,              //   LOGICAL_MAXIMUM (255)
0×75, 0×08,                    //   REPORT_SIZE (8)
// ——– input report ———
0×85, 1, /*      Report ID (1)                                                */
0×95, HID_INT_IN_EP_SIZE-1,                    //   REPORT_COUNT (64)
0×19, 0×01,                    //   USAGE_MINIMUM (Vendor Usage 1)
0×29, HID_INT_IN_EP_SIZE,                    //   USAGE_MAXIMUM (Vendor Usage 64)
0×81, 0×02,                    //   INPUT (Data,Var,Abs)
// ——– output report ———
0×85, 2, /*      Report ID (2)                                                */
0×95, HID_INT_OUT_EP_SIZE-1,                    //   REPORT_COUNT (64)
0×19, 0×01,                    //   USAGE_MINIMUM (Vendor Usage 1)
0×29, HID_INT_OUT_EP_SIZE,                    //   USAGE_MAXIMUM (Vendor Usage 64)
0×91, 0×02,                    //   OUTPUT (Data,Var,Abs)
// ——– feature report ———
0×85, 3, /*      Report ID (3)                                                */
0×95, HID_FEATURE_REPORT_BYTES-1,                    //   REPORT_COUNT ()
0×09, 0×01,                    //   USAGE (Vendor Usage 1)
0xb1, 0×02,                    //   FEATURE (Data,Var,Abs)

0xc0                           // END_COLLECTION
}                   // End Collection
};

//Language code(s) supported string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[1];} sd000={
sizeof(sd000),
USB_DESCRIPTOR_STRING,
{0×0409}    //0×0409 = Language ID code for US English
};
//Manufacturer string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[10];} sd001={
sizeof(sd001),USB_DESCRIPTOR_STRING,
{‘C’,'y’,'b’,'e’,'r’,'d’,'y’,'n’,'e’
}};

//Product string descriptor
ROM struct{BYTE bLength;BYTE bDscType;WORD string[35];} sd002={
sizeof(sd002),USB_DESCRIPTOR_STRING,
//    {‘M’,'i’,'c’,'r’,'o’,'c’,'h’,'i’,'p’,’ ‘,’M',’a',’s',’s',’ ‘,’S',’t',’o',’r',’a',’g',’e',’ ‘,’D',’r',’i',’v',’e’
{‘C’,'y’,'b’,'e’,'r’,'d’,'y’,'n’,'e’,’ ‘,’G',’e',’i',’g',’e',’r',’+',’M',’a',’s',’s',’ ‘,’S',’t',’o',’r',’a',’g',’e',’ ‘,’D',’r',’i',’v',’e’
}};

//Serial number string descriptor.  Note: This should be unique for each unit
//built on the assembly line.  Plugging in two units simultaneously with the
//same serial number into a single machine can cause problems.  Additionally, not
//all hosts support all character values in the serial number string.  The MSD
//Bulk Only Transport (BOT) specs v1.0 restrict the serial number to consist only
//of ASCII characters “0″ through “9″ and capital letters “A” through “F”.
ROM struct{BYTE bLength;BYTE bDscType;WORD string[12];} sd003={
sizeof(sd003),USB_DESCRIPTOR_STRING,
{’1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′,’0′,’8′,’8′}
};

ROM struct { BYTE bLength; BYTE bDscType; WORD string[5]; } sd004 = {
sizeof(sd004),USB_DESCRIPTOR_STRING,
{‘V’,VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′}};

ROM struct { BYTE bLength; BYTE bDscType; WORD string[12]; } sd005 = {
sizeof(sd005),USB_DESCRIPTOR_STRING,
{‘ ‘,’+',’ ‘,’+',’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘}};

//Array of configuration descriptors
ROM BYTE *ROM USB_CD_Ptr[]={
(ROM BYTE *ROM)&configDescriptor1
};

//Array of string descriptors
ROM BYTE *ROM USB_SD_Ptr[]={
(ROM BYTE *ROM)&sd000,
(ROM BYTE *ROM)&sd001,
(ROM BYTE *ROM)&sd002,
(ROM BYTE *ROM)&sd003,
(ROM BYTE *ROM)&sd004,
(ROM BYTE *ROM)&sd005
};

/** EOF usb_descriptors.c ***************************************************/

#endif

Il contatore Geiger : sw_i2c.c

Posted Sunday, April 19th, 2015

/* sw_i2c solite
per PIC24 senza odd pointer
*/

#include “GenericTypeDefs.h”
#include “Compiler.h”
#include “hardwareprofile.h”
#include “contatoregeiger.h”
#include <libpic30.h>
#include “swi2c.h”

BYTE I2CBuffer[16];

/**************************************************************
Start Bit Subroutine
this routine generates a start bit
(Low going data line while clock is high)
**************************************************************/
void I2CSTART(void) {

//    SWStartI2C();
m_I2CClkBit=0;                    // make sure clock is low
m_I2CDataBit=1;                    // make sure data is high
I2CDataTris=0;                    // set data and clock lines for output
I2CDelay();
setClockHigh();                    // CLK=1
I2CDelay();
m_I2CDataBit=0;                    // data line goes low during high clock for start bit
I2CDelay();
m_I2CClkBit=0;                    // start clock train
I2CDelay();
}

/************************************************************
Stop Bit Subroutine
This routine generates a stop bit
(High going data line while clock is high)
************************************************************/
void I2CSTOP(void) {

//    SWStopI2C();
m_I2CDataBit=0;                        // make sure data line is low
m_I2CClkBit=0;                        // make sure clock is low
I2CDataTris=0;                        // set data/clock lines as outputs
m_I2CClkBit=1;                        // set clock high
I2CDelay();
m_I2CDataBit=1;                        // data goes high while clock high for stop bit
I2CDelay();
m_I2CClkBit=0;                        // set clock low again
I2CDelay();
I2CDataTris=1;                        // set data line as input
//    m_I2CClkBit=1;                        // set clock idle

setClockHigh();                        // CLK=1
// questa e’ un’altra attesa, per i dispos. (tipo PICBELL, PICWDI2C) che il WAIT lo fanno DOPO lo STOP!

//    m_I2CClkBit=0;
I2CDelay();

}

/*************************************************************
BITOUT routine takes the bit of data in C and
transmits it to the serial EE device
*************************************************************/
void I2CBITOUT(BYTE n) {

I2CDataTris=0;                    // set data,clock as outputs
if(n)                                        // check for state of data bit to xmit
m_I2CDataBit=1;                    // output a low bit
else
m_I2CDataBit=0;                    // high? set data line high
Nop();                                        // dev’esserci un min. ritardo tra il cambio in DATA e la salita di CLK
Nop();
m_I2CClkBit=1;                            // set clock line high
I2CDelay();
m_I2CClkBit=0;                            // return clock line low
I2CDelay();
//    retlw   0
}

/**************************************************************
BITIN routine reads one bit of data from the
serial EE device and stores it in C
**************************************************************/
BYTE I2CBITIN(void) {
/*overlay*/ BYTE i;

I2CDataTris=1;                        // make sdata an input line
I2CDelay();
m_I2CClkBit=1;                            // set clock line high
I2CDelay();                    // just sit here a sec
i = m_I2CDataBitI ? 1 : 0;          // read the data bit
m_I2CClkBit=0;                        // set clock line low
return i;
}

void setClockHigh(void) {
// Gestisce WAIT_STATE dello slave (CLK basso)… che puo’ succedere SEMPRE!

m_I2CClkBit=1;

I2CClkTris=1;                        // CLK e’ input

I2CDelay();

do {
ClrWdt();
} while(!m_I2CClkBitI);

I2CClkTris=0;                // CLK e’ output

}

/****************************************************************
Transmit Data Subroutine
This routine takes the BYTE of data stored in the
‘temp’ register and transmits it to the serial EE device.
It will then send 1 more clock to the serial EE for the
acknowledge bit.  If the ack bit from the part was low
then the transmission was sucessful.  If it is high, then
the device did not send a proper ack bit and the ack
fail LED will be turned on.
****************************************************************/
#define I2CTXSlaveAddrW() I2CTXByte(0xA0)
#define I2CTXSlaveAddrR() I2CTXByte(0xA1)

BYTE I2CTXByte(BYTE n) {
BYTE I2CData,I2CCnt;

I2CData=n;

for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8
I2CBITOUT(I2CData & 0×80);              // send the bit to serial EE
I2CData <<= 1;                                            // rotate I2CData/txbuf left, bit in CARRY
}                                                                        // 8 bits done?
// no – go again

// read ack bit
I2CDataTris=1;
I2CDelay();
setClockHigh();                    // aspetto ACK
//        Per WAIT_STATE dello slave (CLK basso)… NON e’ chiaro se PRIMA o DOPO ACK… (PicBell lo fa dopo!)
//            questo lo controlla SEMPRE!
I2CDelay();

// dopo Delay, qua arrivo con W=0 e Z=1
I2CCnt=m_I2CDataBitI;                        // Z=1 se ACK=OK (basso), altrimenti Z=0 e W!=0

m_I2CClkBit=0;

if(I2CCnt) {                        // check ack bit
//        m_MemCardLedBit=1;                // spegne! set acknowledge fail LED if the device did not pull data low
return 0;                                // 0=ERR
}
return 1;                                // 1=OK
}

/****************************************************************
Receive data routine
This routine reads one BYTE of data from the part
into the ‘I2CData’ register.
****************************************************************/
BYTE I2CRXByte(void) {
BYTE I2CData,I2CCnt;

//    SWReadI2C();

//    I2CData=0;                            // clear input buffer  non serve!

for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8
I2CData <<= 1;                // rotate I2CData 1 bit left
I2CData |= I2CBITIN();                            // read a bit
//        STATUSbits.C = 1;            // la presenza di ASM disabilita l’ottimizzazione, quindi PEGGIORA!
//        Rlcf(input);            // Rotate the carry into the data BYTE
}                                           // 8 bits done?
// no, do another

return I2CData;
}

/****************************************************************
Receive data routine
This routine reads one BYTE of data from the part
into the ‘I2CData’ register.  It then sends a high
ACK bit to indicate that no more data is to be read
****************************************************************/
BYTE I2CRX1Byte(void) {
BYTE I2CData,I2CCnt;

//    I2CData=0;                            // clear input buffer  non serve!

for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8
//        STATUSbits.C = 1;            // la presenza di ASM disabilita l’ottimizzazione, quindi PEGGIORA!
//        Rlcf(input);            // Rotate the carry into the data BYTE
I2CData <<= 1;               // rotate I2CData 1 bit left
I2CData |= I2CBITIN();                        // read a bit
}                                      // 8 bits done?
// no, do another
// set ack bit = 1
I2CBITOUT(1);                        // to finish transmission

return I2CData;
}

/**************************************************************
READ (read routine)
This routine reads 8 consecutive addresses of the
serial EE device starting at address 00 in the
random access mode (non-sequential read). Reading
the device using the random access mode
requires that the address pointer be set for every
BYTE before the read takes place. The address pointer
is set by sending a ‘write mode’ control BYTE with the
address of the location to read.
***************************************************************/
BYTE I2CReadRandom(BYTE n) {
BYTE I2CData;

//    bcf     port_a,ackf        ; clear the ack fail LED if on

I2CSTART();                        // generate start bit
//
// now send the write control BYTE and
// address to set the pointer
//
I2CTXSlaveAddrW();        // get slave address and write mode
//    movfw   I2CAddr                ; get WORD address
I2CTXByte(n);        // and send it

// now read one BYTE from the part

I2CSTART();                            // generate start bit
I2CTXSlaveAddrR();            // get slave address and read mode
I2CData=I2CRX1Byte();        // read 1 BYTE from serial EE
I2CSTOP();                            // send stop bit to end transmission

return I2CData;
}

BYTE I2CReadRandom16(WORD n) {
BYTE I2CData;

//    bcf     port_a,ackf        ; clear the ack fail LED if on

I2CSTART();                        // generate start bit
//
// now send the write control BYTE and
// address to set the pointer
//
I2CTXSlaveAddrW();        // get slave address and write mode
//    move WORD address (HIGH)
I2CTXByte(HIBYTE(n));                        // and send it
// move WORD address (LOW)
I2CTXByte(LOBYTE(n));                        // and send it

// now read one BYTE from the part

I2CSTART();                            // generate start bit
I2CTXSlaveAddrR();            // get slave address and read mode
I2CData=I2CRX1Byte();        // read 1 BYTE from serial EE
I2CSTOP();                            // send stop bit to end transmission

return I2CData;
}

/**************************************************************
READ (sequential read routine)

This routine reads 8 consecutive addresses of the
serial EE device starting at address 00 in the
sequential read mode. Reading in this mode is more
efficient than the random read mode as the control BYTE
and address have to be sent only once at the beginning
of the sequence.  As many consecutive addresses as
needed can then be read from the part until a stop bit is
sent.  In the read mode, the PIC 16C54 must send the acknowledge
bit after every 8 data bits from the device.  When the
last BYTE needed has been read, then the controller will
send a high acknowledge bit and then a stop bit to halt
transmission from the device.
***************************************************************/
BYTE I2CRead8Seq(BYTE n,BYTE I2CCntB) {            // entra W=indirizzo part. lettura, FSR punta al buffer
BYTE *p;

//    bcf     port_a,ackf        ; clear the ack fail LED if on
p=I2CBuffer;                        // bank1, ISP=0!

I2CSTART();                        // generate start bit
I2CTXSlaveAddrW();        // send slave address and write mode
// get WORD address
I2CTXByte(n);            // and send it
I2CSTART();                        // generate start bit
I2CTXSlaveAddrR();        // send slave address and read mode

I2CRead8Seq2:
*p++=I2CRXByte();                // read 1 BYTE from device
if(!–I2CCntB) {                // are all 8 BYTEs read?
// no, send low ack and do another
// yes, send high ack bit
I2CBITOUT(1);                    // to stop tranxmission
I2CSTOP();                        // and send a stop bit
return 8;
}

//  send low ack bit
I2CBITOUT(0);                // to continue transmission
goto I2CRead8Seq2;        //and read another BYTE
}

/**************************************************************
READ16 (sequential read routine)

This routine reads 8 consecutive addresses of the
serial EE device starting at given 16bit address in the
sequential read mode. Reading in this mode is more
efficient than the random read mode as the control BYTE
and address have to be sent only once at the beginning
of the sequence.  As many consecutive addresses as
needed can then be read from the part until a stop bit is
sent.  In the read mode, the PIC 16C54 must send the acknowledge
bit after every 8 data bits from the device.  When the
last BYTE needed has been read, then the controller will
send a high acknowledge bit and then a stop bit to halt
transmission from the device.
***************************************************************/
BYTE I2CRead16Seq(WORD n,BYTE I2CCntB) {            // entra indirizzo part. lettura, FSR punta al buffer
BYTE *p;

//    bcf     port_a,ackf        ; clear the ack fail LED if on

I2CSTART();                        // generate start bit
I2CTXSlaveAddrW();        // send slave address and write mode

//    move WORD address (HIGH)
I2CTXByte(HIBYTE(n));                        // and send it
// move WORD address (LOW)
I2CTXByte(LOBYTE(n));                        // and send it

I2CSTART();                            // generate start bit
I2CTXSlaveAddrR();            // send slave address and read mode

p=I2CBuffer;

I2CRead16Seq2:
*p++=I2CRXByte();                // read 1 BYTE from device
if(!–I2CCntB) {                    // are all n BYTEs read?
// no, send low ack and do another
// yes, send high ack bit
I2CBITOUT(1);                    // to stop tranxmission
I2CSTOP();                        // and send a stop bit
return 16;
}

// send low ack bit
I2CBITOUT(0);              // to continue transmission
goto I2CRead16Seq2;        // and read another BYTE
}

/****************************************************************
Byte Write Routine
This routine writes the data in “temp” to
8 consecutive BYTEs in the serial EE device starting
at address 00.  This routine waits 10mS after every
BYTE to give the device time to do the write.  This
program repeats forever.
*****************************************************************/
void I2CWriteByte(BYTE n, BYTE b) {
BYTE I2CAddr,I2CCnt;

//    SWWriteI2C();

//    clrf    port_a                ; clear all LEDs
I2CAddr=n;                        // set starting address to W
//    temp=0×55;                        // set data to write as 55h

// set number of BYTEs
for(I2CCnt=0; I2CCnt<8; I2CCnt++) {        // set the #bits to 8

I2CSTART();                        // generate start bit
I2CTXSlaveAddrW();        // send slave address and write mode
// move WORD address
I2CTXByte(I2CAddr);        // and send it
I2CTXByte(b);                    // move data BYTE and transmit it
I2CSTOP();                        // generate stop bit

//    movlw   10
//    movwf   loops                    ; set delay time to give
//    call    WAIT                    ; 10 ms wait after every BYTE
I2CWritePagePoll();

I2CAddr++;                        // add 1 to address counter
}                                            // all 8 BYTEs written?
// no, do another BYTE
}

/****************************************************************
Page Write Routine

This routine uses page mode to write the data in “temp” to
8 consecutive BYTEs in the serial EE device starting
at address 00. This routine waits 10mS after every
page to give the device time to do the write.  This
routine executes forever
*****************************************************************/

void I2CWritePage(BYTE n,BYTE I2CCntB) {                    // entra W=indirizzo part. lettura, (FSR usato per buffer)
BYTE *p;

//    clrf    port_a                    ; clear all LEDs
p=I2CBuffer;

I2CSTART();                            // generate start bit
I2CTXSlaveAddrW();            // send slave address and write mode

// move WORD address
I2CTXByte(n);                        // and send it

do {
I2CTXByte(*p++);                        // and transmit it
} while(–I2CCntB);                        // all n BYTEs written?
// no, do another
I2CSTOP();                            // yes,generate stop bit

//    movlw   10
//    movwf   loops                        ; set delay time to give
//    call    WAIT                        ; 10 ms wait after every BYTE
Delay_mS(20);                            // 50mS
}

/****************************************************************
Page Write 16 Routine (8 BYTEs, address a 16 bit)

This routine uses page mode to write the data in “temp” to
8 consecutive BYTEs in the serial EE device starting
at given address . This routine waits 10mS after every
page to give the device time to do the write.  This
routine executes forever
*****************************************************************/
#define I2CWritePage16Default() I2CWritePage16((WORD)&I2CAddr)

BYTE I2CWritePage16(WORD n,BYTE I2CCntB) {        // entra W=puntat. all’indirizzo part. lettura, (FSR usato per buffer)
BYTE *p;

// clrf    port_a                    ; clear all LEDs

I2CSTART();                            // generate start bit
I2CTXSlaveAddrW();            // send slave address and write mode

//    move WORD address (HIGH)
I2CTXByte(HIBYTE(n));                        // and send it
// move WORD address (LOW)
I2CTXByte(LOBYTE(n));                        // and send it

p=I2CBuffer;

do {
I2CTXByte(*p++);                // and transmit it
} while(–I2CCntB);                    // move data BYTE
// all n BYTEs written?
// no, do another
I2CSTOP();                            // yes,generate stop bit

//    movlw   10
//    movwf   loops                        ; set delay time to give
//    call    WAIT                        ; 10 ms wait after every BYTE
Delay_mS(20);                            // 20mS
return 16;
}

BYTE I2CWritePagePoll(void) {
BYTE I2Cpollcnt,i;

I2Cpollcnt=100;                        // set max number of times to poll as 100
do {
I2CSTART();                                // generate start bit
i=I2CTXSlaveAddrW();                // send slave address and write mode
if(i)                                        // was the ack bit low?
goto exitpoll;                // yes, do another BYTE
} while(–I2Cpollcnt);         // is poll counter down to zero?
// no, poll again.  Otherwise the part is
//    bsf     port_a,timeout    ; not responding in time so set timeout LED and continue on

exitpoll:
;
}

void I2CDelay(void) {            // circa 2,5uSec (400KHz operation)
BYTE uSec;            // 1.25 ca.

uSec=1;
do {
ClrWdt();                            // Clear the WDT
__delay_us(1);            // circa
} while(–uSec);
}

Il contatore Geiger : lcd_text.c

Posted Sunday, April 19th, 2015

/* LCD.c
x LCD basati su HD44870

*/

#include “GenericTypeDefs.h”
#include “Compiler.h”
#include “hardwareprofile.h”        //
#include “contatoregeiger.h”
#include <stdlib.h>
#include <timer.h>
#include <ctype.h>
#include <libpic30.h>
#include “lcd.h”

#define LCD_MAX_COLS 16
#define LCD_MAX_ROWS 2

void subLCDInit(void);

void subLCDget(void);

void SetBeep(void);

#pragma udata

BYTE LCDCols;
BYTE LCDRows;
BYTE LCDX;
BYTE LCDY;
BYTE LuceLCD;                    // mirrored in EEPROM
BYTE ContrLCD;
BYTE StatoLCD;                    // usato per indicare se il cursore è attivo (b0);
BYTE BeepFreq;
BYTE TimerBuzz;

BYTE FLAGS_ESC;                    // per sequenze ESCAPE: 0=SetLuce, 1=SetContr, 2=SetFreq; 3=SetLed; 4&5=SetXY (1&2); 6=SetKClick; 7=invert_bitmap
BYTE FLAGS;

extern WORD I2CAddr;
BYTE I2CData;
BYTE I2CCnt;
BYTE I2CCntB;

BYTE lcd_temp0;            // usato dentro LCDOutCmd da 6963, in GetCharDef da KS0108
BYTE lcd_temp1;            // temporanea, usata da LCD
BYTE lcd_temp2;
BYTE lcd_temp3;
BYTE LCDtmpBuf[40];                    // temp per scroll display (almeno 40 BYTE), BANCO 1

//BYTE *iconptr;                        //    temp. per icone/bigchar LCD
WORD iconptr;                        //    temp. per icone/bigchar LCD

#define LCD_DELAY { Nop();     Nop();     Nop();    ClrWdt(); Nop();     Nop();     Nop();    Nop();     Nop();     Nop();    Nop();     Nop();     Nop();    Nop();     Nop();     Nop();    }
//#define LCD_DELAY Delay_uS(1);

// ———————————————————————

//lang_1:                // italiano (in caso si volessero + lingue…)

const char CopyrDate[32] = {“12/03/12 – S/N 0001n” };
//    messg “Numero di serie: SERNUM”

static const char Copyright[32] = { ‘P’,'I’,'C’,'B’,'e’,'l’,'l’,’ ‘,’f',’w',’ ‘,’v',VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′,0 };
//    dt    ”ADPM Synthesis – Terminale grafico USB ”
//    dt  VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′, ‘ ‘
//    dt “08/04/05″,0
const char *CopyrString=Copyright;
static const char *Copyr1= { “(C) Cyberdyne 2009-2012; ADPM Synthesis 1999-2008 – G.Darn” };

const char String1_l1[32] = { “Cyberdyne” /*”ADPM Synthesis”*/  /*    ” K-tronic sas” */ };
const char String2_l1[] = {    ’ ‘,’P',’I',’C',’B',’e',’l',’l',’ ‘,’v',VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′,’ ‘,0 };
//static const char String2_l1[] = {    ’S',’k',’y',’N',’E',’T',’ ‘,’v',VERNUMH+’0′,’.',VERNUML/10+’0′,(VERNUML % 10)+’0′,’ ‘,0 };
const char String3_l1[2] =
{ ‘_’,0    };            // icona splash-screen ?

const BYTE LUTLuce[16]= { 0,1,2,3, 4,5,7,8, 10,12,14,18, 20,24,28,32 };

void aggLuceContrasto(void) {
WORD w;

//    PR2=BeepFreq;
w = LUTLuce[LuceLCD & 0xf];
w *= 1000;        // quasi-100%, tanto per
// …moltiplico per Luce (ossia il DutyCycle voluto)…
// divido per 32 (v. tab luce)…
//    SetDCOC1PWM(w /* /32 */,BeepFreq);            // FINIRE
// …il risultato nel timer

OC4R=w;
//    SetDCOC2PWM(ContrLCD * 4,BeepFreq);            // FINIRE

}

// ———————————————————————

void print_init(void) {

LCDCls();
LCDX= (LCD_MAX_COLS-14)/2;                // “skynet/picbell vx.xx”: 16 char
LCDXY(0);                        // X,Y=[2,1]

#if LCD_MAX_ROWS>1
LCDWrite(String2_l1);
LCDX=(LCD_MAX_COLS-10)/2;                // “cyberdyne”: 10 char

LCDXY(1);                        // X,Y=[3,2]

LCDWrite(String1_l1);

if(!sw1) {
LCDPrintLF();
#if LCD_MAX_ROWS>2
LCDPrintHex(LuceLCD);
LCDPrintHex(ContrLCD);
LCDPrintLF();
#else
LCDPrintHex(LuceLCD);
#endif
return;
}

//    LCDWrite(String3_l1);
#else
LCDWrite(String2_l1);
#endif

}

// ———————————————————————
void LCDPutChar(BYTE ch) {
static BYTE parm1,parm2,nparms;

if(FLAGS & (1 << IN_ESCAPE_CHAR)) {

if(FLAGS_ESC & 1) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
EEscrivi_(&LuceLCD,ch-1);                    // 1..16
aggLuceContrasto();
return;
}

if(FLAGS_ESC & 2) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
EEscrivi_(&ContrLCD,ch-1);                    // 1..16
aggLuceContrasto();
return;
}
if(FLAGS_ESC & 4) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
// minimo 32 (v. PWM luce) (circa 10KHz per buzzer)
BeepFreq= ch < 32 ? 32 : ch;
aggLuceContrasto();
return;
}
if(FLAGS_ESC & 8) {
FLAGS_ESC=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
//            LATE = ch & 0xf;        // OCCHIO!
return;
}
if(FLAGS_ESC & 0×10) {
// http://ascii-table.com/ansi-escape-sequences-vt-100.php
if(isdigit(ch)) {        // set xy ESC [ x;y f/H
if(!nparms)
parm1=ch;            //NO! usare atoi... su + char...
if(nparms==1)
parm2=ch;            //NO! usare atoi... su + char...
nparms++;
}
else {
if(ch=='m') {
//                    if(nparms)
//                        bigFont=parm1 & 1;
}
if(ch=='f' || ch=='H') {
if(nparms>1) {
LCDY = parm1;
LCDX = parm2;
LCDXY_();
}
}
if(ch=='j') {
if(nparms && parm1=='2' /*sistemare!*/)
LCDCls();
}
FLAGS_ESC=0;
nparms=0;
FLAGS &= ~(1 << IN_ESCAPE_CHAR);
}

return;
}
if(FLAGS_ESC & 0x20) {
if(ch & 1)
FLAGS &= ~(1 << NOKCLICK);
else
FLAGS |= (1 << NOKCLICK);
return;
}

switch(ch) {
case 17:                        // v. sopra
FLAGS_ESC |= 1;
break;
case 18:                        // un po' a caso...
FLAGS_ESC |= 2;
break;
case 7:                        // come "BEL"
FLAGS_ESC |= 4;
break;
case 19:                        // v. sopra
FLAGS_ESC |= 8;
break;
case 91:                        // vagamente ANSI... (VT100 dice: "ESC [ ROW ; COLUMN f" , e simili...
FLAGS_ESC |= 0x10;
nparms=0;
break;
}

if(!FLAGS_ESC)        // se non e' stato trovato nessun char. accettabile, tolgo QUI ESC!
FLAGS &= ~(1 << IN_ESCAPE_CHAR);

return;
}

if(ch >= ' ') {

if(ch & 0x80)            // i caratteri >=0x80 sono usati per i char user-defined...
ch &= 0x7f;            // ...banalmente, se solo testo, li riporto al valore in LCD

LCDOutData(ch);

LCDX++;
if(LCDX >= LCDCols)
goto LCDPrintLF;
/*
if(LCDRows == 1) {
if(LCDX == 8)
LCDXY_();
}        per 1-riga, v. anche LCDXY e frequanzimetro
*/
}

else {

switch(ch) {
case 2:
StatoLCD |= 1;
LCDCursor(3);                // STX=cursor On
break;

case 3:
StatoLCD &= 0xfe;        // ETX=cursor Off
LCDCursor(0);
break;

case 7:
//  call StdBeep                        ; resa ASINCRONA (per velocita' I2C e anche SER)!
SetBeep();
break;

case 9:
LCDtab:
LCDX++;

LCDOutBlankRaw();        // meglio non LCDPutBlank, per lo stack!
// così però non gestisce l'a-capo...

if(LCDX & 7)
goto LCDtab;
break;

case 11:
LCDScrollDown();
break;

case 12:                    // FF = scroll up
LCDScrollUp();
break;

case 10:                // LF
LCDPrintLF:
LCDX=0;
LCDY++;
// METTERE un FLAG per disattivare scroll automatico (CHR$13) su ultima riga, per sfruttarla meglio??
LCDScroll();            // scroll SE necessario
break;

case 13:                // CR
LCDX=0;
LCDXY_();
break;

case 14:            // shift-in (cursor left)
LCDOutCmd(16);
break;
case 15:            // shift-out (cursor right)
LCDOutCmd(20);
break;

case 8:                    //; BS
if(LCDX) {                // solo se X>0...

LCDX--;

LCDOutCmd(16);
LCDOutBlankRaw();
LCDOutCmd(16);
}
break;

case 17:            // DC1..2 usati per Luce LCD
LuceLCD=15;
LCDPC_NoPrint_17_:
//            EEcopiaAEEPROM(&LuceLCD);
aggLuceContrasto();            // occhio allo stack...!
break;

case 18:
LuceLCD=0;
goto LCDPC_NoPrint_17_;
break;

case 19:                    // DC3..4 usati per Led on/off
mLED_1=1;
//            LED1_IO=1;
break;

case 20:
mLED_1=0;
break;

case 24:                    // CAN (opp. FormFeed ?) = CLS
LCDCls();
break;

case 27:                    // ESC (comandi ausiliari)
FLAGS |= (1 << IN_ESCAPE_CHAR);
break;

default:
// LCDPut1:            eliminato, eqv. a return
break;

}
}

}

// ---------------------------------------------------------------------

void LCDXY_(void) {
BYTE i,lcd_temp2;

lcd_temp2=0;

switch(LCDRows) {
case 1:
if(LCDRows == 1 && LCDX >= 8) {            // patch x 1 riga... (v. anche PutChar)
LCDOutCmd(0xc0 | (LCDX & 7));
return;
}
else {
LCDXY1:
i=LCDX & 0x7f;
i+=lcd_temp2;
LCDOutCmd(i | 0x80);
}

if(LCDX & 0x80) {
LCDX &= 0x7f;
LCDX-=LCDCols;
}

break;

case 2:
LCDXY2:
lcd_temp2=(LCDY & 1) * 0x40;
goto LCDXY1;
break;

case 4:
if(LCDCols < 40) {        // se e' 4x40 (M4024) va bene cosi' (hanno 2 ENABLE)...
if(LCDY >= 2) {            // ...altrimenti (4x20), se la riga e' 2 opp. 3...
LCDX+=LCDCols;        // ...aggiungo a X la larghezza (16 opp. 20)
LCDX |= 0x80;             //e me lo segno per poi ri-toglierla!
}
}
goto LCDXY2;
break;

default:                                // NON DEVE succedere!
break;

}
}

// ---------------------------------------------------------------------

void subLCDInit(void) {

LCDOutPort4Bit(0x3);          // init 1st        4 bit!
Delay_mS(5);                                // >4.1mS
LCDOutPort4Bit(0x3);         // init 2nd
Delay_mS(1);                                // >100uS
LCDOutPort4Bit(0x3);          // init 3rd
Delay_mS(1);                                // >39uS
LCDOutPort4Bit(0x2);          //
Delay_mS(1);                                //
LCDOutCmd(0b00101000);                  // function Set 0010NF**            4bit!
LCDOutCmd(0b00001100);      // display ON/OFF = 00001DCB, Display ON,Cursor&Blink OFF
// entry Mode Set = 000001IS, increment & shift off
LCDOutCmd(0b00000110);                 // cursore, blink e ON/OFF
}

const BYTE LCDUserDefChar[7][8]={
//    { 0b00000110,0b00001001,0b00011100,0b00001000,0b00011100,0b00001001,0b00000110,0b00000000    },        // EURO no qua
{ 0b00000000,0b00000000,0b00000001,0b00000011,0b00000111,0b00001111,0b00011111,0b00000000 }, //1=triang. dx (v. pag 77 rivista)
{ 0b00000100,0b00001110,0b00001110,0b00011111,0b00000000,0b00000000,0b00000000,0b00000000 }, //2=allarme
{ 0b00000000,0b00000000,0b00000011,0b00000111,0b00001111,0b00000111,0b00000011,0b00000000    }, //3=PC/232 conn.
{ 0b00000000,0b00000000,0b00011011,0b00010010,0b00011010,0b00001010,0b00011011,0b00000000    }, //4=SD card
{ 0b00000000,0b00000100,0b00001110,0b00001110,0b00001110,0b00001110,0b00001110,0b00000000 }, //5=batt. piena
{ 0b00000000,0b00000100,0b00001010,0b00001010,0b00001010,0b00001010,0b00001110,0b00000000 }, //6=batt. vuota
{ 0b00000000,0b00001010,0b00011011,0b00011111,0b00000100,0b00001110,0b00011111,0b00000000 }, //7=radioactive :)
//purtroppo ce ne sono solo 8!
};

void subLCDdefChar(void) {
BYTE x,y;

LCDOutCmd(0×48);            // definisco char user-def partendo da 1 (non 0!)
for(y=0; y<7; y++) {    // parametrizzare!!!
for(x=0; x<8; x++) {
LCDOutData(LCDUserDefChar[y][x]);
}
}

}

BYTE LCDInit(void) {

LCDY=0;
Delay_mS(15);                // 15mS
subLCDInit();

subLCDdefChar();

#if !defined(__PIC24FJ128GA106__) && !defined(__PIC24FJ256GA106__)
//    OpenOC1(OC_IDLE_CON & OC_TIMER4_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 & OC_SYNC_TRIG_IN_DISABLE,
//        0,0);
//    OpenOC2(OC_IDLE_CON & OC_TIMER4_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 & OC_SYNC_TRIG_IN_DISABLE,
//        0,0);
#else

// OCCHIO CHE SU GA questa sopra non funziona!
// sembra mappare erroneamente sulle funzioni “_GB” che poi non vanno. usare accesso ai registri diretti
#endif

/* Reset PWM */
OC4CON1 = 0×0000;
OC4CON2 = 0×0000;

/* set PWM duty cycle to 50% */
OC4R    = 16384 /* basato su SysClock => 500Hz (16MHz / 32768) */; //PWM_PERIOD >> 1; /* set the duty cycle tp 50% */
OC4RS   = 32768 /* se uso Timer come Src SEMBRA NON FARE NULLA… qua boh! */;  //PWM_PERIOD – 1;  /* set the period */

/* configure PWM */
OC4CON2 = 0x001f;   /* 0x001F = Sync with This OC module                               */
OC4CON1 = 0x1c00 /* 0×0400 => src=Timer3 */;  /* 0x1C08 = Clock source Fcyc, trigger mode 1, Mode 0 (disable OC1) */

/* enable the PWM */
OC4CON1 |= 0×0006;   /* Mode 6, Edge-aligned PWM Mode */

//v. anche PPS

LuceLCD=8;
ContrLCD=12;

LCDRows=LCD_MAX_ROWS;            // PARAMETRIZZARE (da FLASH?)
//            cp  3
//            jp m,LCDInit2

//            movlw 2
//            movwf LCDY
//            call subLCDInit

LCDCols=LCD_MAX_COLS;            // PARAMETRIZZARE (da FLASH?)

LCDCls();

return 1;
}
// CONTINUA

// ———————————————————————

void LCDCls(void) {

//    movfw LCDRows
//  cp  3
//            jp m,LCDCls1
//            ld  a,2
//            ld  (LCDY),a
//            dec a
//  call LCDOutPort

LCDX=0;
LCDY=0;
//    bcf  STATUS,C

LCDOutCmd(1);
// CONTINUA                        ; cls & home (comando 1)
}

// ———————————————————————

BYTE LCDOutPort(BYTE c, BYTE n) {                                                // scrivo W nel display
// dato se C=1, comando se C=0
BYTE t;

m_LCDRWBit=1;                                        // torno in lettura
m_LCDRSBit=0;                                        // preparo per leggere Flag
lcd_temp1=0;

LCD_DELAY;

#ifndef __DEBUG
while(1) {
//    clrwdt                                                                ; incorporato in LCD_DELAY
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

t=PORTB & 0×8;                                // esco se b7=0

m_LCDEnBit=0;
LCD_DELAY;

m_LCDEnBit=1;                                        // scrivo! cmq secondo nibble!
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

if(!t)                                            // esco se b7=0
break;

//    decf  lcd_temp1,f
//    bz  LCDDelay1_err
}
#endif

LCDDelay1_err:
LCDOut1:
m_LCDEnBit=0;                            // rimetto cmq a posto EN…

return LCDOutPortNoW(c,n);
}

BYTE LCDOutPortNoW(BYTE c,BYTE n) {                                    // qui per non aspettare BUSY!

if(c)
m_LCDRSBit=1;                                        // C=1, dato
else
m_LCDRSBit=0;                                        // C=0, comando
m_LCDRWBit=0;                                        // vado in scrittura
TRISB &= ~0b00001111;

LCD_DELAY;
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

LATB &= ~0b00001111;
LATB |= ((n >> 4) & 0x0f);                // nibble H, shift 4 a dx
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

LCD_DELAY;
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

LATB &= ~0b00001111;
LATB |= ((n & 0x0f) );                // nibble L, shift 0 a sx
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

TRISB |= 0b00001111;
m_LCDRWBit=1;                                        // torno in lettura

m_LCDRSBit=1;

return n;
}

BYTE LCDOutPort4Bit(BYTE n) {

m_LCDRSBit=0;                                        // C=0, comando
m_LCDRWBit=0;                                        // vado in scrittura
TRISB &= ~0b00001111;

LCD_DELAY;
m_LCDEnBit=1;                                        // scrivo!
LCD_DELAY;

LATB &= ~0b00001111;
LATB |= ((n & 0x0f) );                // nibble L, shift 0 a sx
LCD_DELAY;

m_LCDEnBit=0;
LCD_DELAY;

TRISB |= 0b00001111;
m_LCDRWBit=1;                                        // torno in lettura

return n;
}

void LCDOutBlankRaw(void) {
char c;

c=’ ‘;

LCDOutData(c);
}

// ———————————————————————
void LCDWrite(const char *p) {

while(*p)
LCDPutChar(*p++);
}

void LCDWriteN(const char *p, BYTE n) {

do {
LCDPutChar(*p++);
} while(–n);
}

// ———————————————————————

void subLCDget(void) {
BYTE *p;
BYTE i,lcd_temp1,t;

p=LCDtmpBuf;

for(i=0; i<LCDCols; i++) {

m_LCDRSBit=0;                                        // preparo per leggere Flag
m_LCDRWBit=1;                                        // vado in lettura
TRISB |= 0b00001111;

lcd_temp1=0;

while(1) {

m_LCDEnBit=1;                                        // strobe!
LCD_DELAY

t=PORTB & 0×8;                                        // esco se b7=0

m_LCDEnBit=0;
LCD_DELAY

m_LCDEnBit=1;                                        // strobe! cmq 2 nibble
LCD_DELAY

m_LCDEnBit=0;
LCD_DELAY

if(!t)                                        // esco se b7=0
break;

//    decf  lcd_temp1,f
//    bz  subLCDg3_err

}

subLCDg3_err:

m_LCDRSBit=1;                                        // dato

LCD_DELAY
m_LCDEnBit=1;                                        // leggo!
LCD_DELAY

Nop();
Nop();
t=PORTB << 4;            // nibble hi
t &= 0xf0;
*p=t;
Nop();
Nop();
Nop();

m_LCDEnBit=0;
LCD_DELAY

LCD_DELAY
m_LCDEnBit=1;                                        // leggo!
LCD_DELAY

Nop();
Nop();
t=PORTB >> 0;
t &= 0xf;
*p++ |= t;
Nop();
Nop();
Nop();

m_LCDEnBit=0;
LCD_DELAY
}

}

void LCDScroll(void) {
BYTE i,*p;
BYTE lcd_temp4;

if(LCDRows > 1) {                // se 1 riga, niente scroll!

goto skippa;     // QUA NO! e mettere ev. il flag di no scroll, v. sopra

if(LCDY == LCDRows) {

LCDScrollUp:

for(lcd_temp4=0; lcd_temp4<(LCDRows-1); lcd_temp4++) {                // riga corrente

lcd_temp4++;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga source
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

subLCDget();

lcd_temp4–;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga dest
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

p=LCDtmpBuf;
for(i=0; i<LCDCols; i++)
LCDOutData(*p++);

// se c’e’ clock attivo su prima riga, limitare lo scroll?
}

LCDY–;
LCDClearCurrentLine();
}

skippa:
LCDXY_();
}

}

void LCDScrollDown(void) {
BYTE i,*p;
BYTE lcd_temp4;

lcd_temp4=LCDRows-1;                    // riga corrente

do {

lcd_temp4–;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga source
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

subLCDget();

lcd_temp4++;
i= lcd_temp4 & 1 ? 0×40 : 0;                // calcolo posizione della riga dest
i+= lcd_temp4 & 2 ? LCDCols : 0;
LCDOutCmd(i | 0×80);

p=LCDtmpBuf;

for(i=0; i<LCDCols; i++)
LCDOutData(*p++);

// se c’e’ clock attivo su prima riga, limitare lo scroll?
} while(–lcd_temp4);

LCDY=0;
LCDClearCurrentLine();

LCDXY_();

}

void LCDPrintHex(BYTE w) {                    // stampa in HEX il BYTE in W
BYTE n;

n=(w >> 4) & 0xf;
if(n>=10)
n+=7;
LCDPutChar(n+’0′);
n=w & 0xf;
if(n>=10)
n+=7;
LCDPutChar(n+’0′);
LCDPutBlank();
}

void LCDPrintDec2(BYTE n) {                // stampa BYTE in W come decimale a 2 cifre (’0′ trailing)
char myBuf[4];

itoa(myBuf,n,10);        // C30 ce l’ha a cazzo!
LCDOutData(myBuf[0]);
LCDOutData(myBuf[1]);
}

void LCDClearLine(BYTE n) {                    // entra n=linea da pulire
BYTE temp;

LCDX=0;
LCDXY(n);
temp=LCDCols;
while(temp–) {
LCDOutBlankRaw();
}
LCDXY_();                    // in caso servisse, sono a inizio riga!
}

// —————————————————————————-

//         ————————————————————————-
#if PIXEL_PER_CELLA==6
BYTE drawLineaVertTable[8]= { 0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xfd,0xfc };
//    movlw 11111101b                    ; SetBit (su 6…)
#else
BYTE drawLineaVertTable[8]= { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8 };
//    movlw 11111101b                    ; SetBit (su 8…)
#endif

void drawLinea(BYTE x1,BYTE y1,BYTE x2,BYTE y2) {        // entrano coord. (lcd_temp2:lcd_temp3) (lcd_temp4:lcd_temp5)
// le X VENGONO ALTERATE!
//    alla fine si fa LCDXY per rimettere l’addr ptr a posto per il testo…
//    BYTE temp;
//    WORD bPos;
//    BYTE lcd_temp5;

}

void drawRect(BYTE x1,BYTE y1,BYTE x2,BYTE y2,BYTE w) {
// entrano coord. (lcd_temp6:lcd_temp7) (lcd_temp8:lcd_temp9); W=0 se vuoto, 1 se pieno, 2=grigio

}

void SetBeep(void) {                                    // asincrono, viene poi resettato da interrupt

//    PR2=BeepFreq;
//    CCPR1L=BeepFreq >> 1;        // /2 (duty cycle 50%)

//    SetDCOC3PWM(BeepFreq,BeepFreq>>1);
//    TRISBbits.TRISB9=0;

//    movlw  00000111b
//    movwf  T2CON
TimerBuzz=2;
}

/*
char *itoa(int i,char *buffer) {
unsigned int n;
unsigned char negate = 0;
int c = 6;

if(i < 0) {
negate=1;
n = -i;
}
else if(i == 0) {
buffer[0] = ’0′;
buffer[1] = 0;
return buffer;
}
else {
n = i;
}
buffer[c--] = 0;
do {
buffer[c--] = (n % 10) + ’0′;
n = n / 10;
} while (n);
if(negate) {
buffer[c--] = ‘-’;
}
return &buffer[c+1];
}
*/

Il contatore Geiger : interrupt.c

Posted Sunday, April 19th, 2015

#include <stdio.h>

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

#include “HardwareProfile.h”

#include <libpic30.h>

#include “contatoregeiger.h”

volatile WORD tick10=0;
volatile BYTE divider1s=0,second_05=0,minute_1=0;
extern volatile BYTE Buf232PtrI,Buf232PtrO;
extern volatile BYTE Buf232[BUF_232_SIZE];
extern volatile struct COMM_STATUS CommStatus;
extern volatile WORD cpsCounter;
extern volatile PIC24_RTCC_DATE currentDate;
extern volatile PIC24_RTCC_TIME currentTime;

// —————————————————————————————
void _ISR __attribute__((__no_auto_psv__)) _AddressError(void) {
Nop();
Nop();
}

void _ISR __attribute__((__no_auto_psv__)) _StackError(void) {
Nop();
Nop();
}

void __attribute__ (( interrupt, shadow,  no_auto_psv )) _T2Interrupt(void) {
// dev’essere 10Hz

//    WriteTimer2(0);    // WRITETIMER0(0) dovrebbe essere la macro!
TMR2=0;
mLED_1_Toggle();

tick10++;
divider1s++;
if(divider1s==5)         //
second_05=1;                    // flag
if(divider1s==10) {        // per RealTimeClock
second_05=1;
divider1s=0;
//        second_1=1;                    // flag
#ifdef USA_SW_RTC
currentTime.sec++;
if(currentTime.sec >= 60) {
currentTime.sec=0;
currentTime.min++;
minute_1=1;
if(currentTime.min >= 60) {
currentTime.min=0;
currentTime.hour++;
if(currentTime.hour >= 24) {
currentTime.hour=0;
currentDate.mday++;
}
}
}
#endif

}

IFS0bits.T2IF = 0;             //Clear the Timer2 interrupt status flag
//    T2_Clear_Intr_Status_Bit;     non la trova, frocio
}

void __attribute__ ((interrupt,no_auto_psv)) _U1RXInterrupt(void) {
BYTE ByteRec;

//        ClrWdt();

if(U1STAbits.FERR)
CommStatus.COMM_FRERR=1;
if(U1STAbits.OERR) {            // non mi interessano i caratteri ev. in attesa…
U1STAbits.OERR=0;

CommStatus.COMM_OVRERR=1;
}

while(!DataRdyUART1());
ByteRec = ReadUART1();

Buf232[Buf232PtrI++]=ByteRec;                // max 32
Buf232PtrI &= (BUF_232_SIZE-1);
// gestire    COMM_OVL  ?? ;         // errore di overflow buffer in ricezione

//putcUART1(ByteRec );            // test

U1RX_Clear_Intr_Status_Bit;
}

void __attribute__((interrupt,no_auto_psv)) _IC1Interrupt(void) {

cpsCounter++;
/*
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
IFS0bits.IC1IF = 0;        // non lo trova…
}

Il contatore Geiger : ContatoreGeiger.h

Posted Sunday, April 19th, 2015

#define SERNUM      1000
#define VERNUMH     1
#define VERNUML     0

//#define FLASH_TIME 7
#define USA_SW_RTC 1

enum {
MILLIROENTGEN=0,
CPS,
UGY,
USV,
UCKG
};
enum {
SBM20=0,
LND712
};
enum {
CO60,
RA226,
CS137
};
enum {
SLEEP=0,
READY
};

struct COMM_STATUS {
// errori/flag in CommStatus Seriale, (LSB prima – right-aligned)
unsigned int FRAME_2SEND:1;         // c’e’ da mandare un frame
unsigned int WAIT_4ACK  :1;
unsigned int FRAME_REC  :1;         // c’e’ un frame ricevuto
unsigned int COMM_OVRERR:1;                    // overrun seriale
unsigned int COMM_OVL   :1;         // errore di overflow buffer in ricezione
unsigned int COMM_TOUT  :1;         // errore di timeout in ricezione frame
unsigned int COMM_FRERR :1;         // errore di framing (START/STOP) in ricezione
unsigned int COMM_PERR  :1;         // errore di parita’ in ricezione  (0×80)
unsigned int BUSY  :1;                            // occupato
unsigned int LINE_BUSY  :1;         // linea intasata, impossibile inviare
unsigned int COMM_CRCERR  :1;         // errore di checksum in ricezione
};

#define CR           0xd
#define LF           0xa
//#define SYN        22
//#define EOT        4
//#define STX        2            // Fine messaggio di Utente
//#define ACK        6
//#define NACK    21

#define BUF_232_SIZE 32
#define BAUD_RATE 9600

// il Timer0 conta ogni 62.5nSec*prescaler… (@32MHz CPUCLK => 16MHz) su PIC24
#define TMR0BASE  (1010-11)    // 500uS ; reale=500.00025 10/2/11;
//#define DELAY_CORREZ (10)        // 22/1/2006, v.anche pelucheUSB.c
#define TMR2BASE (25010-11)        //   10Hz per timer
#define TMR3BASE (2510-11)        //   100Hz per capture

#define BEEP_STD_FREQ 100

#define EEscrivi(a,b) EEscrivi_(a,b)            // per lcd
void EEscrivi_(BYTE *addr,BYTE n);
BYTE EEleggi(BYTE *addr);
void EEscriviDword(BYTE *addr,DWORD n);
DWORD EEleggiDword(BYTE *addr);
void EEscriviWord(BYTE *addr,WORD n);
WORD EEleggiWord(BYTE *addr);
#define EEcopiaARAM(p) { *p=EEleggi(p); }
#define EEcopiaAEEPROM(p) EEscrivi_(p,*p)

void prepOutBuffer(BYTE );
void clearOutBuffer(void);
void prepStatusBuffer(BYTE);

#define DELAY_SPI_FAST 5
#define Delay08()    __delay_us(TIME_GRANULARITY)            // 1 bit-time
#define Delay_SPI() __delay_us(DELAY_SPI_FAST /*DelaySPIVal*/)
#define Delay_1uS() __delay_us(1)
#define Delay_uS(x) __delay_us(x)
#define Delay_mS(x) __delay_ms(x)
#define Delay_1mS() Delay_mS(1)
void I2CDelay(void);

void Beep(void);

void UserTasks(void);
BYTE KBInit(void);
void scanKBD(void);
void handleKBD(void);
void updLCD(void);

void LCDWriteNum(BYTE ,BYTE ,WORD ,signed char );
void LCDWriteStr(BYTE ,BYTE ,char *);
void LCDWriteBool(BYTE ,BYTE ,BYTE );
void LCDPutCharXY(BYTE ,BYTE ,char );

#define SCHERMATA_SPLASH 0
#define SCHERMATA_PRINCIPALE 1
#define PRIMA_SCHERMATA_VISUALIZZAZIONE (SCHERMATA_PRINCIPALE)        // qua sono la stessa… non c’è il pre-menu
#define ULTIMA_SCHERMATA_VISUALIZZAZIONE (PRIMA_SCHERMATA_PROGRAMMAZIONE-1)
#define PRIMA_SCHERMATA_PROGRAMMAZIONE 7
#define ULTIMA_SCHERMATA_PROGRAMMAZIONE (PRIMA_SCHERMATA_PROGRAMMAZIONE+10+3)        // tolto max min e la media/deviazione… aggiunto USB,lcd,baudrate, formatt.

enum MENU {
MENU_IDLE=0,
//    MENU_MAIN, qua no
MENU_VISUALIZZAZIONE,
//    MENU_PROGRAMMAZIONE_MENU,
MENU_PROGRAMMAZIONE
};

struct LCD_ITEM {
BYTE x,y;
BYTE size;
WORD valMin,valMax;
WORD *var;
BYTE varSize;
};
struct LCD_ITEM_GROUP {
struct LCD_ITEM item[2];
};

// PIC24 RTCC Structure
typedef union {
struct {
unsigned char   mday;       // BCD codification for day of the month, 01-31
unsigned char   mon;        // BCD codification for month, 01-12
unsigned char   year;       // BCD codification for years, 00-99
unsigned char   reserved;   // reserved for future use. should be 0
};                              // field access
unsigned char       b[4];       // byte access
unsigned short      w[2];       // 16 bits access
unsigned long       l;          // 32 bits access
} PIC24_RTCC_DATE;

// PIC24 RTCC Structure
typedef union {
struct {
unsigned char   sec;        // BCD codification for seconds, 00-59
unsigned char   min;        // BCD codification for minutes, 00-59
unsigned char   hour;       // BCD codification for hours, 00-24
unsigned char   weekday;    // BCD codification for day of the week, 00-06
};                              // field access
unsigned char       b[4];       // byte access
unsigned short      w[2];       // 16 bits access
unsigned long       l;          // 32 bits access
} PIC24_RTCC_TIME;

DWORD   PIC24RTCCGetTime( void );
DWORD   PIC24RTCCGetDate( void );
void    PIC24RTCCSetTime( WORD weekDay_hours, WORD minutes_seconds );
void    PIC24RTCCSetDate( WORD xx_year, WORD month_day );
void    UnlockRTCC( void );

BYTE to_bcd(BYTE );
BYTE from_bcd(BYTE );

//cmd #
enum {
CMD_NOP=0,
CMD_GETID=1,
CMD_GETCAPABILITIES=2,
CMD_GETCONFIG=3,
CMD_SETCONFIG,

CMD_GETSTATUS=8,
CMD_SETSTATUS,

CMD_TEST=16,
CMD_BEEP=17,
CMD_LCD=18,
CMD_GETLOG,

CMD_WRITEEEPROM=24,
CMD_WRITERTC=25,
CMD_READEEPROM=26,
CMD_READRTC=27,

CMD_RESET_IF=30,
CMD_DEBUG_ECHO=31,
CMD_READ_IDLOCS=63
};

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
*/

try it at home

Posted Sunday, April 19th, 2015