Example #1
0
void main()
{
	bool keyboard_report_ready = false;
	bool consumer_report_ready = false;

	uint8_t prev_keycode = KC_NO;
	
	__xdata uint8_t recv_buffer[RECV_BUFF_SIZE];
	__xdata uint8_t bytes_received;
	
	P0DIR = 0x00;	// all outputs
	P0ALT = 0x00;	// all GPIO default behavior
	
	LED_off();

	usbInit();
	//dbgInit();
	
	rf_dngl_init();

	reset_keyboard_report();
	
	for (;;)
	{
		usbPoll();	// handles USB interrupts
		//dbgPoll();	// send chars from the uart TX buffer
		
		// try to read the recv buffer
		bytes_received = rf_dngl_recv(recv_buffer, RECV_BUFF_SIZE);

		if (bytes_received)
		{
			// we have new data, so what is it?
			if (recv_buffer[0] == MT_KEY_STATE)
			{
				process_key_state_msg(recv_buffer, bytes_received);

				consumer_report_ready = true;
				keyboard_report_ready = true;
			} else if (recv_buffer[0] == MT_TEXT) {
				process_text_msg(recv_buffer, bytes_received);
			}
		}

		if (!keyboard_report_ready  &&  !msg_empty())
		{
			// get the next char from the stored text message
			uint8_t c = msg_peek();
			uint8_t new_keycode = get_keycode_for_char(c);

			reset_keyboard_report();

			// if the keycode is different than the previous
			// otherwise just send an empty report to simulate key went up
			if (new_keycode != prev_keycode  ||  new_keycode == KC_NO)
			{
				usb_keyboard_report.keys[0] = new_keycode;
				usb_keyboard_report.modifiers = get_modifiers_for_char(c);
				
				msg_pop();	// remove char from the buffer
			} else {
				new_keycode = KC_NO;
			}
			
			keyboard_report_ready = true;
			
			prev_keycode = new_keycode;		// remember for later
		}
		
		// send the report if the endpoint is not busy
		if ((in1cs & 0x02) == 0   &&   (keyboard_report_ready  ||  usbHasIdleElapsed()))
		{
			// copy the keyboard report into the endpoint buffer
			in1buf[0] = usb_keyboard_report.modifiers;
			in1buf[1] = 0;
			in1buf[2] = usb_keyboard_report.keys[0];
			in1buf[3] = usb_keyboard_report.keys[1];
			in1buf[4] = usb_keyboard_report.keys[2];
			in1buf[5] = usb_keyboard_report.keys[3];
			in1buf[6] = usb_keyboard_report.keys[4];
			in1buf[7] = usb_keyboard_report.keys[5];

			// send the data on it's way
			in1bc = 8;
			
			keyboard_report_ready = false;
		}

		// send the consumer report if the endpoint is not busy
		if ((in2cs & 0x02) == 0   &&   (consumer_report_ready  ||  usbHasIdleElapsed()))
		{
			in2buf[0] = usb_consumer_report;
			in2bc = 1;
		
			consumer_report_ready = false;
		}
	}
}
Example #2
0
// Called when a packet is received
void comms_ReceivedPacket(unsigned char* packet) {
    // packet is 64 bytes

    //NOTE: If transferring multiple packets,
    // it might pay to temporarily reduce the task interval.

    SetTxErrorCode(ERR_OK);

    switch (packet[0]) {

        ////////// Basic System Commands //////////

        case CMD_PING:
            break;

        case CMD_RESET:
            Reset(); // Causes immediate reset of the MCU
            break;

        case CMD_SET_LED:
            comms_set_led(packet[1], packet[2]);
            break;

        ////////// Diagnostics //////////

        case CMD_GET_BATTERY_INFO:
        {
            battery_info_t* tx_packet = (battery_info_t*)tx_buffer;

            // power_monitor.h
            tx_packet->level = battery_level;
            tx_packet->voltage = battery_voltage;
            tx_packet->charge_status = charge_status;
            tx_packet->power_status = power_status;
            tx_packet->battery_status = battery_status;
            tx_packet->bq25010_status = bq25010_status;

            break;
        }

        case CMD_GET_CPU_INFO:
        {
            cpu_info_t* tx_packet = (cpu_info_t*)tx_buffer;

            // systick.h
            tx_packet->systick = systick;

            break;
        }

        case CMD_GET_NEXT_MESSAGE:
        {
            message_packet_t* tx_packet = (message_packet_t*)tx_buffer;

            if (!msg_isempty()) {
                msg_pop(tx_packet->message);
                tx_packet->len = strlen(tx_packet->message);
            } else {
                tx_packet->len = 0;
            }

            break;
        }

        ////////// Display Interface //////////

        case CMD_QUERY_DISPLAY:
        {
            display_query_t* tx_packet = (display_query_t*)tx_buffer;

            // gfx.h
            tx_packet->width = DISPLAY_WIDTH;
            tx_packet->height = DISPLAY_HEIGHT;
            tx_packet->bpp = DISPLAY_BPP;

            tx_packet->display_on = display_power;

            break;
        }

        case CMD_SET_DISPLAY_POWER:
        {
            bool on = packet[1];
            if (on)
                ssd1351_DisplayOn();
            else
                ssd1351_DisplayOff();

            break;
        }

        case CMD_DISPLAY_LOCK:
        {
            lock_display = true;
            break;
        }

        case CMD_DISPLAY_UNLOCK:
        {
            lock_display = false;
            break;
        }

        case CMD_DISPLAY_WRITEBUF:
        {
            //TODO: Will require multiple RX packets
            SetTxErrorCode(ERR_NOT_IMPLEMENTED);
            break;
        }

        case CMD_DISPLAY_READBUF:
        {
            display_chunk_t* request = (display_chunk_t*)packet;
            display_chunk_t* chunk = (display_chunk_t*)tx_buffer;

            // Make sure the display has a full frame first
            if (display_frame_ready) {
                chunk->state = 1;
                
                // Send the next chunk
                chunk->offset = request->offset;
                ReadScreenBuffer(chunk->buf, request->offset, DISP_CHUNK_SIZE);

            } else {
                chunk->state = 0;
            }

            //comms_read_display_buf(tx_packet);
            break;
        }

        ////////// Sensors //////////

        case CMD_QUERY_SENSORS:
        {
            sensor_query_t* tx_packet = (sensor_query_t*)tx_buffer;

            tx_packet->count = 0;
            //TODO: Dynamically populate with known system sensors
            SetTxErrorCode(ERR_NOT_IMPLEMENTED);
            break;
        }

        case CMD_SET_SENSOR_ENABLE:
        {
            uint16 index = packet[1];

            // TODO: Enable/disable the specified sensor/
            // may already be enabled by the system,
            // and may be re-enabled by the system as required.
            SetTxErrorCode(ERR_NOT_IMPLEMENTED);
            break;
        }

        case CMD_GET_SENSOR_DATA:
        {
            uint16 index = packet[1];

            // TODO: Return the data for the specified sensor index.
            // Won't return the data until the sensor has been updated,
            // will return 0 if the sensor is currently disabled.
            SetTxErrorCode(ERR_NOT_IMPLEMENTED);
            break;
        }

        ////////// Time & Date //////////

        case CMD_GET_DATETIME:
        {
            datetime_packet_t* tx_packet = (datetime_packet_t*)tx_buffer;
            timestamp_t ts = ClockNow();

            tx_packet->hour = ts.hour;
            tx_packet->minute = ts.min;
            tx_packet->second = ts.sec;

            tx_packet->day_of_week = ts.dow;
            tx_packet->day = ts.day;
            tx_packet->month = ts.month;
            tx_packet->year = ts.year;
            break;
        }

        case CMD_SET_DATETIME:
        {
            datetime_packet_t* rx_packet = (datetime_packet_t*)packet;

            ClockSetTime(
                rx_packet->hour,
                rx_packet->minute,
                rx_packet->second
            );

            ClockSetDate(
                rx_packet->day_of_week,
                rx_packet->day,
                rx_packet->month,
                rx_packet->year
            );
            break;
        }

        ////////// Calendar //////////
        
        case CMD_CLEAR_CALENDAR:
        {
            CalendarClear();
            break;
        }

        case CMD_ADD_CALENDAR_EVT:
        {
            calendar_event_packet_t* rx_packet = (calendar_event_packet_t*)packet;
            event_t event;

            event.event_type = rx_packet->event_type;

            strncpy(event.label, rx_packet->label, MAX_LABEL_LEN);
            strncpy(event.location, rx_packet->location, MAX_LOCATION_LEN);

            event.color = rx_packet->color;

            // Timetable events
            event.dow = rx_packet->dow;
            event.hr = rx_packet->hr;
            event.min = rx_packet->min;

            if (CalendarAddEvent(&event) == NULL) {
                SetTxErrorCode(ERR_OUT_OF_RAM);
                break;
            }

            break;
        }

        case CMD_GET_CALENDAR_INFO:
        {
            calendar_info_packet_t* tx_packet = (calendar_info_packet_t*)tx_buffer;
            tx_packet->num_events = CalendarGetNumEvents();
            break;
        }

        case CMD_GET_CALENDAR_EVT:
        {
            calendar_event_packet_t* rx_packet = (calendar_event_packet_t*)packet;
            calendar_event_packet_t* tx_packet  = (calendar_event_packet_t*)tx_buffer;

            int16 index = rx_packet->index;
            event_t* event = CalendarGetEvent(index);

            if (event == NULL) {
                SetTxErrorCode(ERR_INVALID_INDEX);
                break;
            }

            tx_packet->index = index;
            tx_packet->event_type = event->event_type;

            strncpy(tx_packet->label, event->label, MAX_LABEL_LEN);
            strncpy(tx_packet->location, event->location, MAX_LOCATION_LEN);

            tx_packet->color = event->color;

            tx_packet->dow = event->dow;
            tx_packet->hr = event->hr;
            tx_packet->min = event->min;

            break;
        }


        default:
            return; // Don't send any response
    }

    tx_buffer[0] = packet[0]; // Set command field
    USBSendPacket(tx_buffer);
}