[Removed]
[Removed]
Hi,
I've just in the process of interfacing a unmodified chatpad to a Pic24 Micro using the same Cliff Biffle details as you have and came across this thread while searching for any details on how to turn the Orange, Green, Capslock and people Leds on.
I have the keyboard working and sending keycodes back.
The main thing is That as Cliff says there are 2 messages you need to send to the controller.
At startup you need to send a InitMessage (87 02 8C 1F CC), but don't send it too quickly after power up, i currently wait 500ms after power up, 100ms is too quick, i've yet to work out exactly how long you need to wait.
This will start the chatpad sending status messages but after a while they will stop coming.
You need to send a second message to the chatpad to start receiving keycodes, the KeepAwakeMessage (87 02 8C 1B D0).
Again, you need a delay between the init message and this one, if you them too close together the second message will be ignored and you will only get status messages.
At the moment i have another 500ms after i send InitMessage before i send the first KeepAwakeMessage
KeepAwakeMessage needs to be sent at regular intervals or the chatpad will go back to sleep.
I send KeepAwakeMessage every second.
Then, the keypress messages are as Cliff says, starting with B4 C5
I don't think the 37 hex you have highlighted in your original hex dump is part of a keypress message as its surrounded by 0's
The B4 C5 on the bottom line could be the start of one but then it's missing the checksum.
The backlight should come on whenever you press a key, i'm not certain if it comes on when it's first initalised as it's at work in a bright office.
I have created a full keycode array including the shifted, Green and Orange keys if you need it later.
If you get it working could you do me a favour and log the data from the Xbox controller to the Chatpad when you press the Orange, Green and Shift keys.
I'm after the commands for turning the these keys leds on and off.
I don't have an Xbox to log the data from and you seem to have the setup already.
Many thanks,
Jim
[Removed]
Mine was a brand new one from about a month ago, though i don't know how long it had been in stock.
I've not cracked it open to see whats inside.
I also have a Chinese copy of the Chatpad which doesn't work at all with the same code, though, that might have been something to do with connecting the power up reversed to the connector initially ............
That is totally different inside and doesn't have backlight keys.
I'm happy to share the C code i have if it's any help.
Jim
[Removed]
// This Chatpad code is based on examples and data from Cliff L. Biffle http://cliffle.com/project/chatpad
// but greatly modified and converted to PIC C
#define CHATPAD_KEY_NOT_PRESSED 0 // not pressed
#define CHATPAD_KEY_PRESSED 1 // pressed, not processed
#define CHATPAD_KEY_PROCESSED 2 // waiting for release
#define CHATPAD_RX_TIMEOUT 2 // timeout for RX byte in 10ms intervals.
#define CHATPAD_SHIFT_MASK 0b00000001
#define CHATPAD_GREEN_MASK 0b00000010
#define CHATPAD_ORANGE_MASK 0b00000100
#define CHATPAD_PEOPLE_MASK 0b00001000
#define CHATPAD_CAPS_LOCK_MASK 0b00000101
#define CHATPAD_MODIFIERS_MASK 0b00001111
int8 ChatPadRxBuffer[8];
int8 ChatPadTxBuffer[5];
#define CHATPAD_TX_BUFFER_SIZE sizeof(ChatPadTxBuffer)
int8 ChatPadRxBufferPointer=0;
int8 ChatPadTxBufferPointer=0;
int8 ChatPadRxTimer = CHATPAD_RX_TIMEOUT;
int1 ChatPadKeepAwakeFlag=FALSE;
int1 ChatPadTxBufferEmpty=TRUE;
int8 ChatPadKeyPressedState=CHATPAD_KEY_NOT_PRESSED;
int8 ChatPadKey=0;
// Normal, shifted, Green, orange
const char KeyList[] = {
'7', '7', '7', '7', /* 11 Key7 */
'6', '6', '6', '6', /* 12 Key6 */
'5', '5', '5', '5', /* 13 Key5 */
'4', '4', '4', '4', /* 14 Key4 */
'3', '3', '3', '3', /* 15 Key3 */
'2', '2', '2', '2', /* 16 Key2 */
'1', '1', '1', '1', /* 17 Key1 */
0, 0, 0, 0, /* 18 Unused */
'u', 'U', '&', 0, /* 21 KeyU */
'y', 'Y', '^', 0, /* 22 KeyY */
't', 'T', '%', 0, /* 23 KeyT */
'r', 'R', '#', '
I've not included the interrupt driven TX and RX code as that's quite PIC specific but it just sends what is in ChatPadTxBuffer and fills ChatPadRxBuffer.
ChatPadProcessMsg is run from the RX interrupt when the buffer is full and puts a valid key valid into ChatPadKey and sets ChatPadKeyPressedState to CHATPAD_KEY_PRESSED so the main program knows to process it.
AwakeChatpad() is run every second from a flag ChatPadKeepAwakeFlag set in a timer interrupt, the timer is initalised to 1 second at the moment so the first run of AwakeChatpad() is 500ms after InitChatpad()
Sorry about the poor formatting, it's not cutting and pasting too well.
Hopefully it makes some sense.
Jim
, /* 24 KeyR /
'e', 'E', 0, 0, / 25 KeyE /
'w', 'W', '@', 0, / 26 KeyW /
'q', 'Q', '!', 0, / 27 KeyQ /
0, 0, 0, 0, / 28 Unused */
'j', 'J', ''', '"', /* 31 KeyJ /
'h', 'H', '/', '\',/ 32 KeyH /
'g', 'G', 0, 0, / 33 KeyG /
'f', 'F', '}', '£', / 34 KeyF /
'd', 'D', '{', 0, / 35 KeyD /
's', 'S', 0, 0, / 36 KeyS /
'a', 'A', '~', 0, / 37 KeyA /
0, 0, 0, 0, / 38 Unused */
'n', 'N', '<', 0, /* 41 KeyN /
'b', 'B', '|', '+', / 42 KeyB /
'v', 'V', '-', '_', / 43 KeyV /
'c', 'C', 0, 0, / 44 KeyC /
'x', 'X', 0, 0, / 45 KeyX /
'z', 'Z', '`', 0, / 46 KeyZ /
0, 0, 0, 0, / 47 Unused /
0, 0, 0, 0, / 48 Unused */
0, 0, 0, 0, /* 51 KeyRight /
'm', 'M', '>', 0, / 52 KeyM /
'.', '.', '?', 0, / 53 KeyPeriod /
' ', ' ', ' ', ' ', / 54 KeySpace /
0, 0, 0, 0, / 55 KeyLeft /
0, 0, 0, 0, / 56 Unused /
0, 0, 0, 0, / 57 Unused /
0, 0, 0, 0, / 58 Unused */
0, 0, 0, 0, /* 61 Unused /
',', ',', ':', ';', / 62 KeyComma /
'\n','\n','\n','\n',/ 63 KeyEnter /
'p', 'P', ')', '=', / 64 KeyP /
'0', '0', '0', '0', / 65 Key0 /
'9', '9', '9', '9', / 66 Key9 /
'8', '8', '8', '8', / 67 Key8 /
0, 0, 0, 0, / 68 Unused */
'\b','\b','\b','\b',/* 71 KeyBackspace /
'l', 'L', ']', 0, / 72 KeyL /
0, 0, 0, 0, / 73 Unused /
0, 0, 0, 0, / 74 Unused /
'o', 'O', '(', 0, / 75 KeyO /
'i', 'I', '', 0, /* 76 KeyI /
'k', 'K', '[', 0, / 77 KeyK /
0, 0, 0, 0, / 78 Unused */
};
void InitChatpad(void)
{
// InitMessage” (87 02 8C 1F CC)
delay_ms(500);
ChatPadTxBuffer[0]=0x87;
ChatPadTxBuffer[1]=0x02;
ChatPadTxBuffer[2]=0x8C;
ChatPadTxBuffer[3]=0x1F;
ChatPadTxBuffer[4]=0xCC;
ChatPadSendMsg();
//delay_ms(500);
//AwakeChatpad();
}
void AwakeChatpad(void)
{
// AwakeMessage” (87 02 8C 1B D0)
ChatPadTxBuffer[0]=0x87;
ChatPadTxBuffer[1]=0x02;
ChatPadTxBuffer[2]=0x8C;
ChatPadTxBuffer[3]=0x1B;
ChatPadTxBuffer[4]=0xD0;
ChatPadSendMsg();
}
void ChatPadProcessMsg(void)
{
int8 checksum=0xb4 + 0xc5; // preload checksum with what 1st 2 bytes should be to save time
int8 key0;
int8 key1;
int8 modifier;
int8 index;
if(ChatPadRxBuffer[0]==0xb4 && ChatPadRxBuffer[1]==0xc5) // check for right message, ignore status
{
modifier=ChatPadRxBuffer[3] & CHATPAD_MODIFIERS_MASK;
key0=ChatPadRxBuffer[4];
key1=ChatPadRxBuffer[5];
checksum=checksum + ChatPadRxBuffer[2]+modifier+key0+key1+ChatPadRxBuffer[6]; // do checksum the easy way, no loop
checksum=~checksum+1; // 2' complement
if(checksum==ChatPadRxBuffer[7]) // check checksum
{
if(key0==0)
{
ChatPadKeyPressedState=CHATPAD_KEY_NOT_PRESSED; // invalidate any unread keypress
}
else // new press
{
ChatPadKeyPressedState=CHATPAD_KEY_NOT_PRESSED;
index = (((key0 - 0x11) & 0x70) >> 1) | ((key0 - 0x11) & 0x7);
index=index*4;
if ((modifier & CHATPAD_GREEN_MASK) !=0) // green pressed
index+=2;
else if ((modifier & CHATPAD_ORANGE_MASK) !=0) // orange pressed
index+=3;
else if ((modifier & CHATPAD_SHIFT_MASK) !=0) // Shift pressed
index++;
if (index < sizeof(KeyList)) // make sure no overflow
{
ChatPadKey = KeyList[index];
}
if(ChatPadKey!=0)
ChatPadKeyPressedState=CHATPAD_KEY_PRESSED;
}
}
}
}
void main() // chatpad test
{
InitChatpad();
while(1)
{
if(ChatPadKeyPressedState==CHATPAD_KEY_PRESSED)
{
sprintf(buffer,"%ld K=%02X %c %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X",jim,ChatPadKey,ChatPadKey,ChatPadRxBuffer[0],ChatPadRxBuffer[1],ChatPadRxBuffer[2],ChatPadRxBuffer[3],ChatPadRxBuffer[4],ChatPadRxBuffer[5],ChatPadRxBuffer[6],ChatPadRxBuffer[7]);
LCD_Text(0,0,&buffer,WHITE,BLACK);
ChatPadKeyPressedState=CHATPAD_KEY_PROCESSED;
}
if(ChatPadKeepAwakeFlag==TRUE)
{
AwakeChatpad();
ChatPadKeepAwakeFlag=FALSE;
}
}
}
[/code]
I've not included the interrupt driven TX and RX code as that's quite PIC specific but it just sends what is in ChatPadTxBuffer and fills ChatPadRxBuffer.
ChatPadProcessMsg is run from the RX interrupt when the buffer is full and puts a valid key valid into ChatPadKey and sets ChatPadKeyPressedState to CHATPAD_KEY_PRESSED so the main program knows to process it.
AwakeChatpad() is run every second from a flag ChatPadKeepAwakeFlag set in a timer interrupt, the timer is initalised to 1 second at the moment so the first run of AwakeChatpad() is 500ms after InitChatpad()
Sorry about the poor formatting, it's not cutting and pasting too well.
Hopefully it makes some sense.
Jim
[Removed]
[Removed]
[Removed]
PM'd you man