 1Content-type: application/x-Unknown; charset=UTF8package nmc.sidekick;

import javax.comm.SerialPort;
import com.ajile.drivers.spi.*;
import java.lang.Thread;
import java.io.IOException;
import javax.comm.SerialPort;
import javax.comm.CommPortIdentifier;

import nmc.common.*;
import com.ajile.jem.Configuration;
import nmc.sidekick.Rtc;
import com.ajile.jem.rawJEM;
import java.util.Date;
import java.util.Calendar;
public class Instantiator {

    private static int[] spiSlaveIndex = {
        SpiMaster.SPI_SLAVE_SELECT_0,
        SpiMaster.SPI_SLAVE_SELECT_1,
        SpiMaster.SPI_SLAVE_SELECT_2,
        SpiMaster.SPI_SLAVE_SELECT_3
    };

    public static DpaBoard[] dpaBoards = new DpaBoard[4];
    public static DpaBoard.DpaChannel[] dpaChannels = new DpaBoard.DpaChannel[8];

    public static String dpaPortNames[] = {
        "com0", // instrument serial port
        "com1", // instrument serial port
        "com2", // instrument serial port
        "com3", // instrument serial port
        "com4", // instrument serial port
        "com5", // instrument serial port
        "com6", // instrument serial port
        "com7", // instrument serial port
    };

    // The instrument drivers are actually instantiated in the array
    // initializer. 
    // channels 0-7 for instrument drivers (w/ DPA channels; InstrumentSensorDrivers)
    // channels 8-11 for things on SK with serial ports
    // channels 12-15 for environmental sensors (w/o DPA channels; EnvironmentalSensorDrivers)
    //public static InstrumentSensorDriver[] instrumentDrivers= {
    public static SensorDriver[] instrumentDrivers= {
        null,
        null,
        null,
        null,
        null,
        null,
        new eMeter(),  // e.g., 'new MicroKat(), new eMeter() etc'
        new MicroKat(),
        null, // channels 8-11 for use by things on SK with serial ports
        null,
        null,
        null,
        new SKHumidity(2), 
        new SKPressureTemp(),
        null,
        null,
    };

    protected static SpiMaster spi = SpiMaster.getInstance();
    private static Rtc rtc = Rtc.getInstance();
    /**
     * Starts the application.
     * @param args an array of command-line arguments
     */
    public static void main(java.lang.String[] args) {
        /* Turn off Rtc CS FIRST THING!!! or else we might lose time */
        rtc.initialize();

        // Set to NO_DEBUG or SYSTEM_OUT
        // DebugMessage.setOutDevice(DebugMessage.NO_DEBUG);
        DebugMessage.setOutDevice(DebugMessage.SYSTEM_OUT);
        
        // Blink the lights to show we're alive, then
        // turn off for power savings
        blinkLeds(3,500,false);

        InitSpiBus();

        // Set Ajile clock = RTC
        SyncSystemClock();

       // Find and Initialize DPA HW
       // Create drivers and bind to DPA channels 
        SetupDpaBoards();
        
        // Enter the main loop
        try{
          CommandParser cp = new CommandParser();
          cp.loadAndGo(); // this is still the main thread;
        }catch(Throwable t){DebugMessage.println("Instantiator: Throwable caught! "+t);}
}// end main()

    public static void InitSpiBus() {
        synchronized(spi){
          spi.setClkDivider(spi.SPI_CLOCK_DIVIDER_64);
        }
    }// end InitSpiBus()

    public static void SyncSystemClock() {
        DebugMessage.println("Synchronizing RTC and Ajile System clocks ");
        long nowR=0;
        long nowA=0;
        nowA=System.currentTimeMillis();
        DebugMessage.println("Ajile System time currently: "+Rtc.toString((long)nowA)+" ("+nowA+")");

         synchronized(rtc){
           if(rtc.isInitialized==false)
              rtc.initialize();
           nowR =rtc.currentTimeMillis();
         }
         Configuration.setBaseTime(nowR);
         nowA=System.currentTimeMillis();
         DebugMessage.println("Ajile System time set to: "+Rtc.toString((long)nowA)+" ("+nowA+")");
         DebugMessage.println("RTC time set to : "+Rtc.toString((long)nowR)+" ("+nowR+")");
    }// end SyncSystemClock()

    public static void SetupDpaBoards() {
        // must call InitSpiBus() first
        FindDpaBoards();
        InitDpaChannels();
    }

    public static void FindDpaBoards() {
        // must call InitSpiBus() first
        // Figure out what Dpa boards exist...
        for (int i=0; i<4; i++) {
            boolean dpaHdwr = DpaBoard.checkForDpaHardware(spiSlaveIndex[i]);
            if (dpaHdwr) {
                DebugMessage.println("At location " + i
                                   + " there is a dpa board");
                dpaBoards[i] = new DpaBoard(spiSlaveIndex[i]);
            } else {
                DebugMessage.println("At location " + i
                                   + " there is NOT a dpa board");
                dpaBoards[i] = null;
            }
        }
    }// end FindDpaBoards()

    // This is very similar to InitDpaChannels, except that it ONLY inits
    // the DPA channels.  It does not do anything with the serial ports
    // or the instrument drivers
    public static void InitDpaChannelsOnly() {
        // For all the dpa boards,
        //    initialize their channels,
        //    create the appropriate serial ports,
        //    and tell the driver about its DpaChannel and its serial port.
        for (int i=0; i<4; i++) {
            if (dpaBoards[i] != null) {
                int channelIndex = 2*i;

                dpaChannels[channelIndex] = dpaBoards[i].getLeftChannel();
                dpaChannels[channelIndex].initializeChannel();

                channelIndex++;
                dpaChannels[channelIndex] = dpaBoards[i].getRightChannel();
                dpaChannels[channelIndex].initializeChannel();
            }
        }
    }// end InitDpaChannelsOnly()

    public static void InitDpaChannels() {
        // For all the dpa boards,
        //    initialize their channels,
        //    create the appropriate serial ports,
        //    and tell the driver about its DpaChannel and its serial port.
        for (int i=0; i<4; i++) {
            if (dpaBoards[i] != null) {
                int channelIndex = 2*i;

                dpaChannels[channelIndex] = dpaBoards[i].getLeftChannel();
                dpaChannels[channelIndex].initializeChannel();
                SerialPort sp = openSerialPort(channelIndex);
                //InstrumentSensorDriver d = instrumentDrivers[channelIndex];
                SensorDriver d = instrumentDrivers[channelIndex];
	    try{
                if (d != null) {
                    //d.setSerialPort(sp);
                    //d.setDpaChannel(dpaChannels[channelIndex]);
                     ((InstrumentSensorDriver) d).setSerialPort(sp);
                     ((InstrumentSensorDriver) d).setDpaChannel(dpaChannels[channelIndex]);
                    // for backwards compatability, we support the
                    // channel holding onto a serial port.
                    // This should be removed asap.
                    dpaChannels[channelIndex].setSerialPort(sp);
                }

                channelIndex++;
                dpaChannels[channelIndex] = dpaBoards[i].getRightChannel();
                dpaChannels[channelIndex].initializeChannel();
                sp = openSerialPort(channelIndex);
                d = instrumentDrivers[channelIndex];
                if (d != null) {
                    //d.setSerialPort(sp);
                    //d.setDpaChannel(dpaChannels[channelIndex]);
                     ((InstrumentSensorDriver) d).setSerialPort(sp);
                     ((InstrumentSensorDriver) d).setDpaChannel(dpaChannels[channelIndex]);
                    // also remove this one when it's time...
                    dpaChannels[channelIndex].setSerialPort(sp);
                }
	    }catch(Exception e){DebugMessage.println("InitializeDpaChannels() Exception caught "+e);}
            }
            
        }

        // Now remove any drivers that don't have a channel (i.e.,
        // don't have a DpaBoard (this allows us to iterate over all
        // the drivers without having to special-case the ones that
        // don't have anything to talk to; that is really an error
        // in configuration, perhaps a more aggressive flagging should
        // be in order... but then again, we may remove a malfunctioning
        // dpa board from service..... this is good enough for now.
        //
        for (int i=0; i<8; i++) {
            if (dpaChannels[i] == null) {
                instrumentDrivers[i] = null;
            }
        }
    }// end InitDpaChannels()

    static void InitializeDrivers(OutboundMessageQ theOutboundMsgQ) {
        for (int i=0; i<15; i++) {
            //InstrumentSensorDriver d = instrumentDrivers[i];
            SensorDriver d = instrumentDrivers[i];
            if (d != null) {
                d.setOutboundMessageQ(theOutboundMsgQ);
                d.initialize();
            }
        }
    }// end InitializeDrivers()

    protected static SerialPort openSerialPort(int i)  {
        String portName = dpaPortNames[i];
        CommPortIdentifier commPortId;
        SerialPort serialPort = null;
        try {
            DebugMessage.println("opening port: " + portName);
            commPortId = CommPortIdentifier.getPortIdentifier(portName);
            serialPort = (SerialPort)commPortId.open(portName, 0);
            DebugMessage.println("port config: "+serialPort.getBaudRate()+" "+serialPort.getParity()+" "+serialPort.getDataBits()+" "+serialPort.getStopBits());
        } catch (javax.comm.PortInUseException e) {
            DebugMessage.println("Could not open port " + portName
                               + " (already in use), exception: " + e);
            return null;
        } catch (javax.comm.NoSuchPortException e2) {
            DebugMessage.println("javax.comm.NoSuchPortException on '"
                               + portName + "', exception: " + e2);
            return null;
        } 

        // This really should throw an exception if it cannot
        // create a fully functioning serial port.

        return serialPort;
    } // end openSerialPort()

    // should move following functions to a helper class
    public void blockForever(){
       DebugMessage.println("Stopping the program dead in its tracks...");
       while(true);
    }

   public static void initLeds(){
          rawJEM.setField(1,AjileAddr.GPIOB_OER,7,1);
          rawJEM.setField(1,AjileAddr.GPIOD_OER,2,1);
   }//end initLeds()
          
    public static void setGreenLed(boolean on){
	if(on==true)
              rawJEM.setField(1,AjileAddr.GPIOB_OR,7,1);
	else
              rawJEM.setField(0,AjileAddr.GPIOB_OR,7,1);
    }

    public static void setRedLed(boolean on){
	if(on==true)
              rawJEM.setField(1,AjileAddr.GPIOD_OR,2,1);
	else
              rawJEM.setField(0,AjileAddr.GPIOD_OR,2,1);
    }
    
    public static void blinkLeds(int n,int t,boolean exitOn){
    	initLeds();
    	for(int i=0;i<n;i++){
    	  setGreenLed(true);
    	  setRedLed(true);
              Instantiator.delay(t);
    	  setGreenLed(false);
    	  setRedLed(false);
              Instantiator.delay(t);          
    	}
    	if(exitOn==true){
    	  setGreenLed(true);
    	  setRedLed(true);
    	}
    }
    
public  static void delay(int ms){
	try{
	 DebugMessage.println("delaying "+ms+" ms");
	  Thread.sleep(ms);
	}catch(InterruptedException e){DebugMessage.println("Should never see this InterruptedException");}    
}

}





