static int mbox_property(int file_desc, void *buf)
{
   int fd = file_desc;
   int ret_val = -1;

   if (fd < 0) {
      fd = mbox_open();
   }
   if (fd >= 0) {
      ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf);

      if (ret_val < 0) {
         printf("ioctl_set_msg failed, errno %d: %m\n", errno);
      }
   }
#ifdef DEBUG
   unsigned *p = buf; int i; unsigned size = *(unsigned *)buf;
   for (i=0; i<size/4; i++)
      printf("%04x: 0x%08x\n", i*sizeof *p, p[i]);
#endif
   if (file_desc < 0)
      mbox_close(fd);

   return ret_val;
}
Exemple #2
0
static void
terminate(int dummy)
{
	int i;

	dprintf("Resetting DMA...\n");
	if (dma_reg && mbox.virt_addr) {
		for (i = 0; i < num_channels; i++)
			channel_pwm[i] = 0;
		update_pwm();
		udelay(CYCLE_TIME_US);
		dma_reg[DMA_CS] = DMA_RESET;
		udelay(10);
	}

	dprintf("Freeing mbox memory...\n");
	if (mbox.virt_addr != NULL) {
		unmapmem(mbox.virt_addr, NUM_PAGES * PAGE_SIZE);
		if (mbox.handle <= 2) {
			/* we need to reopen mbox file */
			mbox.handle = mbox_open();
		}
		mem_unlock(mbox.handle, mbox.mem_ref);
		mem_free(mbox.handle, mbox.mem_ref);
		mbox_close(mbox.handle);
	}
	dprintf("Unlink %s...\n", DEVFILE);
	unlink(DEVFILE);
	dprintf("Unlink %s...\n", DEVFILE_MBOX);
	unlink(DEVFILE_MBOX);
	printf("pi-blaster stopped.\n");

	exit(1);
}
/**
 * Cleanup previously allocated device memory and buffers.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  None
 */
void ws2811_cleanup(ws2811_t *ws2811)
{
    int chan;
    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)
    {
        if (ws2811->channel[chan].leds)
        {
            free(ws2811->channel[chan].leds);
        }
        ws2811->channel[chan].leds = NULL;
    }

    if (mbox.virt_addr != NULL)
    {
        unmapmem(mbox.virt_addr, mbox.size);
        mem_unlock(mbox.handle, mbox.mem_ref);
        mem_free(mbox.handle, mbox.mem_ref);
        if (mbox.handle >= 0)
            mbox_close(mbox.handle);
        memset(&mbox, 0, sizeof(mbox));
    }

    ws2811_device_t *device = ws2811->device;
    if (device) {
        free(device);
    }
    ws2811->device = NULL;
}
Exemple #4
0
/**
 * Cleanup previously allocated device memory and buffers.
 *
 * @param    ws2811  ws2811 instance pointer.
 *
 * @returns  None
 */
void ws2811_cleanup(ws2811_t *ws2811)
{
    ws2811_device_t *device = ws2811->device;
    int chan;

    for (chan = 0; chan < RPI_PWM_CHANNELS; chan++)
    {
        if (ws2811->channel[chan].leds)
        {
            free(ws2811->channel[chan].leds);
        }
        ws2811->channel[chan].leds = NULL;
    }

    if (device->mbox.handle != -1)
    {
        videocore_mbox_t *mbox = &device->mbox;

        unmapmem(mbox->virt_addr, mbox->size);
        mem_unlock(mbox->handle, mbox->mem_ref);
        mem_free(mbox->handle, mbox->mem_ref);
        mbox_close(mbox->handle);

        mbox->handle = -1;
    }

    if (device) {
        free(device);
    }
    ws2811->device = NULL;
}
Exemple #5
0
int main(int argc, char *argv[])
{
  int mb = mbox_open();
  unsigned words[MAX_WORDS] = {};
  int i;

  if (argc < 2 || argc+1 >= MAX_WORDS)
  {
    printf("Usage %s [word0] [word1] ...\n", argv[0]);
    return 1;
  }

  words[0] = (argc+2) * sizeof words[0];
  words[1] = 0; // process request
  for (i=1; i<argc; i++)
    words[i+1] = strtoul(argv[i], 0, 0);

  words[argc+1] = 0; // end tag

  int s = mbox_property(mb, words);

  mbox_close(mb);

  for (i=0; i<argc+2; i++)
     printf("0x%08x ", words[i]);
  printf("\n");
  return s;
}
Exemple #6
0
void mbox_deinit(void)
{
    // Remove any envelope symbols
    lcd_symbol_clr(LCD_SYMBOL_ENV_MAIN);
    lcd_symbol_clr(LCD_SYMBOL_ENV_CL);
    lcd_symbol_clr(LCD_SYMBOL_ENV_OP);
    
    // Close mailbox and indicate no longer initialized
    mbox_close();
    mbox_initalized = false;
}
Exemple #7
0
void main (int argc, char *argv[])
{
  char so4[SO4_SIZE] = {'S', 'O', '4'};

  mbox_t h_mbox;           // Handle to the mailbox
  sem_t s_procs_completed; // Semaphore to signal the original process that we're done

  if (argc != 3) { 
    Printf("Usage: %s <handle_to_mailbox> <handle_to_page_mapped_semaphore>\n"); 
    Exit();
  } 

  // Convert the command-line strings into integers for use as handles
  h_mbox = dstrtol(argv[1], NULL, 10); // The "10" means base 10
  s_procs_completed = dstrtol(argv[2], NULL, 10);

  // Open the mailbox
  if (mbox_open(h_mbox) == MBOX_FAIL) {
    Printf("Generator SO4 (%d): Could not open the mailbox!\n", getpid());
    Exit();
  }

  // Send a message to the mailbox
  if (mbox_send(h_mbox, SO4_SIZE, (void *) so4) == MBOX_FAIL) {
    Printf("Generator SO4 (%d): Could not send message to the mailbox %d!\n", getpid(), h_mbox);
    Exit();
  }
 
  // Now print a message to show that everything worked
  Printf("Generate SO4 Molecule\n");

  // Close the mbox
  if (mbox_close(h_mbox) == MBOX_FAIL) {
    Printf("Generator SO4 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }


  // Signal the semaphore to tell the original process that we're done
  if(sem_signal(s_procs_completed) != SYNC_SUCCESS) {
    Printf("Generator SO4 (%d): Bad semaphore s_procs_completed (%d)!\n", getpid(), s_procs_completed);
    Exit();
  }

  Printf("Generator SO4 (%d): Done!\n", getpid());

}
Exemple #8
0
void main (int argc, char *argv[])
{
    sem_t s_procs_completed;    // Semaphore to signal the original process that we're done
    mbox_t mb_n2;                // mailbox for H2O atom

    Printf("Starting N2 Injection - PID %d \n", getpid());

    if (argc > 4 ) { 
        Printf("Usage: "); Printf(argv[0]); Printf(" <handle_to_proc_semaphore> <handle_to_N2_mailbox>\n"); 
        Exit();
    } 

    // Convert the command-line strings into integers for use as handles
    s_procs_completed = dstrtol(argv[1], NULL, 10);
    mb_n2 = dstrtol(argv[2], NULL, 10);
   
    if(!mbox_open(mb_n2)){
        Printf("Bad mailbox open mb_n2\n");
        Exit();
    }

    Printf("opened n2 mailbox\n");

    if(mbox_send(mb_n2, 2, (void *) "N2") != MBOX_SUCCESS){
        Printf("N2 send error\n");
    }
    Printf("Sent N2 to mb_n2\n");

    if(!mbox_close(mb_n2)){
        Printf("Bad mailbox open mb_n2\n");
        Exit();
    }

    // Signal the semaphore to tell the original process that we're done
    Printf("Inject N2: PID %d is complete.\n", getpid());

    if(sem_signal(s_procs_completed) != SYNC_SUCCESS) {
        Printf("Bad semaphore s_procs_completed (%d) in ", s_procs_completed); Printf(argv[0]); Printf(", exiting...\n");
        Exit();
    }
}
Exemple #9
0
static int mbox_property(int file_desc, void *buf) {
    int fd = file_desc;
    int ret_val = -1;

    if (fd < 0) {
        fd = mbox_open();
    }

    if (fd >= 0) {
        ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf);

        if (ret_val < 0) {
            perror("ioctl_set_msg failed\n");
        }
    }

    if (file_desc < 0) {
        mbox_close(fd);
    }

    return ret_val;
}
Exemple #10
0
int mbox_open(void)
{
    // Return if not initialized
    if (mbox_initalized == false) {
        return EOF;
    }
    
    // If allready open, close first
    if (mbox_is_open == true) {
        mbox_close();
    }
    
    // Start file rading at start of data flash
    sfs_fget_restart();
    
    // allocate memory for mail reading
    if ((mbox_mail_element = (mbox_mail_element_t*)vrt_mem_alloc(/*sizeof(mbox_mail_element_t)*/ + 64)) == NULL) {
        return EOF;
    } else {
        mbox_is_open = true;
        return 0;
    }
}
Exemple #11
0
void main (int argc, char *argv[])
{
  int ct;

  char h2o_buffer_1[H2O_SIZE];
  char h2o_buffer_2[H2O_SIZE];

  char h2_molecule[H2_SIZE] = {'H', '2'};
  char o2_molecule[O2_SIZE] = {'O', '2'};
  
  mbox_t h_mbox_h2o;           // Handle to the mailbox for h2o
  mbox_t h_mbox_h2;
  mbox_t h_mbox_o2;

  sem_t s_procs_completed; // Semaphore to signal the original process that we're done

  if (argc != 5) { 
    Printf("Usage: %s <mailbox h2o> <mailbox h2> <mailbox o2> <handle_to_page_mapped_semaphore>\n"); 
    Exit();
  } 

  // Convert the command-line strings into integers for use as handles
  h_mbox_h2o = dstrtol(argv[1], NULL, 10); // The "10" means base 10
  h_mbox_h2 = dstrtol(argv[2], NULL, 10); // The "10" means base 10
  h_mbox_o2 = dstrtol(argv[3], NULL, 10); // The "10" means base 10

  s_procs_completed = dstrtol(argv[4], NULL, 10);

  // Open the h2o mailbox
  if (mbox_open(h_mbox_h2o) == MBOX_FAIL) {
    Printf("Reaction 1 (%d): Could not open the h2o mailbox!\n", getpid());
    Exit();
  }

  // Wait for the first h2o molecule from the mailbox
  if (mbox_recv(h_mbox_h2o, H2O_SIZE, (void *) h2o_buffer_1) == MBOX_FAIL) {
    Printf("Reaction 1 (%d): Could not receive message from the mbox %d!\n", getpid(), h_mbox_h2o);
    Exit();
  }

  // Wait for the second h2o molecule from the mailbox  
  if (mbox_recv(h_mbox_h2o, H2O_SIZE, (void *) h2o_buffer_2) == MBOX_FAIL) {
    Printf("Reaction 1 (%d): Could not receive message from the mbox %d!\n", getpid(), h_mbox_h2o);
    Exit();
  }

  // Close the h2o mailbox
  if (mbox_close(h_mbox_h2o) == MBOX_FAIL) {
    Printf("Reaction 1 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }

  // Open the h2 mailbox
  if (mbox_open(h_mbox_h2) == MBOX_FAIL) {
    Printf("Reaction 1 (%d): Could not open the h2 mailbox!\n", getpid());
    Exit();
  }


  // Send the first h2 to the h2 mailbox
  if (mbox_send(h_mbox_h2, H2_SIZE, (void *) h2_molecule) == MBOX_FAIL) {
    Printf("Generator h2 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_h2);
    Exit();
  }

  // Send the second h2 to the h2 mailbox
  if (mbox_send(h_mbox_h2, H2_SIZE, (void *) h2_molecule) == MBOX_FAIL) {
    Printf("Generator h2 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_h2);
    Exit();
  }


  // Close the h2 mailbox
  if (mbox_close(h_mbox_h2) == MBOX_FAIL) {
    Printf("Generator h2 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }


  // Open the o2 mailbox
  if (mbox_open(h_mbox_o2) == MBOX_FAIL) {
    Printf("Reaction 1 (%d): Could not open the o2 mailbox!\n", getpid());
    Exit();
  }
  

  // Send the o2 to the o2 mailbox
  if (mbox_send(h_mbox_o2, O2_SIZE, (void *) o2_molecule) == MBOX_FAIL) {
    Printf("Reaction o2 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_o2);
    Exit();
  }

  // Close the o2 mailbox
  if (mbox_close(h_mbox_o2) == MBOX_FAIL) {
    Printf("Reaction o2 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }

  // Now print a message to show that everything worked
  Printf("Two molecules H2 has been generated\n");
  Printf("A molecule O2 has been generated\n");

  // Signal the semaphore to tell the original process that we're done
  if(sem_signal(s_procs_completed) != SYNC_SUCCESS) {
    Printf("Reaction 1 (%d): Bad semaphore s_procs_completed (%d)!\n", getpid(), s_procs_completed);
    Exit();
  }

  Printf("Reaction 1 (%d): Done!\n", getpid());
}
Exemple #12
0
int
main(int argc, char **argv)
{
	parseargs(argc, argv);
	mbox.handle = mbox_open();
	if (mbox.handle < 0)
		fatal("Failed to open mailbox\n");
	unsigned mbox_board_rev = get_board_revision(mbox.handle);
	printf("MBox Board Revision: %#x\n", mbox_board_rev);
	get_model(mbox_board_rev);
	unsigned mbox_dma_channels = get_dma_channels(mbox.handle);
	printf("DMA Channels Info: %#x, using DMA Channel: %d\n", mbox_dma_channels, DMA_CHAN_NUM);

	printf("Using hardware:                 %5s\n", delay_hw == DELAY_VIA_PWM ? "PWM" : "PCM");
	printf("Number of channels:             %5d\n", (int)num_channels);
	printf("PWM frequency:               %5d Hz\n", 1000000/CYCLE_TIME_US);
	printf("PWM steps:                      %5d\n", NUM_SAMPLES);
	printf("Maximum period (100  %%):      %5dus\n", CYCLE_TIME_US);
	printf("Minimum period (%1.3f%%):      %5dus\n", 100.0*SAMPLE_US / CYCLE_TIME_US, SAMPLE_US);
	printf("DMA Base:                  %#010x\n", DMA_BASE);

	setup_sighandlers();

	/* map the registers for all DMA Channels */
	dma_virt_base = map_peripheral(DMA_BASE, (DMA_CHAN_SIZE * (DMA_CHAN_MAX + 1)));
	/* set dma_reg to point to the DMA Channel we are using */
	dma_reg = dma_virt_base + DMA_CHAN_NUM * (DMA_CHAN_SIZE / sizeof(dma_reg));
	pwm_reg = map_peripheral(PWM_BASE, PWM_LEN);
	pcm_reg = map_peripheral(PCM_BASE, PCM_LEN);
	clk_reg = map_peripheral(CLK_BASE, CLK_LEN);
	gpio_reg = map_peripheral(GPIO_BASE, GPIO_LEN);

	/* Use the mailbox interface to the VC to ask for physical memory */
	mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * PAGE_SIZE, PAGE_SIZE, mem_flag);
	/* TODO: How do we know that succeeded? */
	dprintf("mem_ref %u\n", mbox.mem_ref);
	mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref);
	dprintf("bus_addr = %#x\n", mbox.bus_addr);
	mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * PAGE_SIZE);
	dprintf("virt_addr %p\n", mbox.virt_addr);

	if ((unsigned long)mbox.virt_addr & (PAGE_SIZE-1))
		fatal("pi-blaster: Virtual address is not page aligned\n");

	/* we are done with the mbox */
	mbox_close(mbox.handle);
	mbox.handle = -1;
	
	//fatal("TempFatal\n");

	init_ctrl_data();
	init_hardware();
	init_channel_pwm();
	// Init pin2gpio array with 0/false values to avoid locking all of them as PWM.
	init_pin2gpio();
	// Only calls update_pwm after ctrl_data calculates the pin mask to unlock all pins on start.
	init_pwm();
	unlink(DEVFILE);
	if (mkfifo(DEVFILE, 0666) < 0)
		fatal("pi-blaster: Failed to create %s: %m\n", DEVFILE);
	if (chmod(DEVFILE, 0666) < 0)
		fatal("pi-blaster: Failed to set permissions on %s: %m\n", DEVFILE);

	printf("Initialised, ");
	if (daemonize) {
		if (daemon(0,1) < 0) 
			fatal("pi-blaster: Failed to daemonize process: %m\n");
		else
			printf("Daemonized, ");
	}
	printf("Reading %s.\n", DEVFILE);

	go_go_go();

	return 0;
}
Exemple #13
0
void main (int argc, char *argv[])
{
  int numprocs;               // Used to store number of processes to create
  int i;                          // Loop index variable
  missile_code mc;                // Used as message for mailbox
  
  int num_N2;                     //numer of N2 injection
  int num_H2O;                    //number of H2O injection
  int num_N2_2N;                  //number of reaction1
  int num_H2O_H2_O2;              //number of reaction2
  int num_N_O2_NO2;               //number of reaction3
  int number_N2;                  //number of N2 molecules
  int number_H2O;                 //number of H2O molecules

  mbox_t mbox_N2;                  //N2 mailbox
  mbox_t mbox_N;                   //N mailbox
  mbox_t mbox_H2O;                 //H2O mailbox
  mbox_t mbox_H2;                  //H2 mailbox
  mbox_t mbox_O2;                  //O2 mailbox
  mbox_t mbox_NO2;                 //NO2 mailbox
  
  sem_t s_procs_completed;        // Semaphore used to wait until all spawned processes have completed
  char mbox_N2_str[10];            // Used as command-line argument to pass mem_handle to new processes
  char mbox_N_str[10];
  char mbox_H2O_str[10];
  char mbox_H2_str[10];
  char mbox_O2_str[10];
  char mbox_NO2_str[10];
  char s_procs_completed_str[10]; // Used as command-line argument to pass page_mapped handle to new processes

  if (argc != 3) {
    Printf("Usage: ");Printf(argv[0]);Printf("<number of N2 molecules> <number of H2O molecules\n");
    Exit();
  }
  
  // Convert string from ascii command line argument to integer number
  number_N2 = dstrtol(argv[1],NULL,10); //the "10" means base 10
  number_H2O = dstrtol(argv[2],NULL,10);
  
  if(number_H2O%2 ==1){
     num_H2O = number_H2O;
     num_H2O_H2_O2 = (number_H2O-1)/2;
     num_N2 = number_N2;
     num_N2_2N = number_N2;
     if (2*num_N2>num_H2O_H2_O2){    //number of N larger than number of O2
         num_N_O2_NO2 = num_H2O_H2_O2;
     }
     else{
         num_N_O2_NO2 = 2*num_N2;
     }
   }
  else{
     num_H2O = number_H2O;
     num_H2O_H2_O2 =(number_H2O)/2;
     num_N2 = number_N2;
     num_N2_2N = number_N2;
     if (2*num_N2>num_H2O_H2_O2){  //number of N larger than number of O2
        num_N_O2_NO2 = num_H2O_H2_O2;
     }
     else{
         num_N_O2_NO2 = 2*num_N2;
     }
   }
   
   numprocs=num_H2O+num_N2+num_H2O_H2_O2+num_N2_2N+num_N_O2_NO2;

  // Allocate space for a mailbox
  if ((mbox_N2 = mbox_create()) == MBOX_FAIL) {
    Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid());
    Exit();
  }

  if ((mbox_N = mbox_create()) == MBOX_FAIL) {
    Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid());
    Exit();
  }

  if ((mbox_O2 = mbox_create()) == MBOX_FAIL) {
    Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid());
    Exit();
  }
  
  if ((mbox_NO2 = mbox_create()) == MBOX_FAIL) {
    Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid());
    Exit();
  }

  if ((mbox_H2O = mbox_create()) == MBOX_FAIL) {
    Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid());
    Exit();
  }

  if ((mbox_H2 = mbox_create()) == MBOX_FAIL) {
    Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid());
    Exit();
  }

  // Open mailbox to prevent deallocation
  if (mbox_open(mbox_N2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_N2);
    Exit();
  }

  if (mbox_open(mbox_N) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_N);
    Exit();
  }

  if (mbox_open(mbox_H2O) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_H2O);
    Exit();
  }

  if (mbox_open(mbox_H2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_H2);
    Exit();
  }
  if (mbox_open(mbox_O2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_O2);
    Exit();
  }
  if (mbox_open(mbox_NO2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_NO2);
    Exit();
  }
  // Put some values in the mc structure to send as a message
  mc.numprocs = numprocs;
  mc.really_important_char = 'A';

  // Create semaphore to not exit this process until all other processes 
  // have signalled that they are complete.  To do this, we will initialize
  // the semaphore to (-1) * (number of signals), where "number of signals"
  // should be equal to the number of processes we're spawning - 1.  Once 
  // each of the processes has signaled, the semaphore should be back to
  // zero and the final sem_wait below will return.
  if ((s_procs_completed = sem_create(-(numprocs-1))) == SYNC_FAIL) {
    Printf("makeprocs (%d): Bad sem_create\n", getpid());
    Exit();
  }

  // Setup the command-line arguments for the new process.  We're going to
  // pass the handles to the shared memory page and the semaphore as strings
  // on the command line, so we must first convert them from ints to strings.
  ditoa(mbox_N2, mbox_N2_str);
  ditoa(mbox_H2O, mbox_H2O_str);
  ditoa(mbox_N, mbox_N_str);
  ditoa(mbox_H2, mbox_H2_str);
  ditoa(mbox_O2, mbox_O2_str);
  ditoa(mbox_NO2, mbox_NO2_str);
  ditoa(s_procs_completed, s_procs_completed_str);

  // Now we can create the processes.  Note that you MUST end your call to
  // process_create with a NULL argument so that the operating system
  // knows how many arguments you are sending.
  for(i=0; i<num_N2; i++) {
    process_create(FILENAME_TO_RUN_0, 0, 0, mbox_N2_str,s_procs_completed_str, NULL);
 //   Printf("makeprocs (%d): Process %d created\n", getpid(), i);
  }
  for(i=0; i<num_H2O; i++) {
    process_create(FILENAME_TO_RUN_1, 0, 0, mbox_H2O_str, s_procs_completed_str, NULL);
//    Printf("makeprocs (%d): Process %d created\n", getpid(), i);
  }
  for(i=0; i<num_N2_2N; i++) {
    process_create(FILENAME_TO_RUN_2, 0, 0, mbox_N2_str,mbox_N_str, s_procs_completed_str, NULL);
//    Printf("makeprocs (%d): Process %d created\n", getpid(), i);
  }
  for(i=0; i<num_H2O_H2_O2; i++) {
    process_create(FILENAME_TO_RUN_3, 0, 0, mbox_H2O_str,mbox_H2_str,mbox_O2_str, s_procs_completed_str, NULL);
//    Printf("makeprocs (%d): Process %d created\n", getpid(), i);
  }
  for(i=0; i<num_N_O2_NO2; i++) {
    process_create(FILENAME_TO_RUN_4, 0, 0, mbox_N_str,mbox_O2_str,mbox_NO2_str, s_procs_completed_str, NULL);
//    Printf("makeprocs (%d): Process %d created\n", getpid(), i);
  }

  // And finally, wait until all spawned processes have finished.
  if (sem_wait(s_procs_completed) != SYNC_SUCCESS) {
    Printf("Bad semaphore s_procs_completed (%d) in ", s_procs_completed); Printf(argv[0]); Printf("\n");
    Exit();
  }
  if (mbox_close(mbox_N2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_N2);
    Exit();
  }
  if (mbox_close(mbox_N) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_N);
    Exit();
  }
  if (mbox_close(mbox_O2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_O2);
    Exit();
  }
  if (mbox_close(mbox_NO2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_NO2);
    Exit();
  }
  if (mbox_close(mbox_H2O) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_H2O);
    Exit();
  }
  if (mbox_close(mbox_H2) == MBOX_FAIL) {
    Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_H2);
    Exit();
  }
  Printf("makeprocs (%d): All other processes completed, exiting main process.\n", getpid());
}
void int_evt_key(void* evt)
{
    key_state_t key_state = *(key_state_t*)evt;
    FMENU_item_flash_t* current_menu_entry = FMENU_GetCurrentItem(&MENU_menuHandle);
    FMENU_item_flash_t* new_menu_entry = current_menu_entry;
    menu_action_t menu_action = MENU_ACTION_ENTER;
    int int_temp;
    static uint8_t file_name[SFS_MAX_FILENAME_BUFFER_SIZE];
    unsigned char search_string[SFS_MAX_FILENAME_BUFFER_SIZE];
    lcd_config_t config;
    static key_state_t auto_key_state;
    static bool auto_key_wait = true;
    static bool auto_key_registered = false;
    static asy_tmr_t auto_key_timer = ASY_TMR_NO_TIMER;
    
    // Navigate to next avrraven.status.state
    switch (key_state){
    case KEY_UP:
        switch (avrraven.status.state) {
        case STATE_IDLE:
            new_menu_entry = FMENU_NavigateUp(&MENU_menuHandle);
            break;
        case STATE_CONFIG_DEBUG_ENABLE:
            lcd_puts_P("ENABLE");
            avrraven.user_config.debug_enable = true;
            break;
        case STATE_CONFIG_TXTPREV_ENABLE:
            lcd_puts_P("ENABLE");
            avrraven.user_config.txtmsg_preview = true;
            break;
        case STATE_CONFIG_FW_UPGRADE:
            lcd_puts_P("AUTO");
            avrraven.user_config.fw_upgr_auto = true;
            break;
        case STATE_CONFIG_CONNECT:
            lcd_puts_P("AUTO");
            avrraven.user_config.join_auto = true;
            break;
        case STATE_CONFIG_IMG_RCV:
            lcd_puts_P("AUTO");
            avrraven.user_config.fw_rcv_auto = true;
            break;
        case STATE_CONFIG_NAME:
        case STATE_MAIL_COMPOSE:
            txtedit_event(TXTEDIT_KEY_UP);
            break;
        case STATE_CONFIG_LCD_CONTRAST:
            lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE);
            config = lcd_config_get();
            config.contrast = numedit_buffer;
            lcd_config_set(config);
            break;
        case STATE_CONFIG_CLOCK_MIN:
            {
                timendate_clk_t set_time;
                timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // hours from current clock
                int clk = set_time.hour*100 + numedit_event(NUMEDIT_KEY_UP); // minutes from current editing
                lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_CONFIG_CLOCK_HOUR:
            {
                timendate_clk_t set_time;
                timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // minutes from current clock
                int clk = numedit_event(NUMEDIT_KEY_UP)*100 + set_time.min; // hours from current editing
                lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_CONFIG_LCD_SCROLLING:
            lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE);
            
            // Update LCD scrolling settings
            config = lcd_config_get();
            config.scrolling = (lcd_scrolling_t)numedit_value_get();
            lcd_config_set(config);
            break;
        case STATE_CONFIG_RADIO_CHANNEL:
            lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE);
            break;
        case STATE_CONFIG_RADIO_PANID:
        case STATE_MAIL_COMPOSE_ADDRESS_SET:
            lcd_num_puthex(numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_ZERO);
            break;
        case STATE_CONFIG_UNIT_TEMP:
            avrraven.user_config.unit.temp = TEMP_UNIT_CELCIUS;
            lcd_symbol_clr(LCD_SYMBOL_F);
            lcd_symbol_set(LCD_SYMBOL_C);
            break;
        case STATE_CONFIG_UNIT_CLOCK:
            avrraven.user_config.unit.clock = TIME_CLOCK_UNIT_24;
            if (avrraven.user_config.unit.clock == TIME_CLOCK_UNIT_24) {
                lcd_symbol_clr(LCD_SYMBOL_AM);
                lcd_symbol_clr(LCD_SYMBOL_PM);
                lcd_num_puthex(0x2400, LCD_NUM_PADDING_ZERO);
            } else {
                lcd_symbol_set(LCD_SYMBOL_AM);
                lcd_symbol_set(LCD_SYMBOL_PM);
                lcd_num_puthex(0x1200, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_MAIL_READ:
            mbox_mail_get(&current_mail, MBOX_GET_NEXT);
            if (current_mail != NULL) {
                int_temp = current_mail->size;
                lcd_puta(current_mail->data, int_temp);
                lcd_num_puthex(current_mail->address, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_FW_WAIT_USER_CONFIRMATION:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_AUDIO_FILE_SELECT:
            strncpy_P((char*)search_string, AUDIO_FILE_TYPE, AUDIO_FILE_TYPE_SIZE);
            if (avrraven.status.batt_low == false) {
                sfs_fget(search_string, file_name, SFS_FGET_REV);
                lcd_puts((const char*)file_name);
            } else {
                lcd_puts_P("ERROR");
            }
            break;
        case STATE_STORAGE_FILE_LIST:
            strncpy_P((char*)search_string, "*.*", 4);
            if (avrraven.status.batt_low == false) {
                sfs_fget(search_string, file_name, SFS_FGET_REV);
                lcd_puts((const char*)file_name);
            } else {
                lcd_puts_P("ERROR");
            }
            break;
        default:
            // Key events in unknown state is ignored
            break;
        }
        break;
    case KEY_DOWN:
        switch (avrraven.status.state) {
        case STATE_IDLE:
            new_menu_entry = FMENU_NavigateDown(&MENU_menuHandle);
            break;
        case STATE_CONFIG_DEBUG_ENABLE:
            lcd_puts_P("DISABLE");
            avrraven.user_config.debug_enable = false;
            break;
        case STATE_CONFIG_TXTPREV_ENABLE:
            lcd_puts_P("DISABLE");
            avrraven.user_config.txtmsg_preview = false;
            break;
        case STATE_CONFIG_FW_UPGRADE:
            lcd_puts_P("USR ACK");
            avrraven.user_config.fw_rcv_auto = false;
            break;
        case STATE_CONFIG_CONNECT:
            lcd_puts_P("MANUAL");
            avrraven.user_config.join_auto = false;
            break;
        case STATE_CONFIG_IMG_RCV:
            lcd_puts_P("USR ACK");
            avrraven.user_config.fw_rcv_auto = false;
            break;
        case STATE_MAIL_COMPOSE:
        case STATE_CONFIG_NAME:
            txtedit_event(TXTEDIT_KEY_DOWN);
            break;
        case STATE_CONFIG_LCD_CONTRAST:
            lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE);
            config = lcd_config_get();
            config.contrast = numedit_buffer;
            lcd_config_set(config);
            break;
        case STATE_CONFIG_CLOCK_MIN:
            {
                timendate_clk_t set_time;
                timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // hours from current clock
                int clk = set_time.hour*100 + numedit_event(NUMEDIT_KEY_DOWN); // minutes from current editing
                lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_CONFIG_CLOCK_HOUR:
            {
                timendate_clk_t set_time;
                timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // minutes from current clock
                int clk = numedit_event(NUMEDIT_KEY_DOWN)*100 + set_time.min; // hours from current editing
                lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_CONFIG_LCD_SCROLLING:
            lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE);
            
            // Update LCD scrolling settings
            config = lcd_config_get();
            config.scrolling = (lcd_scrolling_t)numedit_value_get();
            lcd_config_set(config);
            break;
        case STATE_CONFIG_RADIO_CHANNEL:
            lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE);
            break;
        case STATE_CONFIG_RADIO_PANID:
        case STATE_MAIL_COMPOSE_ADDRESS_SET:
            lcd_num_puthex(numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_ZERO);
            break;
        case STATE_CONFIG_UNIT_TEMP:
            avrraven.user_config.unit.temp = TEMP_UNIT_FAHRENHEIT;
            lcd_symbol_clr(LCD_SYMBOL_C);
            lcd_symbol_set(LCD_SYMBOL_F);
            break;
        case STATE_CONFIG_UNIT_CLOCK:
            avrraven.user_config.unit.clock = TIME_CLOCK_UNIT_12;
            if (avrraven.user_config.unit.clock == TIME_CLOCK_UNIT_24) {
                lcd_symbol_clr(LCD_SYMBOL_AM);
                lcd_symbol_clr(LCD_SYMBOL_PM);
                lcd_num_puthex(0x2400, LCD_NUM_PADDING_ZERO);
            } else {
                lcd_symbol_set(LCD_SYMBOL_AM);
                lcd_symbol_set(LCD_SYMBOL_PM);
                lcd_num_puthex(0x1200, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_MAIL_READ:
            mbox_mail_get(&current_mail, MBOX_GET_PREV);
            if (current_mail != NULL) {
                int_temp = current_mail->size;
                lcd_puta(current_mail->data, int_temp);
                lcd_num_puthex(current_mail->address, LCD_NUM_PADDING_ZERO);
            }
            break;
        case STATE_FW_WAIT_USER_CONFIRMATION:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_AUDIO_FILE_SELECT:
            strncpy_P((char*)search_string, AUDIO_FILE_TYPE, AUDIO_FILE_TYPE_SIZE);
            if (avrraven.status.batt_low == false) {
                sfs_fget(search_string, file_name, SFS_FGET_FWD);
                lcd_puts((const char*)file_name);
            } else {
                lcd_puts_P("ERROR");
            }
            break;
        case STATE_STORAGE_FILE_LIST:
            strncpy_P((char*)search_string, "*.*", 4);
            if (avrraven.status.batt_low == false) {
                sfs_fget(search_string, file_name, SFS_FGET_FWD);
                lcd_puts((const char*)file_name);
            } else {
                lcd_puts_P("ERROR");
            }
            break;
        default:
            // Key events in unknown state is ignored
            break;
        }
        break;
    case KEY_LEFT:
        switch (avrraven.status.state) {
        case STATE_IDLE:
            new_menu_entry = FMENU_NavigateLeft(&MENU_menuHandle);
            break;
        case STATE_CONFIG_CLOCK_MIN:
            {    // Set min
                timendate_clk_t new_time;
                timndate_clock_get(&new_time, avrraven.user_config.unit.clock);
                new_time.min = numedit_buffer;
                new_time.sec = 0;
                timndate_clock_set(new_time, avrraven.user_config.unit.clock);
            }
            
            // Done numeric editing on hours
            numedit_done();
            
            // Start numeric editor on hours
            {
                timendate_clk_t current_time;
                timndate_clock_get(&current_time, avrraven.user_config.unit.clock);
                numedit_buffer = current_time.hour;
                numedit_config_t conf = {
                    .number = &numedit_buffer,
                    .min_value = 0,
                    .max_value = 23,
                    .radix = NUMEDIT_RADIX_DEC,
                    .size = 2,
                    .offset = 2
                };
                numedit_init(conf);
            }
            
            avrraven.status.state = STATE_CONFIG_CLOCK_HOUR;
            break;
        case STATE_AUDIO_FILE_SELECT:
            if (audio_playback_active() == true) {
                audio_playback_stop();
            }
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_NAME:
        case STATE_MAIL_COMPOSE:
            txtedit_event(TXTEDIT_KEY_LEFT);
            break;
        case STATE_CONFIG_RADIO_PANID:
        case STATE_MAIL_COMPOSE_ADDRESS_SET:
            lcd_num_puthex(numedit_event(NUMEDIT_KEY_LEFT), LCD_NUM_PADDING_ZERO);
            break;
        case STATE_CONFIG_UNIT_TEMP:
            break;
        case STATE_CONFIG_UNIT_CLOCK:
            break;
/*        case STATE_MAIL_READ:
            mbox_mail_getnext(&txtmsg);
            if (txtmsg != NULL) {
                int_temp = ((txtmsg->size) < LCD_SEGMENT_COUNT) ? txtmsg->size : LCD_SEGMENT_COUNT;
                mail_read_offset = ((mail_read_offset + LCD_SEGMENT_COUNT) >= txtmsg->size) ? mail_read_offset : (mail_read_offset + LCD_SEGMENT_COUNT);
                lcd_puta(&txtmsg->data[mail_read_offset], int_temp);
            }
            break;*/
        case STATE_FW_WAIT_USER_CONFIRMATION:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        default:
            // Key events in unknown state is ignored
            break;
        }
        break;
    case KEY_RIGHT:
        switch (avrraven.status.state) {
        case STATE_IDLE:
            new_menu_entry = FMENU_NavigateRight(&MENU_menuHandle);
            break;
        case STATE_CONFIG_CLOCK_HOUR:
            {    // Set hour
                timendate_clk_t new_time;
                timndate_clock_get(&new_time, avrraven.user_config.unit.clock);
                new_time.hour = numedit_buffer;
                new_time.sec = 0;
                timndate_clock_set(new_time, avrraven.user_config.unit.clock);
            }
            
            // Done numeric editing on hours
            numedit_done();
            
            // Start numeric editor on minutes
            {
                timendate_clk_t current_time;
                timndate_clock_get(&current_time, avrraven.user_config.unit.clock);
                numedit_buffer = current_time.min;
                numedit_config_t conf = {
                    .number = &numedit_buffer,
                    .min_value = 0,
                    .max_value = 59,
                    .radix = NUMEDIT_RADIX_DEC,
                    .size = 2,
                    .offset = 0
                };
                numedit_init(conf);
            }
            
            avrraven.status.state = STATE_CONFIG_CLOCK_MIN;
            break;
        case STATE_MAIL_COMPOSE:
        case STATE_CONFIG_NAME:
            txtedit_event(TXTEDIT_KEY_RIGHT);
            break;
        case STATE_CONFIG_RADIO_PANID:
        case STATE_MAIL_COMPOSE_ADDRESS_SET:
            lcd_num_puthex(numedit_event(NUMEDIT_KEY_RIGHT), LCD_NUM_PADDING_ZERO);
            break;
        case STATE_CONFIG_UNIT_TEMP:
            break;
        case STATE_CONFIG_UNIT_CLOCK:
            break;
        case STATE_FW_WAIT_USER_CONFIRMATION:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        default:
            // Key events in unknown state is ignored
            break;
        }
        break;
    case KEY_ENTER:
        switch (avrraven.status.state) {
        case STATE_DISPLAY_MESSAGE:
            // Default display avrraven.status.state
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            led_status_set(LED_OFF);
            lcd_num_clr_all();
            
            // Refresh menu function (in case it affects the display)
            menu_action = MENU_ACTION_REFRESH;
            if (current_menu_entry->action != NULL) {
                current_menu_entry->action((void*)&menu_action);
            }
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_LCD_CONTRAST:
            // Done numeric editing, write value to user configuration
            numedit_done();
            avrraven.user_config.lcd.contrast = (lcd_contrast_t)numedit_buffer;
            
            // Update LCD HW 
            config = lcd_config_get();
            config.contrast = avrraven.user_config.lcd.contrast;
            lcd_config_set(config);
            
            // Write new user configuration to EEPROM
            USER_CONFIG_STORE();
            
            // Refresh menu title
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_LCD_SCROLLING:
            // Done numeric editing, write value to user configuration
            avrraven.user_config.lcd.scrolling = (lcd_scrolling_t)numedit_value_get();
            numedit_done();
            
            // Update LCD scrolling settings
            config = lcd_config_get();
            config.scrolling = avrraven.user_config.lcd.scrolling;
            lcd_config_set(config);
            
            // Write new user configuration to EEPROM
            USER_CONFIG_STORE();
            
            // Refresh menu title
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_RADIO_CHANNEL:
            // Done numeric editing, write value to user configuration
            avrraven.user_config.channel = numedit_value_get();
            numedit_done();
            
            // Write new user configuration to EEPROM
            USER_CONFIG_STORE();
            
            // Refresh menu title
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_CLOCK_HOUR:
            {    // Set hour
                timendate_clk_t new_time;
                timndate_clock_get(&new_time, avrraven.user_config.unit.clock);
                new_time.hour = numedit_value_get();
                new_time.sec = 0;
                timndate_clock_set(new_time, avrraven.user_config.unit.clock);
            }
            
            // Done numeric editing on hours
            numedit_done();
            
            // Start show clock event
            menu_action = MENU_ACTION_REFRESH;
            if (current_menu_entry->action != NULL) {
                current_menu_entry->action((void*)&menu_action);
            }
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_CLOCK_MIN:
            {    // Set min
                timendate_clk_t new_time;
                timndate_clock_get(&new_time, avrraven.user_config.unit.clock);
                new_time.min = numedit_value_get();
                new_time.sec = 0;
                timndate_clock_set(new_time, avrraven.user_config.unit.clock);
            }
            
            // Done numeric editing on minutes
            numedit_done();
            
            // Start show clock event
            menu_action = MENU_ACTION_REFRESH;
            if (current_menu_entry->action != NULL) {
                current_menu_entry->action((void*)&menu_action);
            }
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_DEBUG_ENABLE:
            // Write new user configuration to EEPROM
            USER_CONFIG_STORE();
            
            // Refresh menu title
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_RADIO_PANID:
            // Done numeric editing on hours
            numedit_done();
            
            // Write new user configuration to EEPROM
            USER_CONFIG_STORE();
            
            // Refresh menu title
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_UNIT_TEMP:
        case STATE_CONFIG_UNIT_CLOCK:
        case STATE_CONFIG_TXTPREV_ENABLE:
        case STATE_CONFIG_FW_UPGRADE:
        case STATE_CONFIG_CONNECT:
        case STATE_CONFIG_IMG_RCV:
            // Write new user configuration to EEPROM
            USER_CONFIG_STORE();
            
            // Refresh menu title
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_MAIL_PREVIEW:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            menu_action = MENU_ACTION_REFRESH;
            if (current_menu_entry->action != NULL) {
                current_menu_entry->action((void*)&menu_action);
            }
            led_status_set(LED_OFF);
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_AUDIO_FILE_SELECT:
            if (audio_playback_active() == false) {
                audio_playback_start(file_name, false);
            } else {
                audio_playback_stop();
            }
            break;
        case STATE_STORAGE_FILE_LIST:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_FW_WAIT_USER_CONFIRMATION:
            avrraven.status.state = STATE_FW_WRITE_INIT;
            break;
        case STATE_IDLE:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            if (current_menu_entry->action != NULL) {
                current_menu_entry->action((void*)&menu_action);
            }
            break;
        case STATE_AUDIO_RECORD:
            audio_record_stop();
            lcd_symbol_clr(LCD_SYMBOL_MIC);
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_CONFIG_NAME:
            txtedit_event(TXTEDIT_KEY_ENTER);
            txtedit_done();
            USER_CONFIG_STORE();
            // Print the menu title to the display
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_MAIL_READ:
            lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry));
            // If any unread mail, show closed envelope
            if (mbox_unread() == true) {
                lcd_symbol_set(LCD_SYMBOL_ENV_MAIN);
                lcd_symbol_set(LCD_SYMBOL_ENV_CL);
                lcd_symbol_clr(LCD_SYMBOL_ENV_OP);
            // If all mail read, show open envelope
            } else {
                lcd_symbol_set(LCD_SYMBOL_ENV_MAIN);
                lcd_symbol_set(LCD_SYMBOL_ENV_CL);
                lcd_symbol_set(LCD_SYMBOL_ENV_OP);
            }
            // show number of mails on display
            int_temp = mbox_mail_count_get();
            lcd_num_putdec(int_temp, LCD_NUM_PADDING_SPACE);
            mbox_close();
            avrraven.status.state = STATE_IDLE;
            break;
        case STATE_MAIL_COMPOSE:
            txtedit_event(TXTEDIT_KEY_ENTER);
            txtedit_done();
            mbox_mail_buffer_put(new_mail_buffer);
            {
                lcd_puts_P("ADDRESS");
                    numedit_config_t conf = {
                        .number = &numedit_buffer,
                        .min_value = 0,
                        .max_value = UINT16_MAX,
                        .radix = NUMEDIT_RADIX_DEC,
                        .size = 1,
                        .offset = 0
                    };
                numedit_init(conf);
            }
            numedit_buffer = 0x0000; // default address
            lcd_num_puthex(numedit_buffer, LCD_NUM_PADDING_ZERO);
            avrraven.status.state = STATE_MAIL_COMPOSE_ADDRESS_SET;
            break;
        case STATE_MAIL_COMPOSE_ADDRESS_SET:
            avrraven.status.trans_seq_nmbr = mbox_mail_send(numedit_value_get(), txtedit_size_get());
            avrraven.status.state = STATE_MAIL_SEND_INIT;
            numedit_done();
            mbox_close();
            break;
        default:
            lcd_puts_P("CANCELED");
            led_status_set(LED_FAST_BLINK);
            lcd_num_clr_all();
            avrraven.status.state = STATE_DISPLAY_MESSAGE;
            break;
        }
        break;
    case KEY_NO_KEY:
        // Do nothing?
        break;
    default:
            // Key events in unknown state is ignored
        break;
    }
    
    // Navigate menu if new menu entry is different from last
    if (new_menu_entry != current_menu_entry) {
        navigate_menu(current_menu_entry, new_menu_entry, menu_action);
    }
    
    // After processing the key event it is safe to enable auto key
    auto_key_state = key_state;
    if (key_state != KEY_NO_KEY) {
        if (auto_key_registered == false) {
            long delay;
            if (auto_key_wait == true) {
                delay = 300;
                auto_key_wait = false;
            } else {
                asy_tmr_put(auto_key_timer);
                delay = 80;
                auto_key_registered = true;
            }
            auto_key_timer = asy_tmr_get(int_evt_key, (void*)&auto_key_state, delay);
        }
    } else {
        asy_tmr_put(auto_key_timer);
        auto_key_wait = true;
        auto_key_registered = false;
    }
}

void int_evt_check_key(void* evt)
{
    static bool first_time = true;          // Static variable used as flag to indicate first execution of function
    static key_state_t last_key_state;      // Variable hodling last value of the joystick. Used to detect changes in joystick state
    
    /* Check joystick state. Post event if any change since last
     * First time function is executed no event is posted. This is
     * done to not respond if joystick activated while booting
     */
    key_state_t new_key_state;
    if (first_time) {
        last_key_state = key_state_get();
        new_key_state = last_key_state;
        first_time = false;
    } else if((new_key_state = key_state_get()) != last_key_state){
        last_key_state = new_key_state;
        vrt_post_event(int_evt_key, (void*)&last_key_state);
    }
}

void int_evt_lcd_shift_left(void* evt)
{
    lcd_text_shift_left();
}

void int_evt_lcd_cursor_toggle(void* evt)
{
    lcd_cursor_toggle();
}

void int_evt_lcd_num_refresh(void* evt)
{
    lcd_num_refresh();
}

void int_evt_update_batt(void* evt)
{
    int16_t vcc_batt = battery_voltage_read();
    
    lcd_symbol_battery_empty();
    if (vcc_batt>2000) {
        lcd_symbol_set(LCD_SYMBOL_BAT_CAP1);
    }
    if (vcc_batt>2500) {
        lcd_symbol_set(LCD_SYMBOL_BAT_CAP2);
    }
    if (vcc_batt>2800) {
        lcd_symbol_set(LCD_SYMBOL_BAT_CAP3);
    }
    
    // Indicate low battery if voltage less than 2.6 V
    if (avrraven.status.batt_low == false) {
        if (vcc_batt<2600) {
            avrraven.status.batt_low = true;
            lcd_symbol_set(LCD_SYMBOL_ATT);
            mbox_deinit();
            sfs_deinit();
        }
    }
}

void int_evt_show_clock(void* evt)
{
    static bool col = false;
    timendate_clk_t clk;
    timndate_clock_get(&clk, avrraven.user_config.unit.clock);
    int16_t display_clock = clk.hour*100 + clk.min;
    lcd_num_putdec(display_clock, LCD_NUM_PADDING_ZERO);
    if ((col = !col) == true){
        lcd_symbol_set(LCD_SYMBOL_COL);
    } else {
        lcd_symbol_clr(LCD_SYMBOL_COL);
    }
}

void int_evt_toggle_num_digit(void* evt)
{
    int8_t digit_mask = *(int8_t*)evt;
    lcd_num_enable(digit_mask);
}

void int_evt_audio(void* evt)
{
    audio_event_handler();
}
Exemple #15
0
int main(int argc, char *argv[]) {

	int mb = mbox_open();

	/* Enable QPU for execution */
	int qpu_enabled = !qpu_enable(mb, 1);
	if (!qpu_enabled) {
		printf("Unable to enable QPU.  Check your firmware is latest.");
		goto cleanup;
	}

	/* Allocate GPU memory and map it into ARM address space */
	unsigned size = 4096;
	unsigned align = 4096;
    	unsigned handle = mem_alloc(mb, size, align, GPU_MEM_FLG);
	if (!handle) {
		printf("Failed to allocate GPU memory.");
		goto cleanup;
	}
	void *gpu_pointer = (void *)mem_lock(mb, handle);
	void *arm_pointer = mapmem((unsigned)gpu_pointer+GPU_MEM_MAP, size);

	unsigned *p = (unsigned *)arm_pointer;

	/*
	   +---------------+ <----+
	   |  QPU Code     |      |
	   |  ...          |      |
	   +---------------+ <--+ |
	   |  Uniforms     |    | |
	   +---------------+    | |
	   |  QPU0 Uniform -----+ |
	   |  QPU0 Start   -------+
	   |  ...                 |
	   |  QPUn Uniform        |
	   |  QPUn PC      -------+
	   +---------------+
	*/

	/* Copy QPU program into GPU memory */
	unsigned *qpu_code = p;
	memcpy(p, program, sizeof program);
	p += (sizeof program)/(sizeof program[0]);

	/* Build Uniforms */
	unsigned *qpu_uniform = p;
	*p++ = 1;
	
	/* Build QPU Launch messages */
	unsigned *qpu_msg = p;
	*p++ = as_gpu_address(qpu_uniform);
	*p++ = as_gpu_address(qpu_code);

	int i;
	for (i=0; i<16+1+2; i++) {
		printf("%08x: %08x\n", gpu_pointer+i*4, ((unsigned *)arm_pointer)[i]);
	}
	printf("qpu exec %08x\n", gpu_pointer + ((void *)qpu_msg - arm_pointer));

	/* Launch QPU program and block till its done */
    	unsigned r = execute_qpu(mb, GPU_QPUS, as_gpu_address(qpu_msg), 1, 10000);
	printf("%d\n", r);

cleanup:
	/* Release GPU memory */
	if (arm_pointer) {
		unmapmem(arm_pointer, size);
	}
    	if (handle) {
		mem_unlock(mb, handle);
    		mem_free(mb, handle);
	}
	
	/* Release QPU */
	if (qpu_enabled) {
	    	qpu_enable(mb, 0);
	}
	
	/* Release mailbox */
	mbox_close(mb);

}
Exemple #16
0
void main (int argc, char *argv[])
{
  char h2_buffer[H2_SIZE];
  char o2_buffer[O2_SIZE];
  char so2_buffer[SO2_SIZE];

  char h2so4_molecule[H2SO4_SIZE] = {'H', '2', 'S', 'O', '4'};

  mbox_t h_mbox_h2;
  mbox_t h_mbox_o2;
  mbox_t h_mbox_so2;
  mbox_t h_mbox_h2so4;

  sem_t s_procs_completed; // Semaphore to signal the original process that we're done

  /* int ct; */
  /* Printf("argc = %d\n", argc); */
  /* for(ct = 0 ; ct < argc; ct++){ */
  /*   Printf("argv[%d] = %s\n", ct, argv[ct]); */
  /* } */

  if (argc != 6) { 
    Printf("Usage: %s <mailbox h2> <mailbox o2> <mailbox so2> <mailbox h2so4> <handle_to_page_mapped_semaphore>\n"); 
    Exit();
  } 

  // Convert the command-line strings into integers for use as handles
  h_mbox_h2 = dstrtol(argv[1], NULL, 10); // The "10" means base 10
  h_mbox_o2 = dstrtol(argv[2], NULL, 10); // The "10" means base 10
  h_mbox_so2 = dstrtol(argv[3], NULL, 10); // The "10" means base 10
  h_mbox_h2so4 = dstrtol(argv[4], NULL, 10); // The "10" means base 10


  s_procs_completed = dstrtol(argv[5], NULL, 10);

  // Open the h2 mailbox
  if (mbox_open(h_mbox_h2) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not open the so4 mailbox!\n", getpid());
    Exit();
  }

  // Wait for the h2 molecule from the mailbox
  if (mbox_recv(h_mbox_h2, H2_SIZE, (void *) h2_buffer) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not receive message from the mbox %d!\n", getpid(), h_mbox_h2);
    Exit();
  }

  // Close the h2 mailbox
  if (mbox_close(h_mbox_h2) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }


  // Open the o2 mailbox
  if (mbox_open(h_mbox_o2) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not open the o2 mailbox!\n", getpid());
    Exit();
  }
  

  // Send the o2 to the o2 mailbox
  if (mbox_recv(h_mbox_o2, O2_SIZE, (void *) o2_buffer) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_o2);
    Exit();
  }

  // Close the o2 mailbox
  if (mbox_close(h_mbox_o2) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }


  // Open the SO2 mailbox
  if (mbox_open(h_mbox_so2) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not open the so2 mailbox!\n", getpid());
    Exit();
  }

  // Send the SO2 to the SO2 mailbox
  if (mbox_recv(h_mbox_so2, SO2_SIZE, (void *) so2_buffer) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_so2);
    Exit();
  }

  // Close the SO2 mailbox
  if (mbox_close(h_mbox_so2) == MBOX_FAIL) {
    Printf("Reaction 2 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }

    // Open the h2so4 mailbox
  if (mbox_open(h_mbox_h2so4) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not open the h2so4 mailbox!\n", getpid());
    Exit();
  }
  

  // Send the h2so4 to the o2 mailbox
  if (mbox_send(h_mbox_h2so4, H2SO4_SIZE, (void *) h2so4_molecule) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_h2so4);
    Exit();
  }

  // Close the h2so4 mailbox
  if (mbox_close(h_mbox_h2so4) == MBOX_FAIL) {
    Printf("Reaction 3 (%d): Could not close the mailbox!\n", getpid());
    Exit();
  }



  // Now print a message to show that everything worked
  Printf("A molecule H2SO4 has been generated\n");

  // Signal the semaphore to tell the original process that we're done
  if(sem_signal(s_procs_completed) != SYNC_SUCCESS) {
    Printf("Reaction 3 (%d): Bad semaphore s_procs_completed (%d)!\n", getpid(), s_procs_completed);
    Exit();
  }

  Printf("Reaction 3 (%d): Done!\n", getpid());
}