|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Did you know...
|
Serial Wombat Remote Control Channel ModeThe Serial Wombat can monitor key presses from a Sony Compatible Remote Control by using the timer interrupt functionality. Because of this, only pins 33 through 40 can be used for Remote Control mode. The Remote control mode requries a full 256 bytes be used for input storage. The Serial Wombat decodes the signal at a high level, and expects an input from a demodulator such as this one, which turns the modulated carrier signal into a logic output. The timer interrupt functionality should be configured before configuring a pin for Remote mode. It is suggested that the interrupt be configured for at least 10,000Hz (.1ms) sampling. This allows 6 samples of the shortest pulse in the Sony protocol, which is 600us long. The Remote mode has a number of options:
Message format:Message 200 is used to initialize the Pin mode. This should be sent after the timer interrupt has been configured.
Message 201 is used to put the Remote Control pin mode into queueuing mode. This should be sent (if desired) after message 200 and after the queue has been initialized.
Example:Configure pin 33 to Remote Control mode. Set up the timer interrupt to read once every 100us, and not output values to output pins. Put individual key presses into a 32 byte queue at 0x200 (remember that the timer interrupt uses the first 0x200 bytes). Don't display device ID. Polarity is active negative. 128 0x0200 32 0 0x55 0x55 0x55 ; Configure a 32 byte RAM queue at address 0x200 97 25 1 0xFCE6 255 0 0x55 ;Setting Timer
;Interrupt Enable True, 10000 per second, Output Enable: False,
;Memory Usage: 256
200 33 30 0 6 0 0x55 0x55 ; Set Pin 33 to Remote mode
; Polarity Low (0)
; 6 Samples per 600us pulse
; Don't use device ID
201 33 30 0x0200 0 0x55 0x55; Second configuration message, pin 33 to Remote mode
; Queue address 0x0200
; Only queue presses, not packets
Pin Mode Source CodeThe following code is what creates the pin mode for this function inside of the Wombat. You don't need to know this to use the pin mode, but some people find it interesting. See the SDK for some insight into how pin modes work. Hold your mouse over various words and variables for definitions. #ifndef COMPILING_FIRMWARE#include <stdio.h> #endif #include "types.h" #include "utilities.h" #include "global_data.h" #pragma code APPLICATION #pragma romdata APPLICATION_DATA void init_remote(void) { //printf ("Initializing remote\n"); if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_0) { tp.remote.activepolarity = (rxbuffer[3] > 0); tp.remote.bittime = rxbuffer[4]; tp.remote.showdevid = (rxbuffer[5] > 0); tp.remote.lastportbcounter = TMR1_PORTB_counter; tp.remote.count = 0; tp.remote.idle = 0; tp.remote.queuedata = 0; tp.remote.queueall = 0; tp.remote.newdata = 1; vpin_input(); } if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_1) { tp.generic.buffer = RXBUFFER16(3); tp.remote.queueall = rxbuffer[5] > 0; tp.remote.queuedata = 1; tp.remote.count = 0; tp.remote.idle = 0; tp.remote.lastportbcounter = TMR1_PORTB_counter; tp.remote.newdata = 1; vpin_input(); } } void update_remote(void) { #ifdef __18F4620 local_j = current_physical_pin; local_j -= 33; #endif #ifndef COMPILING_FIRMWARE local_j = current_physical_pin; local_j -= 33; #endif //printf("Processing update_remote\n"); tp2.remote.bitfield = uint8_bitfield[local_j]; while (TMR1_PORTB_counter != tp.remote.lastportbcounter) { ++tp.remote.count; tp2.remote.currentvalue = ((PORTB_READ_AREA[tp.remote.lastportbcounter] & tp2.remote.bitfield) > 0); if (tp.remote.activepolarity == 0) { tp2.remote.currentvalue = !tp2.remote.currentvalue; } if (tp2.remote.currentvalue == tp.remote.lastvalue) { //printf("Current %d Matches Previous %d at %d\n", tp2.remote.currentvalue, tp.remote.lastvalue,tp.remote.lastportbcounter); if (!tp2.remote.currentvalue) { //inactive if (!tp.remote.idle ) { local_j = 4 * tp.remote.bittime; if (tp.remote.count > local_j) { //printf("Reporting data 0x%4X at %d\n",tp.remote.data,tp.remote.lastportbcounter); tp.remote.data >>= 4; if (!tp.remote.showdevid) { tp.remote.data &= 0x007F; } if (tp.remote.queuedata) { if (tp.remote.queueall || tp.remote.newdata) { queue_address = tp.generic.buffer; if (tp.remote.showdevid) { //printf ("Queueing %X with dev id\n",tp.remote.data); push_word(tp.remote.data); } else { //printf ("Queueing %Xwithout dev id\n",tp.remote.data); push_byte (tp.remote.data); } } } else { tp.generic.buffer = tp.remote.data; } tp.remote.idle = 1; tp.remote.newdata = 0; } } else { local_temp16_1.u = tp.remote.bittime * ((uint16)100); if (tp.remote.count > local_temp16_1.u && tp.remote.data != 0xFFFF) { queue_address = tp.generic.buffer; if (tp.remote.queuedata) { if (tp.remote.queueall) { if (tp.remote.showdevid) { push_word(0xFFFF); } else { push_byte(0xFF); } } } else { tp.generic.buffer = 0xFFFF; } tp.remote.data = 0xFFFF;^M tp.remote.newdata = 1; } } } else { //Active. Do nothing till transition } } else { //printf("Current %d Differs Previous %d at %d, count of %d \n", tp2.remote.currentvalue, tp.remote.lastvalue,tp.remote.lastportbcounter,tp.remote.count); if (tp2.remote.currentvalue) { //Just went active // TODO: Verify bit time } else { // Just Went inactive // Process bit. tp2.remote.halfbit = tp.remote.bittime; tp2.remote.halfbit >>= 1; tp2.remote.threshold = tp.remote.bittime; tp2.remote.threshold += tp2.remote.halfbit; tp2.remote.start = tp.remote.bittime * 4; if (tp.remote.count < tp2.remote.halfbit) { //probably noise. tp.remote.idle = 1; //printf ("Active time was too short\n"); } else if (tp.remote.count < tp2.remote.threshold) { if (!tp.remote.idle) { //Got a 0 tp.remote.data >>= 1; //printf ("Found a 0 \n"); } } else if (tp.remote.count < (3* tp.remote.bittime)) { if (!tp.remote.idle) { // Got a 1 tp.remote.data >>= 1; tp.remote.data |= 0x8000; //printf ("Found a 1 \n"); } } else if (tp.remote.count < (5 * tp.remote.bittime)) { //if (tp.remote.idle) //{ // // Got a start frame // tp.remote.idle = 0; //} //else //{ // //Unexpected start frame // tp.remote.idle = 1; //} //Above translates to an invert tp.remote.idle = !tp.remote.idle; tp.remote.data = 0; //printf("Found a start frame. Idle is %d\n",tp.remote.idle); } else { //unacceptably long pulse tp.remote.idle = 1; //printf("Found a too long pulse\n"); } } tp.remote.count = 0; tp.remote.lastvalue = tp2.remote.currentvalue; } ++tp.remote.lastportbcounter; } executive_settings.buffer_dirty = 1; } #ifndef COMPILING_FIRMWARE #ifdef TEST_REMOTE static void print_user_data(uint8 bit, uint8 next_data); static uint8 set_start(uint16 offset, uint16 count, uint8 bit, uint8 active_state); static uint8 set_bit(uint8 data, uint16 offset, uint16 count, uint8 bit, uint8 active_state); static void print_user_data(uint8 bit, uint8 next_data); static uint8 set_idle(uint16 offset, uint8 bit, uint8 active_state); int main(void) { int i; uint8 c; uint8 next_address; uint16 output = 0x05AA; uint16 output_counter; uint8 pin = 33; system_init(); for (i = 0; i < 256 ; ++i) { user_buffer[i] = 0xFF; } TMR1_PORTB_counter_max = 255; TMR1_PORTB_counter = 0; rxbuffer[0] = 128; //Initialize queue rxbuffer[1] = 0x01; rxbuffer[2] = 0x00; rxbuffer[3] = 0x00; rxbuffer[4] = 0x10; process_rxbuffer(); rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0; rxbuffer[1] = pin; rxbuffer[2] = PIN_MODE_REMOTE; rxbuffer[3] = 0; //Active 0 rxbuffer[4] = 6; // bit time 6 rxbuffer[5] = 0; // No device ID rxbuffer[6] = 0x55; rxbuffer[7] = 0x55 ; process_rxbuffer(); rxbuffer[0] = CONFIGURE_CHANNEL_MODE_1; rxbuffer[1] = pin; rxbuffer[2] = PIN_MODE_REMOTE; rxbuffer[3] = 0x01; // Queue address 0x0100 rxbuffer[4] = 0; rxbuffer[5] = 0x1 ; // Queue all rxbuffer[6] = 0x55; rxbuffer[7] = 0x55 ; process_rxbuffer(); next_address = set_start(27, 6, 0, 0); for (output_counter = 0; output_counter < 12; ++ output_counter) { if (output & 0x01) { next_address = set_bit(1, next_address, 6, 0, 0); } else { next_address = set_bit(0, next_address, 6, 0, 0); } output >>= 1; print_user_data(0,next_address); TMR1_PORTB_counter = next_address; process_pins(); } next_address = set_idle(next_address,0,0); print_user_data(0,next_address); TMR1_PORTB_counter = next_address; process_pins(); printf ("Public data was: %04X\n",get_buffer(map_pin(pin))); queue_address = 0x100; if (shift_byte(&c) != QUEUE_BYTE_SHIFTED) { printf("No Byte Received. Expected 2A\n"); return (1); } if (c == 0) { if (shift_byte(&c) != QUEUE_BYTE_SHIFTED) { printf("No Byte Received (2). Expected 2A\n"); return (1); } } if (c != 0x2A) { printf("Wrong Byte Received. Expected 2A, got %X\n",c); return(1); } return(0); } static uint8 set_idle(uint16 offset, uint8 bit, uint8 active_state) { int i = 0; //Start for (i = 0; i < 256; ++i) { if (!active_state) { user_buffer[i] |= (0x01<<bit); } else { user_buffer[i] &= ~(0x01 << bit); } } return (offset + 255); } static uint8 set_start(uint16 offset, uint16 count, uint8 bit, uint8 active_state) { int i = 0; uint8 buffercounter = offset; //Start for (i = 0; i < count * 4; ++i) { if (active_state) { user_buffer[buffercounter] |= (0x01<<bit); } else { user_buffer[buffercounter] &= ~(0x01 << bit); } ++buffercounter; } for (i=0; i < count; ++i) { if (!active_state) { user_buffer[buffercounter] |= (0x01<<bit); } else { user_buffer[buffercounter] &= ~(0x01 << bit); } ++buffercounter; } return buffercounter; } static uint8 set_bit(uint8 data, uint16 offset, uint16 count, uint8 bit, uint8 active_state) { int i = 0; int numofbits = 0; uint8 buffercounter = offset; if (data & 0x01) { numofbits = 2 * count; } else { numofbits = count; } for (i = 0; i < numofbits; ++i) { if (active_state) { user_buffer[buffercounter] |= (0x01<<bit); } else { user_buffer[buffercounter] &= ~(0x01 << bit); } ++buffercounter; } for (i = 0; i < count; ++i) { if (!active_state) { user_buffer[buffercounter] |= (0x01<<bit); } else { user_buffer[buffercounter] &= ~(0x01 << bit); } ++buffercounter; } return (buffercounter); } static void print_user_data(uint8 bit, uint8 next_data) { int i; for (i = 0; i < 256; ++i) { if ((i % 16) == 0) { printf("\n%3d",i); } if (user_buffer[i] & (0x01<<bit)) { printf("#"); } else { printf("."); } } printf("\n"); printf(" Next value is: %d\n",next_data); } #endif #endif |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Copyright Wombat Interface Products, 2005-2008. All Rights Reserved.