int main(int argument_count, char **arguments)
{
	DM7820_Board_Descriptor *board;
	DM7820_Error dm7820_status;
	int status;
	struct option options[] = {
		{"help", 0, 0, 1},
		{"minor", 1, 0, 2},
		{0, 0, 0, 0}
	};
	uint32_t values_read;
	uint32_t values_written;
	uint8_t fifo_empty;
	uint8_t fifo_full;
	uint8_t fifo_status;
	uint8_t help_option = 0x00;
	uint8_t minor_option = 0x00;
	unsigned long int minor_number = 0;

	program_name = arguments[0];

	fprintf(stdout, "\n");
	fprintf(stdout, "\tDM7820 FIFO PCI Request Example Program\n");
	fprintf(stdout, "\n");

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   Process command line options
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	while (1) {

		/*
		 * Parse the next command line option and any arguments it may require
		 */

		status = getopt_long(argument_count,
				     arguments, "", options, NULL);

		/*
		 * If getopt_long() returned -1, then all options have been processed
		 */

		if (status == -1) {
			break;
		}

		/*
		 * Figure out what getopt_long() found
		 */

		switch (status) {

			/*#################################################################
			   User entered '--help'
			   ################################################################# */

		case 1:

			/*
			 * Refuse to accept duplicate '--help' options
			 */

			if (help_option) {
				error(0, 0, "ERROR: Duplicate option '--help'");
				usage();
			}

			/*
			 * '--help' option has been seen
			 */

			help_option = 0xFF;
			break;

			/*#################################################################
			   User entered '--minor'
			   ################################################################# */

		case 2:{
				char *invalid_char_p;

				/*
				 * Refuse to accept duplicate '--minor' options
				 */

				if (minor_option) {
					error(0, 0,
					      "ERROR: Duplicate option '--minor'");
					usage();
				}

				/*
				 * Convert option argument string to unsigned long integer
				 */

				errno = 0;

				minor_number =
				    strtoul(optarg, &invalid_char_p, 10);

				/*
				 * Catch unsigned long int overflow
				 */

				if ((minor_number == ULONG_MAX)
				    && (errno == ERANGE)) {
					error(0, 0,
					      "ERROR: Device minor number caused numeric overflow");
					usage();
				}

				/*
				 * Catch argument strings with valid decimal prefixes, for
				 * example "1q", and argument strings which cannot be converted,
				 * for example "abc1"
				 */

				if ((*invalid_char_p != '\0')
				    || (invalid_char_p == optarg)) {
					error(0, 0,
					      "ERROR: Non-decimal device minor number");
					usage();
				}

				/*
				 * '--minor' option has been seen
				 */

				minor_option = 0xFF;
				break;
			}

			/*#################################################################
			   User entered unsupported option
			   ################################################################# */

		case '?':
			usage();
			break;

			/*#################################################################
			   getopt_long() returned unexpected value
			   ################################################################# */

		default:
			error(EXIT_FAILURE,
			      0,
			      "ERROR: getopt_long() returned unexpected value %#x",
			      status);
			break;
		}
	}

	/*
	 * Recognize '--help' option before any others
	 */

	if (help_option) {
		usage();
	}

	/*
	 * '--minor' option must be given
	 */

	if (minor_option == 0x00) {
		error(0, 0, "ERROR: Option '--minor' is required");
		usage();
	}

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   Device initialization
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	fprintf(stdout, "Opening device with minor number %lu ...\n",
		minor_number);

	dm7820_status = DM7820_General_Open_Board(minor_number, &board);
	DM7820_Return_Status(dm7820_status, "DM7820_General_Open_Board()");

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   FIFO generic initialization
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	/*
	 * Disable all FIFOs to put them into a known state
	 */

	fprintf(stdout, "Disabling FIFOs ...\n");

	fprintf(stdout, "    FIFO 0 ...\n");

	dm7820_status = DM7820_FIFO_Enable(board, DM7820_FIFO_QUEUE_0, 0x00);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Enable()");

	fprintf(stdout, "    FIFO 1 ...\n");

	dm7820_status = DM7820_FIFO_Enable(board, DM7820_FIFO_QUEUE_1, 0x00);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Enable()");

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   FIFO 0 initialization
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	fprintf(stdout, "Initializing FIFO 0 ...\n");

	/*
	 * Set input clock to PCI write to FIFO 0 Read/Write Port Register
	 */

	fprintf(stdout, "    Setting input clock ...\n");

	dm7820_status =
	    DM7820_FIFO_Set_Input_Clock(board, DM7820_FIFO_QUEUE_0,
					DM7820_FIFO_INPUT_CLOCK_PCI_WRITE);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Set_Input_Clock()");

	/*
	 * Set output clock to PCI read from FIFO 0 Read/Write Port Register
	 */

	fprintf(stdout, "    Setting output clock ...\n");

	dm7820_status =
	    DM7820_FIFO_Set_Output_Clock(board, DM7820_FIFO_QUEUE_0,
					 DM7820_FIFO_OUTPUT_CLOCK_PCI_READ);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Set_Output_Clock()");

	/*
	 * Set data input to PCI data
	 */

	fprintf(stdout, "    Setting data input ...\n");

	dm7820_status =
	    DM7820_FIFO_Set_Data_Input(board, DM7820_FIFO_QUEUE_0,
				       DM7820_FIFO_0_DATA_INPUT_PCI_DATA);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Set_Data_Input()");

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   Secondary FIFO 0 initialization
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	fprintf(stdout, "Enabling FIFO 0 ...\n");

	dm7820_status = DM7820_FIFO_Enable(board, DM7820_FIFO_QUEUE_0, 0xFF);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Enable()");

	/*
	 * Clear FIFO status empty flag without checking its state
	 */

	fprintf(stdout, "Clearing FIFO 0 status empty flag ...\n");

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_EMPTY,
			&fifo_status);

	/*
	 * Clear FIFO status full flag without checking its state
	 */

	fprintf(stdout, "Clearing FIFO 0 status full flag ...\n");

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_FULL,
			&fifo_status);

	/*
	 * Clear FIFO status overflow flag without checking its state
	 */

	fprintf(stdout, "Clearing FIFO 0 status overflow flag ...\n");

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_OVERFLOW,
			&fifo_status);

	/*
	 * Clear FIFO status underflow flag without checking its state
	 */

	fprintf(stdout, "Clearing FIFO 0 status underflow flag ...\n");

	get_fifo_status(board, DM7820_FIFO_QUEUE_0,
			DM7820_FIFO_STATUS_UNDERFLOW, &fifo_status);

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   Fill FIFO 0 by writing values to it via the PCI bus
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	fprintf(stdout, "Filling FIFO 0 via PCI bus ...\n");

	/*#########################################################################
	   Write initialization
	   ######################################################################### */

	values_written = 0;

	/*#########################################################################
	   Determine initial FIFO status
	   ######################################################################### */

	/*
	 * FIFO should be empty
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_EMPTY,
			&fifo_status);

	if (!fifo_status) {
		error(EXIT_FAILURE, 0, "ERROR: FIFO is not empty");
	}

	/*
	 * FIFO should not have overflowed
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_OVERFLOW,
			&fifo_status);

	if (fifo_status) {
		error(EXIT_FAILURE, 0, "ERROR: FIFO has overflowed");
	}

	/*
	 * FIFO should not have underflowed
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0,
			DM7820_FIFO_STATUS_UNDERFLOW, &fifo_status);

	if (fifo_status) {
		error(EXIT_FAILURE, 0, "ERROR: FIFO has underflowed");
	}

	/*
	 * Determine whether or not FIFO is full
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_FULL,
			&fifo_full);

	/*#########################################################################
	   Write values to FIFO
	   ######################################################################### */

	while (!fifo_full) {

		/*
		 * Write value to FIFO which can be easily recalculated on read so that
		 * values written can be verified
		 */

		dm7820_status =
		    DM7820_FIFO_Write(board, DM7820_FIFO_QUEUE_0,
				      (values_written % MODULUS_DIVISOR)
		    );
		DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Write()");

		/*
		 * Another value written successfully
		 */

		values_written++;

		/*
		 * Don't let program loop infinitely if something goes wrong
		 */

		if (values_written > EXPECTED_FIFO_ELEMENTS) {
			error(EXIT_FAILURE, 0,
			      "ERROR: Too many values written to FIFO");
		}

		/*
		 * Print progress information to inform user program is working
		 */

		fprintf(stdout, "    %u\r", values_written);

		/*
		 * FIFO should not be empty
		 */

		get_fifo_status(board, DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_EMPTY, &fifo_status);

		if (fifo_status) {
			error(EXIT_FAILURE, 0, "ERROR: FIFO is empty");
		}

		/*
		 * FIFO should not have overflowed
		 */

		get_fifo_status(board,
				DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_OVERFLOW, &fifo_status);

		if (fifo_status) {
			error(EXIT_FAILURE, 0, "ERROR: FIFO has overflowed");
		}

		/*
		 * FIFO should not have underflowed
		 */

		get_fifo_status(board,
				DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_UNDERFLOW, &fifo_status);

		if (fifo_status) {
			error(EXIT_FAILURE, 0, "ERROR: FIFO has underflowed");
		}

		/*
		 * Determine whether or not FIFO is full
		 */

		get_fifo_status(board, DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_FULL, &fifo_full);
	}

	fprintf(stdout, "\n");

	/*
	 * Verify that expected number of values were written to FIFO
	 */

	fprintf(stdout, "%u values written to FIFO\n", values_written);

	if (values_written != EXPECTED_FIFO_ELEMENTS) {
		error(EXIT_FAILURE, 0,
		      "ERROR: Unexpected number of values written");
	}

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   Empty FIFO 0 by reading values from it via the PCI bus
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	fprintf(stdout, "Emptying FIFO 0 via PCI bus ...\n");

	/*#########################################################################
	   Read initialization
	   ######################################################################### */

	values_read = 0;

	/*#########################################################################
	   Determine FIFO status
	   ######################################################################### */

	/*
	 * FIFO should be full
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_FULL,
			&fifo_status);

	if (!fifo_status) {
		error(EXIT_FAILURE, 0, "ERROR: FIFO is not full");
	}

	/*
	 * FIFO should not have overflowed
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_OVERFLOW,
			&fifo_status);

	if (fifo_status) {
		error(EXIT_FAILURE, 0, "ERROR: FIFO has overflowed");
	}

	/*
	 * FIFO should not have underflowed
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0,
			DM7820_FIFO_STATUS_UNDERFLOW, &fifo_status);

	if (fifo_status) {
		error(EXIT_FAILURE, 0, "ERROR: FIFO has underflowed");
	}

	/*
	 * Determine whether or not FIFO is empty
	 */

	get_fifo_status(board, DM7820_FIFO_QUEUE_0, DM7820_FIFO_STATUS_EMPTY,
			&fifo_empty);

	/*#########################################################################
	   Read values from FIFO
	   ######################################################################### */

	while (!fifo_empty) {
		uint16_t fifo_value;

		/*
		 * Read value from FIFO and verify that it matches the value written
		 */

		dm7820_status =
		    DM7820_FIFO_Read(board, DM7820_FIFO_QUEUE_0, &fifo_value);
		DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Read()");

		if (fifo_value != (values_read % MODULUS_DIVISOR)) {
			error(EXIT_FAILURE, 0,
			      "ERROR: Incorrect value read from FIFO");
		}

		/*
		 * Another value read successfully
		 */

		values_read++;

		/*
		 * Don't let program loop infinitely if something goes wrong
		 */

		if (values_read > EXPECTED_FIFO_ELEMENTS) {
			error(EXIT_FAILURE, 0,
			      "ERROR: Too many values read from FIFO");
		}

		/*
		 * Print progress information to inform user program is working
		 */

		fprintf(stdout, "    %u\r", values_read);

		/*
		 * FIFO should not be full
		 */

		get_fifo_status(board, DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_FULL, &fifo_status);

		if (fifo_status) {
			error(EXIT_FAILURE, 0, "ERROR: FIFO is full");
		}

		/*
		 * FIFO should not have overflowed
		 */

		get_fifo_status(board,
				DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_OVERFLOW, &fifo_status);

		if (fifo_status) {
			error(EXIT_FAILURE, 0, "ERROR: FIFO has overflowed");
		}

		/*
		 * FIFO should not have underflowed
		 */

		get_fifo_status(board,
				DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_UNDERFLOW, &fifo_status);

		if (fifo_status) {
			error(EXIT_FAILURE, 0, "ERROR: FIFO has underflowed");
		}

		/*
		 * Determine whether or not FIFO is empty
		 */

		get_fifo_status(board, DM7820_FIFO_QUEUE_0,
				DM7820_FIFO_STATUS_EMPTY, &fifo_empty);
	}

	fprintf(stdout, "\n");

	/*
	 * Verify that expected number of values were read from FIFO
	 */

	fprintf(stdout, "%u values read from FIFO\n", values_read);

	if (values_read != EXPECTED_FIFO_ELEMENTS) {
		error(EXIT_FAILURE, 0,
		      "ERROR: Unexpected number of values read");
	}

	/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	   Final processing before exit
	   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */

	fprintf(stdout, "Disabling FIFO 0 ...\n");

	dm7820_status = DM7820_FIFO_Enable(board, DM7820_FIFO_QUEUE_0, 0x00);
	DM7820_Return_Status(dm7820_status, "DM7820_FIFO_Enable()");

	fprintf(stdout, "Closing device ...\n");

	dm7820_status = DM7820_General_Close_Board(board);
	DM7820_Return_Status(dm7820_status, "DM7820_General_Close_Board()");

	fprintf(stdout, "\n");
	fprintf(stdout, "Successful end of example program.\n");

	exit(EXIT_SUCCESS);
}
bool NRF24L01p::tx_fifo_empty() {
    return get_fifo_status() & (1 << FIFO_STATUS_TX_EMPTY);
}