// ------------ compcontrol.h:
enum SERIALMSG
{
MSG_UNUSED = 0, // 0x00 c0nb0x specific, not used by adafruit or sokkos
MSG_PING = 1, // 0x01
MSG_PATT_WR = 16, // 0x10
MSG_PATT_RD = 17, // 0x11
MSG_PATT_LOAD = 18, // 0x12
MSG_PATT_GET = 19, // 0x13
MSG_PATT_PLAY = 20, // 0x14
MSG_PATT_STOP = 21, // 0x15
MSG_PATT = 25, // 0x19
MSG_TRACK_WR = 32, // 0x20
MSG_TRACK_RD = 33, // 0x21
MSG_TRACK_LOAD = 34, // 0x22
MSG_TRACK_GET = 35, // 0x23
MSG_TRACK = 41, // 0x29
MSG_SEQ_START = 48, // 0x30
MSG_SEQ_STOP = 49, // 0x31
MSG_SEQ_GET = 50, // 0x32
MSG_SYNC_SET = 51, // 0x33
MSG_TEMPO_GET = 64, // 0x40
MSG_TEMPO_SET = 65, // 0x41
MSG_TEMPO = 66, // 0x42
MSG_STATUS = 128, // 0x80
// /---------------------------
// extended messages go here (after 128)
// ---------------------------/
MSG_FW_VER = 129, // 0x81
MSG_ISSUPP = 130, // 0x82 "is MSG supported"
MSG_DIAG = 131, // 0x83 DiagOS diagnostic stuff..
MSG_TEXTOUT = 132, // 0x84 text output (useful for debugging)
MSG_GET_MEM = 133, // 0x85 get variable amounts of memory from the external EEPROM
MSG_SET_MEM = 134, // 0x86 write variable amounts of memory to the external EEPROM
MSG_PATBUF = 135, // 0x87 get/set the pattern(s) from the pattern buffer (as opposed to the EEPROM)
MSG_GET_INFO = 136, // 0x88 get info such as EEPROM size, number of banks/slots and so on
};
enum STATREPLY
{
STAT_BAD = 0,
STAT_OK = 1
};
// -------------- compcontrol.c:
case MSG_ISSUPP:
{
// to x0x:
// [uint16_t CODE]
// for now, the first byte is not used (yet) so should be zero
if (size == 2)
{
uint8_t issupp = 0;
if (recv_msg_buff[3] == 0)
{
// to app:
// [uint16_t CODE] [uint8_t issupp]
switch (recv_msg_buff[4])
{
case MSG_ISSUPP: issupp = 1; break;
case MSG_FW_VER: issupp = 1; break;
case MSG_GET_MEM: issupp = 1; break;
case MSG_SET_MEM: issupp = 1; break;
case MSG_PATBUF: issupp = 1; break;
#ifdef XMSG_TEXTOUT
case MSG_TEXTOUT: issupp = 1; break;
#endif // XMSG_TEXTOUT
case MSG_GET_INFO: issupp = 1; break;
case MSG_PATT: issupp = PAT_SZ; break;
default: issupp = 0; break;
};
}
tx_msg_buff[0] = MSG_ISSUPP;
tx_msg_buff[1] = 0;
tx_msg_buff[2] = 3;
tx_msg_buff[3] = recv_msg_buff[3];
tx_msg_buff[4] = recv_msg_buff[4];
tx_msg_buff[5] = issupp;
tx_msg_buff[6] = calc_CRC8(tx_msg_buff, 6);
send_msg(tx_msg_buff, 7);
break;
}
send_status(STAT_BAD);
} break;
case MSG_GET_MEM:
{
// to x0x:
// [uint16_t ADDRESS] [uint8_t LENGTH]
uint8_t i, len;
uint16_t addr;
if (size != 3) { send_status(STAT_BAD); break; }
addr = recv_msg_buff[3];
addr <<= 8;
addr |= recv_msg_buff[4];
len = recv_msg_buff[5];
if (len > 58) { send_status(STAT_BAD); break; }
// to app:
// [uint16_t ADDRESS] [data]
tx_msg_buff[0] = MSG_GET_MEM;
tx_msg_buff[1] = 0;
tx_msg_buff[2] = 2+len;
tx_msg_buff[3] = recv_msg_buff[3];
tx_msg_buff[4] = recv_msg_buff[4];
for (i=0; i<len; i++)
{
tx_msg_buff[5+i] = spieeprom_read(addr + i);
}
len = tx_msg_buff[2]+3;
tx_msg_buff[len] = calc_CRC8(tx_msg_buff, len);
++len;
send_msg(tx_msg_buff, len);
} break;
case MSG_SET_MEM:
{
// to x0x:
// [uint16_t ADDRESS] [data]
uint8_t i, len;
uint16_t addr;
addr = recv_msg_buff[3];
addr <<= 8;
addr |= recv_msg_buff[4];
len = recv_msg_buff[2]-2;
if ((len > 58) || (len == 0)) { send_status(STAT_BAD); break; }
for (i=0; i<len; i++)
{
spieeprom_write(recv_msg_buff[5+i], addr + i);
}
send_status(STAT_OK);
} break;
case MSG_PATBUF:
{
// [CMD] [N] <DATA>
// CMD: 0 == get, 1 = set
// N: which pattern (if the patbuf can hold multiple)
// DATA: THE data
uint8_t i = 0;
if (recv_msg_buff[3] == 0) // GET
{
// [CMD] [N]
if (size != 2) { send_status(STAT_BAD); break; }
if (recv_msg_buff[4] >= MAX_CHAIN) { send_status(STAT_BAD); break; }
// return the pattern, maybe use MSG_PATT ?
tx_msg_buff[0] = MSG_PATT;
tx_msg_buff[1] = 0;
tx_msg_buff[2] = PAT_SZ;
i = 0;
while (i < PAT_SZ)
{
tx_msg_buff[3+i] = patbuf[(PAT_SZ*recv_msg_buff[4])+i];
++i;
}
i += 3;
tx_msg_buff[i] = calc_CRC8(tx_msg_buff, i);
++i;
send_msg(tx_msg_buff,i);
}
else if (recv_msg_buff[3] == 1) // SET
{
// [CMD] [N] [PATTERN_DATA]
if (size != (2+PAT_SZ)) { send_status(STAT_BAD); break; }
if (recv_msg_buff[4] >= MAX_CHAIN) { send_status(STAT_BAD); break; }
// take the pattern
i = 0;
while (i < PAT_SZ)
{
patbuf[(PAT_SZ*recv_msg_buff[4])+i] = recv_msg_buff[5+i];
++i;
}
// send STAT_OK
send_status(STAT_OK);
}
else
{
send_status(STAT_BAD);
}
} break;
case MSG_GET_INFO:
{
// [CODE]
uint8_t len = 0;
uint8_t ok = 1;
tx_msg_buff[0] = MSG_GET_INFO;
tx_msg_buff[1] = 0;
switch (recv_msg_buff[3])
{
case 0: // EEPROM info
// [INTERNAL] [EXTERNAL]
// internal eeprom is 4kB on the atmega2561
// 0x1000 == 4096
tx_msg_buff[3] = 0x10; // internal
tx_msg_buff[4] = 0x00; // internal
// maybe check whether there's eeprom (detect it) ?
tx_msg_buff[5] = 0x10; // external, 4kB too
tx_msg_buff[6] = 0x00; // external
len = 4;
break;
case 1: // pattern count info
// [BANKS] [SLOTS]
tx_msg_buff[3] = NUM_BANKS;
tx_msg_buff[4] = NUM_SLOTS * NUM_SECTS;
len = 2;
break;
case 8: // is cpumod? (x0x2561)
tx_msg_buff[3] = 1; // YES
len = 1;
break;
default:
ok = 0; // unknown code, send STAT_BAD
break;
};
if (ok)
{
// finalize the message and send it
tx_msg_buff[2] = len;
len += 3;
tx_msg_buff[len] = calc_CRC8(tx_msg_buff, len);
++len;
send_msg(tx_msg_buff, len);
}
else
{
send_status(STAT_BAD);
}
} break;