Files

150 lines
5.7 KiB
C

#include "tux.h"
#include "serial.h"
#include "tux-mtcp.h"
#define TC_SERIAL_PORT COM1
// Initialization sequence of Tux Controller
#define TC_INITIALIZATION_SEQUENCE_LEN 2
const unsigned char tc_initialization_sequence[TC_INITIALIZATION_SEQUENCE_LEN] = {
MTCP_BIOC_ON, // Enable button interrupt
MTCP_LED_USR // Set LED content to accept user-defined content
};
// Length of LED control sequence
#define TC_LED_SEQUENCE_LEN 6
#define TC_LED_COUNT 4
#define TC_LED_OFFSET (TC_LED_SEQUENCE_LEN - TC_LED_COUNT)
uint8_t tc_led_sequence[TC_LED_SEQUENCE_LEN] = {MTCP_LED_SET, 0x0F, 0, 0, 0, 0};
// Variable used to hold state of buttons
uint8_t tc_buttons = 0;
/* tc_led_segments: segment information for Tux Controller LED,
* maps 0-9 & A-Z to LED segment packet.
* Tux Controller segment to packet bit mapping:
* +--7--+
* 5 | | 1
* +--3--+
* 6 | | 2
* +--0--+ dot(4)
* Hand calculated, you can calculate again to verify this
*/
const uint8_t tc_led_segments[] = {
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
0xe7, 0x6, 0xcb, 0x8f, 0x2e, 0xad, 0xed, 0x86, 0xef, 0xaf,
// A, B, C, D, E, F, G, H, I, J
0xee, 0x6d, 0x49, 0x4f, 0xe9, 0xe8, 0xe5, 0x6e, 0x6, 0x47,
// K, L, M, N, O, P, Q, R, S, T
0x6e, 0x61, 0xe6, 0x4c, 0xe7, 0xea, 0xae, 0xee, 0xad, 0x69,
// U, V, W, X, Y, Z
0x45, 0x67, 0x67, 0x6e, 0x2f, 0xcb
};
/* int8_t tux_init()
* @output: SUCCESS / FAIL
* @description: Initializes Tux Controller.
*/
int8_t tux_init() {
if(SERIAL_OP_SUCCESS != serial_init(TC_SERIAL_PORT, TC_SERIAL_BAUDRATE)) return TUX_OP_FAIL;
cli();
int i;
for(i = 0; i < TC_INITIALIZATION_SEQUENCE_LEN; i++) {
if(SERIAL_OP_SUCCESS != serial_write(TC_SERIAL_PORT, tc_initialization_sequence[i])) {
sti();
return TUX_OP_FAIL;
}
}
for(i = 0; i < TC_LED_SEQUENCE_LEN; i++) {
if(SERIAL_OP_SUCCESS != serial_write(TC_SERIAL_PORT, tc_led_sequence[i])) {
sti();
return TUX_OP_FAIL;
}
}
sti();
return TUX_OP_SUCCESS;
}
/* int8_t tux_set_led(char* word, uint8_t dot)
* @input: word - 4 character word to be displayed on LED
* dot - the least 4 bits record whether dots on LEDs will be on
* @output: SUCCESS / FAIL
* @description: Changes the content on display of Tux Controller.
*/
int8_t tux_set_led(char* word, uint8_t dot) {
int i;
char ch;
for(i = 0; i < TC_LED_COUNT; i++) {
ch = word[TC_LED_COUNT - i - 1];
// Convert character to LED segment layout
if(ch >= '0' && ch <= '9') {
tc_led_sequence[TC_LED_OFFSET + i] = tc_led_segments[(int) (ch - '0')];
} else if(ch >= 'A' && ch <= 'Z') {
tc_led_sequence[TC_LED_OFFSET + i] = tc_led_segments[(int) (ch - 'A' + 10)];
} else if(ch >= 'a' && ch <= 'z') {
tc_led_sequence[TC_LED_OFFSET + i] = tc_led_segments[(int) (ch - 'a' + 10)];
} else {
return TUX_OP_FAIL;
}
// If dot is enabled, set bit 4 for the layout, as described above
if(dot & (1 << i)) {
tc_led_sequence[TC_LED_OFFSET + i] |= 0x10;
}
}
// Send the sequence to Tux Controller
for(i = 0; i < TC_LED_SEQUENCE_LEN; i++) {
if(SERIAL_OP_SUCCESS != serial_write(TC_SERIAL_PORT, tc_led_sequence[i])) {
return TUX_OP_FAIL;
}
}
return TUX_OP_SUCCESS;
}
/* void tux_interrupt(char packet)
* @input: packet - new packet received, by the serial handler.
* tux_packet_buf - buffer of packets, holds up to 3,
* used for handling button press events.
* @output: tc_buttons - updated to reflect button state
* tux_packet_buf - a new packet inserted
* Tux may get re-initialized if MTCP_RESET received
* @description: Tux Controller interrupt handler.
*/
#define TUX_PACKET_BUF_LEN 3
char tux_packet_buf[TUX_PACKET_BUF_LEN] = {0, 0, 0};
void tux_interrupt(char packet) {
// Move forward buf for handling button events
// As we only cache 3 chars, we just use the simple way
// of copying 3 times to implement a ring buffer.
tux_packet_buf[0] = tux_packet_buf[1];
tux_packet_buf[1] = tux_packet_buf[2];
tux_packet_buf[2] = packet;
// Check if the packet is the last of button event if:
// - first packet is MTCP_BIOC_EVENT
// - 2nd and 3rd packets' most significant bit is 1
// See mp2-tux.pdf provided in mp2 for more info.
if(tux_packet_buf[0] == MTCP_BIOC_EVENT
&& tux_packet_buf[1] & 0x80
&& tux_packet_buf[2] & 0x80) {
// This packet is part of the 3 packets of button event
tc_buttons = 0x00 // Placeholder, make the code look cleaner
| (tux_packet_buf[1] & 0x0F) // Start, A, B, C button, bit 0-3 of pkt 1
| ((tux_packet_buf[2] & 0x09) << 4) // Up, Right button, bit 0, 3 of pkt 2
| ((tux_packet_buf[2] & 0x02) << 5) // Left button, bit 1 of pkt 2
| ((tux_packet_buf[2] & 0x04) << 3);// Down button, bit 2 of pkt 2
tc_buttons = ~tc_buttons; // Flip the states for specs compliance
} else if(tux_packet_buf[2] == MTCP_RESET) {
// Tux reseted, resend initialization sequence & led sequence
int i;
for(i = 0; i < TC_INITIALIZATION_SEQUENCE_LEN; i++) {
if(SERIAL_OP_SUCCESS != serial_write(TC_SERIAL_PORT, tc_initialization_sequence[i])) {
return;
}
}
for(i = 0; i < TC_LED_SEQUENCE_LEN; i++) {
if(SERIAL_OP_SUCCESS != serial_write(TC_SERIAL_PORT, tc_led_sequence[i])) {
return;
}
}
}
}