예제 #1
0
/*This routine is the HNIC. It determines when all the subroutines run.
Messing with business in here can have lethal consequences for many things, particularly 
related to timing.	What needs to run when is one of the greatest challenges of this design.
*/
int main(void)
{
	
	
	MIDI_MESSAGE mm_incoming_message;
	MIDI_MESSAGE *p_mm_incoming_message = &mm_incoming_message;

	p_global_setting = &global_setting;//assign the pointer to point at the global_setting structure

	static unsigned char uc_aux_task_state;//keep track of auxilliary task state - filter, lfo, envelope


	cli();//disable interrupts
  	sys_init();
	sei();//enable interrupts

	initialize_pots(p_global_setting);

	/*Initialize global_settings.
	This routine sets some important initial values. Without them, some of the subroutines
	can be confused because they are expecting certain 0 points that indicate some function is
	not active.*/
	global_setting.auc_synth_params[ADSR_SUSTAIN] = 92;
	global_setting.auc_synth_params[ADSR_LENGTH] = 127;
	decode_adsr_length(p_global_setting, 127);
	global_setting.auc_synth_params[ADSR_DECAY] = 127;
	global_setting.auc_synth_params[ADSR_RELEASE] = 127;
	global_setting.auc_ad_values[PITCH_SHIFT] = 127;
	global_setting.auc_synth_params[PITCH_SHIFT] = 127;
	global_setting.auc_parameter_source[PITCH_SHIFT] = SOURCE_AD;
	global_setting.auc_ad_values[AMPLITUDE] = 192;
	global_setting.auc_synth_params[AMPLITUDE] = 255;//set amplitude
	global_setting.auc_parameter_source[AMPLITUDE] = SOURCE_AD;
	global_setting.uc_adsr_multiplier = ADSR_MIN_VALUE;//Initialize the ADSR to its minimum value
	global_setting.auc_synth_params[PORTAMENTO] = 0;
	global_setting.auc_synth_params[FILTER_ENV_AMT] = 128;
	global_setting.auc_synth_params[OSC_MIX] = 127;
	global_setting.auc_synth_params[OSC_2_WAVESHAPE] = SQUARE;

  for (; ;)
  { 
  	RESET_WATCHDOG;

	/*Has the slow interrupt occurred?*/
	if(1 == g_uc_slow_interrupt_flag)
	{

		//Calculate the adsr envelope value
		adsr(p_global_setting);

		//Set the amplitude of the Voltage-Controlled Amplifier
		set_amplitude(p_global_setting);
		
		if(g_un_switch_debounce_timer > 0)
		{
			g_un_switch_debounce_timer--;
		}
		else if(g_uc_ext_int_0_flag ==  TRUE)
		{
			led_switch_handler(p_global_setting, TACT_LFO_SHAPE);
			g_uc_ext_int_0_flag = FALSE;
			CLEAR_EXT_INTERRUPTS;
			ENABLE_EXT_INT_0;
		}
		else if(g_uc_ext_int_1_flag == TRUE)
		{
			led_switch_handler(p_global_setting, TACT_LFO_DEST);
			g_uc_ext_int_1_flag = FALSE;
			CLEAR_EXT_INTERRUPTS
			ENABLE_EXT_INT_1;
		}

		//Let's handle midi messages.
		//We have to check the receive uart.
		//If there is data in the uart receive buffer, check to see
		//if the incoming fifo has anything in it.  If it doesn't have midi messages
		//waiting to be handled, send it to the incoming midi handler routine. 
		//If there is stuff in the incoming midi fifo, put the new message next in the fifo.
		if(uart_rx_buffer_has_byte())
		{
			handle_incoming_midi_byte(uart_get_byte());
		}

		/*auxilliary tasks
		These tasks are handled one at a time, each time through the slow interrupt routine
		We have to do them one at a time because we can't do them all every time through the loop
		because we don't have enough clock cycles, nor do we really need to do them that way
		They are contained in a state machine
		The number of things to do here affects the timing of them.  Adding more things to do will affect timing
		Just think about it a minute before you do anything crazy like that, but if you must and if you want the 
		envelopes and LFOs to work at specific frequency then 
		you'll have to go through each of the things below
		*/
		switch(uc_aux_task_state)
		{
			case AUX_TASK_SPI:
			/*The SPI is shared by the i/o expanders and the digital pots of the 
			filter. These tasks are mutually exclusive though, only one at a time.*/

			    spi();

				uc_aux_task_state = AUX_TASK_READ_AD;				

			break;

			case AUX_TASK_READ_AD:

				if(!CHECK_BIT(ADCSRA, ADSC))
				{
						read_ad(p_global_setting);
						g_uc_ad_ready_flag = 0;
				}
				
				uc_aux_task_state = AUX_TASK_CALC_PITCH;	

			break;

			case AUX_TASK_CALC_PITCH:

				calculate_pitch(p_global_setting);
				uc_aux_task_state = AUX_TASK_LFO;

			break;
	
			case AUX_TASK_LFO:
				
				lfo(p_global_setting);				
				uc_aux_task_state = AUX_TASK_MIDI;

			break;

			case AUX_TASK_MIDI:
					
				//If there are midi messages in the incoming message fifo, handle them.
				if(g_uc_midi_messages_in_incoming_fifo > 0)
				{
					get_midi_message_from_incoming_fifo(p_mm_incoming_message);
					midi_interpret_incoming_message(p_mm_incoming_message, p_global_setting);
				}
				
				uc_aux_task_state = AUX_TASK_SPI;

			break;

			default:

			break;


			}//Case statement end

		//clear the slow interrupt flag
		g_uc_slow_interrupt_flag = 0;
	}
	
	
  }//for Loop end

  return 0;
  }
예제 #2
0
/*
 * ISR context
 * uart_rx_cb() will be called when UART rx interrupt assert,
 * then we should featch data from HW FIFO quickly.
 * fucntion: fetch data from HW FIFO to rx ring buffer
 * we should use uart_get_byte(&ch) to fetch byte from HW FIFO as quickly as possible
 */
void uart_rx_cb(void)
{
    uint16   roomleft = 0;
    PKT_FIFO     *infor;
    PKT_FIFO     *temp_info;
    uint8        ch = 0;

    PKT_DESC     *rx_desc = &(UARTPort.Rx_desc);
    BUFFER_INFO  *rx_ring = &(UARTPort.Rx_Buffer);

    static uint8  ATMatchNum = 0;
    static uint8  IWMatchNum = 0;

    /*
     * MCU only forward uart rx data to air
     * here,copy to rx ring and return
     */
#if (UARTRX_TO_AIR_LEVEL == 2)
    if (iot_uart_rx_mode == UARTRX_PUREDATA_MODE) {
        while (uart_get_byte(&ch)) {
            Buf_Push(rx_ring,ch);
        }
        return;
    }
#endif

    /*
     * MCU should collect data to be packet
     */
    //normal case
    Buf_GetRoomLeft(rx_ring,roomleft);

    while (uart_get_byte(&ch)) {
        //new receive begin,detect packet header at first
        switch (rx_desc->cur_type)   {
            case PKT_UNKNOWN: {
                /**************** detect packet type ***************/
                //support more ATcmd prefix analysis
                /*case 1:AT#*/
                if (ATCmdPrefixAT[ATMatchNum] == ch) {
                    ATMatchNum++;
                } else {
                    ATMatchNum = 0;
                }
                /*case 2:iwpriv ra0*/
                if (ATCmdPrefixIW[IWMatchNum] == ch) {
                    IWMatchNum++;
                } else {
                    IWMatchNum = 0;
                }

                if ((ATMatchNum == sizeof(ATCmdPrefixAT)-1) || //match case 1: AT#
                    (IWMatchNum == sizeof(ATCmdPrefixIW)-1)) {  //match case 2:iwpriv ra0
                    rx_desc->cur_num = rx_desc->pkt_num;
                    infor = &(rx_desc->infor[rx_desc->cur_num]);
                    infor->pkt_len = 0;

                    if (ATMatchNum == sizeof(ATCmdPrefixAT)-1) {
                        rx_desc->cur_type = PKT_ATCMD;             //match case 1: AT#
                    } else if (IWMatchNum == sizeof(ATCmdPrefixIW)-1) {
                        rx_desc->cur_type = PKT_IWCMD;             //match case 2:iwpriv ra0
                    }

                    ATMatchNum = 0;
                    IWMatchNum = 0;
                    continue;
                }
            }
            break;

            case PKT_ATCMD:
            case PKT_IWCMD: {
                infor = &(rx_desc->infor[rx_desc->cur_num]);

                /*received one complete packet*/
                if (ch == '\n' || ch == '\r')  {
                    //if task has consumed some packets
                    if (rx_desc->cur_num != rx_desc->pkt_num) {
                        temp_info = infor;
                        infor     = &(rx_desc->infor[rx_desc->pkt_num]);
                        infor->pkt_len = temp_info->pkt_len;
                        temp_info->pkt_len = 0;
                        temp_info->pkt_type = PKT_UNKNOWN;
                    }

                    infor->pkt_type = rx_desc->cur_type;  // PKT_ATCMD / PKT_IWCMD;
                    rx_desc->pkt_num++;
                    rx_desc->cur_type = PKT_UNKNOWN;
                } else {
                    /*continue to receiving packet */
                    Buf_Push(rx_ring,ch);
                    roomleft--;
                    infor->pkt_len++;
                }

                /*
                 * if overflow,we discard the current packet
                 * example1:packet length > ring size
                 * example2:rx ring buff can no be freed by task as quickly as rx interrupt coming
                 */
                if ((!roomleft) || (rx_desc->pkt_num >= NUM_DESCS)) {
                    //rollback
                    Buff_RollBack(rx_ring,infor->pkt_len);

                    roomleft += infor->pkt_len;

                    infor->pkt_type = PKT_UNKNOWN;
                    infor->pkt_len = 0;
                    rx_desc->cur_type = PKT_UNKNOWN;

                    if (rx_desc->pkt_num >= NUM_DESCS) {
                        rx_desc->pkt_num--;
                    }
                }
            }
            break;
            default:
                break;
        }
    }
}
예제 #3
0
파일: roomba.c 프로젝트: calemcnulty/csc460
void Roomba_UpdateSensorPacket(ROOMBA_SENSOR_GROUP group, roomba_sensor_data_t* sensor_packet)
{
	// No, I don't feel bad about manual loop unrolling.
	uart_putchar(SENSORS);
	uart_putchar(group);
	switch(group)
	{
	case EXTERNAL:
		// environment sensors
		while (uart_bytes_received() != 10);
		sensor_packet->bumps_wheeldrops = uart_get_byte(0);
		sensor_packet->wall = uart_get_byte(1);
		sensor_packet->cliff_left = uart_get_byte(2);
		sensor_packet->cliff_front_left = uart_get_byte(3);
		sensor_packet->cliff_front_right = uart_get_byte(4);
		sensor_packet->cliff_right = uart_get_byte(5);
		sensor_packet->virtual_wall = uart_get_byte(6);
		sensor_packet->motor_overcurrents = uart_get_byte(7);
		sensor_packet->dirt_left = uart_get_byte(8);
		sensor_packet->dirt_right = uart_get_byte(9);
		break;
	case CHASSIS:
		// chassis sensors
		while (uart_bytes_received() != 6);
		sensor_packet->remote_opcode = uart_get_byte(0);
		sensor_packet->buttons = uart_get_byte(1);
		sensor_packet->distance.bytes.high_byte = uart_get_byte(2);
		sensor_packet->distance.bytes.low_byte = uart_get_byte(3);
		sensor_packet->angle.bytes.high_byte = uart_get_byte(4);
		sensor_packet->angle.bytes.low_byte = uart_get_byte(5);
		break;
	case INTERNAL:
		// internal sensors
		while (uart_bytes_received() != 10);
		sensor_packet->charging_state = uart_get_byte(0);
		sensor_packet->voltage.bytes.high_byte = uart_get_byte(1);
		sensor_packet->voltage.bytes.low_byte = uart_get_byte(2);
		sensor_packet->current.bytes.high_byte = uart_get_byte(3);
		sensor_packet->current.bytes.low_byte = uart_get_byte(4);
		sensor_packet->temperature = uart_get_byte(5);
		sensor_packet->charge.bytes.high_byte = uart_get_byte(6);
		sensor_packet->charge.bytes.low_byte = uart_get_byte(7);
		sensor_packet->capacity.bytes.high_byte = uart_get_byte(8);
		sensor_packet->capacity.bytes.low_byte = uart_get_byte(9);
		break;
	}
	uart_reset_receive();
}