diff --git a/LDCC_Adv_v2.pdf b/LDCC_Adv_v2.pdf new file mode 100644 index 0000000..bb6f254 Binary files /dev/null and b/LDCC_Adv_v2.pdf differ diff --git a/LDCC_Adv_v2.ppt b/LDCC_Adv_v2.ppt new file mode 100644 index 0000000..50239c9 Binary files /dev/null and b/LDCC_Adv_v2.ppt differ diff --git a/LDCC_Intro_v2.pdf b/LDCC_Intro_v2.pdf new file mode 100644 index 0000000..3908467 Binary files /dev/null and b/LDCC_Intro_v2.pdf differ diff --git a/README.md b/README.md index 3076c63..3f5c6a6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,15 @@ # LDCC DCC for the Lego MindStorms RCX + +Links +----- +* [DCC for the RCX](http://home.surewest.net/markril/lego/dcc/) +* [Beta Zone: DCC for the RCX](http://home.surewest.net/markril/lego/dcc/beta.html) +* [LDCC and RCX](http://news.lugnet.com/org/us/indylug/?n=618) +* [DCC and Lego Robotics Creations](http://folk.uio.no/thomasw/robotics/creations.html) +* [DCC on LeJOS](http://news.lugnet.com/robotics/rcx/legos/?n=3959) + * [LeJOS Support for LDCC IR Protocol](http://news.lugnet.com/robotics/rcx/java/?n=259&t=i&v=a) +* [LGauge DCC](http://www.lgauge.com/trains/dcc/dcc.htm) +* [Dr. Vegetable’s Full Throttle App](http://www.drvegetable.com/download_throttle.html) +* [pbForth with DCC Support](http://news.lugnet.com/robotics/rcx/?n=2297) +* [LDCC Patch for BrickOS](http://news.lugnet.com/org/ca/rtltoronto/?n=14996) diff --git a/brickOS/ldcc_lnp.c b/brickOS/ldcc_lnp.c new file mode 100644 index 0000000..ea2bc27 --- /dev/null +++ b/brickOS/ldcc_lnp.c @@ -0,0 +1,167 @@ +/****************************************************************************** + Author : Mark Riley + File : ldcc_lnp.c + Created : 6/29/2003 + Purpose : Demonstration of BrickOS to LDCC comms using LNP +******************************************************************************/ + +#include +#include +#include + +/****************************************************************************** + LDCC Declarations & Functions +******************************************************************************/ + +enum + { + LDCC_CMD_SPEED = 1, + LDCC_CMD_FN_OFF, + LDCC_CMD_FN_ON, + LDCC_CMD_STOP_ALL, + LDCC_CMD_POWER_OFF, + LDCC_CMD_POWER_ON, + LDCC_CMD_SWITCH_CLOSED, + LDCC_CMD_SWITCH_THROWN + }; + +unsigned char g_packet[8]; + +#define LDCC_REPEAT 3 + +void ldcc_send_packet(unsigned char length, char times) + { + for ( ; times; times--) + lnp_addressing_write(g_packet, length, 0x11, 0x01); + } + +void ldcc_power(int state) + { + g_packet[0] = state ? LDCC_CMD_POWER_ON : LDCC_CMD_POWER_OFF; + ldcc_send_packet(1, LDCC_REPEAT); + } + +void ldcc_stop_all() + { + g_packet[0] = LDCC_CMD_STOP_ALL; + ldcc_send_packet(1, LDCC_REPEAT); + } + +void ldcc_speed(char loco, int speed) + { + g_packet[0] = LDCC_CMD_SPEED; + g_packet[1] = loco; + g_packet[2] = speed >> 8; + g_packet[3] = speed & 0xFF; + ldcc_send_packet(4, 1); + } + +void ldcc_function(char loco, char fn, int state) + { + g_packet[0] = state ? LDCC_CMD_FN_ON : LDCC_CMD_FN_OFF; + g_packet[1] = loco; + g_packet[2] = fn; + ldcc_send_packet(3, 1); + } + +/****************************************************************************** + Demo +******************************************************************************/ + +#define MAX_ANGLE 48 +#define LOCO 3 + +int main() + { + int angle = 0; + int last_angle = -1; + char state = 0; + char headlight = 0; + char headlight_repeat = LDCC_REPEAT; + char speed_repeat = LDCC_REPEAT; + int time; + + ds_active(&SENSOR_3); + ds_rotation_on(&SENSOR_3); + ds_rotation_set(&SENSOR_3, 0); + + ldcc_power(1); + + while (!shutdown_requested()) + { + switch (state) + { + case 1: + if (SENSOR_3 >= 0x4000) + { // button released, toggle headlight; + headlight = !headlight; + headlight_repeat = LDCC_REPEAT; + state = 0; + } + else + { // button still held down + if (time - (int)get_system_up_time() <= 0) + { // 1/4 second elapsed, stop loco + ds_rotation_set(&SENSOR_3, 0); + angle = 0; + speed_repeat = LDCC_REPEAT; + state = 2; + } + } + break; + + case 2: + if (SENSOR_3 >= 0x4000) + // button released, resume + state = 0; + break; + + default: + if (SENSOR_3 >= 0x4000) + { // no button pressed, normal throttle operation + angle = ROTATION_3; + + if (angle < -MAX_ANGLE) + angle = -MAX_ANGLE; + else if (angle > MAX_ANGLE) + angle = MAX_ANGLE; + + if (angle != last_angle) + { + last_angle = angle; + speed_repeat = LDCC_REPEAT; + } + } + else + { // button pressed + time = (int)get_system_up_time() + 250; // 1/4 second + state = 1; + } + break; + } + + if (speed_repeat) + { + speed_repeat--; + ldcc_speed(LOCO, ((long)angle << 14) / MAX_ANGLE); + } + + if (headlight_repeat) + { + headlight_repeat--; + ldcc_function(LOCO, 0, headlight); + } + + // so the man will run... + msleep(1); + } + + ldcc_power(0); + + ds_rotation_off(&SENSOR_3); + ds_passive(&SENSOR_3); + + return 0; + } + +// EOF // diff --git a/brickOS/programs/dccdemo.c b/brickOS/programs/dccdemo.c new file mode 100644 index 0000000..eed81f4 --- /dev/null +++ b/brickOS/programs/dccdemo.c @@ -0,0 +1,123 @@ +/****************************************************************************** + + The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Original Code is DCC Library for the RCX. + + The Initial Developer of the Original Code is Mark Riley. Portions + created by Mark Riley are Copyright (C) 2003 Mark Riley. All Rights + Reserved. + + File : dccdemo.c + Created : 6/12/2003 + Purpose : DCC demonstration program for DCC library + +******************************************************************************/ + +#include +#include +#include +#include + +#define MASK (MOTOR_A_MASK | MOTOR_B_MASK | MOTOR_C_MASK) + +#define MAX_ANGLE 48 + +#define ADDR 3 + +// state of decoder functions FL through F4 +unsigned char funcs = 0; + +int main() + { + unsigned char old_dm_mask = dm_mask; + int angle = 0; + char state = 0; + int time; + + dm_mask &= ~MASK; + dcc_mask = MASK; + + ds_active(&SENSOR_3); + ds_rotation_on(&SENSOR_3); + ds_rotation_set(&SENSOR_3, 0); + + dcc_power_on(); + + while (!shutdown_requested()) + { + switch (state) + { + case 1: + if (SENSOR_3 >= 0x4000) + { // button released, toggle headlight; + funcs ^= DCC_FL; + state = 0; + } + else + { // button still held down + if (time - (int)get_system_up_time() <= 0) + { // 1/4 second elapsed, stop loco + angle = 0; + ds_rotation_set(&SENSOR_3, 0); + state = 2; + } + } + break; + + case 2: + if (SENSOR_3 >= 0x4000) + // button released, resume + state = 0; + break; + + default: + if (SENSOR_3 >= 0x4000) + { // no button pressed, normal throttle operation + angle = ROTATION_3; + + if (angle < -MAX_ANGLE) + angle = -MAX_ANGLE; + else if (angle > MAX_ANGLE) + angle = MAX_ANGLE; + } + else + { // button pressed + time = (int)get_system_up_time() + 250; // 1/4 second + state = 1; + } + break; + } + + //dcc_speed14(ADDR, angle * 14 / MAX_ANGLE, funcs & DCC_FL); + //dcc_speed28(ADDR, angle * 28 / MAX_ANGLE); + dcc_speed126(ADDR, angle * 126 / MAX_ANGLE); + + dcc_idle(); + dcc_idle(); + + dcc_FL_F4(ADDR, funcs); + + dcc_idle(); + dcc_idle(); + } + + dcc_power_off(); + + ds_rotation_off(&SENSOR_3); + ds_passive(&SENSOR_3); + + dm_mask = old_dm_mask; + + return 0; + } + +// EOF // diff --git a/brickOS/programs/dcctest.c b/brickOS/programs/dcctest.c new file mode 100644 index 0000000..8e13b74 --- /dev/null +++ b/brickOS/programs/dcctest.c @@ -0,0 +1,267 @@ +/****************************************************************************** + + The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + The Original Code is DCC Library for the RCX. + + The Initial Developer of the Original Code is Mark Riley. Portions + created by Mark Riley are Copyright (C) 2003 Mark Riley. All Rights + Reserved. + + File : dccdemo.c + Created : 6/12/2003 + Purpose : DCC demonstration program for DCC library + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define MASK (MOTOR_A_MASK | MOTOR_B_MASK | MOTOR_C_MASK) + +#define MAX_ANGLE 48 + +#define ADDR 3 + +#define DCC_FUNC_GRP_0 0x80 +#define DCC_FUNC_GRP_1 0xB0 +#define DCC_FUNC_GRP_2 0xA0 + +// state of decoder functions FL through F4 +unsigned char funcs [] = { DCC_FUNC_GRP_0, DCC_FUNC_GRP_1, DCC_FUNC_GRP_2 }; + +void dcc_func(int addr, unsigned char func) +{ + + // Determine function group and toggle the specified function flag + if ((0xE0 & func) == DCC_FUNC_GRP_0) + { + funcs[0] = DCC_FUNC_GRP_0 | ((funcs[0] ^ func) & 0x1F); + p_buffer[1] = funcs[0]; + cputc_0('0'); + } + else if ((0xF0 & func) == DCC_FUNC_GRP_1) + { + funcs[1] = DCC_FUNC_GRP_1 | ((funcs[1] ^ func) & 0x0F); + p_buffer[1] = funcs[1]; + cputc_0('1'); + } + else if ((0xF0 & func) == DCC_FUNC_GRP_2) + { + funcs[2] = DCC_FUNC_GRP_2 | ((funcs[2] ^ func) & 0x0F); + p_buffer[1] = funcs[2]; + cputc_0('2'); + } + else + { + cputc_0('-'); + } + + // Fill the command buffer + p_buffer[0] = addr; + + // Send the command + dcc_ops_packet(p_buffer, 2); +} + +void dcc_sleep(int sec) +{ + dcc_msleep(sec * 1000); +} + +void dcc_msleep(int msec) +{ + int tmStart = (int)get_system_up_time(); + int i = 0; + + while(tmStart + msec >= (int)get_system_up_time()) + { + p_buffer[0] = ADDR; + for(i = 0; i < 3; i++) + { + dcc_idle(); + p_buffer[1] = funcs[i]; + dcc_ops_packet(p_buffer, 2); + dcc_idle(); + } + } +} + +void dcc_funcFlip(int bank, int func) +{ + switch (bank) + { + case 0: + dcc_FL_F4(ADDR, func); + dcc_msleep(20); + dcc_FL_F4(ADDR, 0); + break; + case 1: + dcc_F5_F8(ADDR, func); + dcc_msleep(20); + dcc_F5_F8(ADDR, 0); + break; + case 2: + dcc_F9_F12(ADDR, func); + dcc_msleep(20); + dcc_F9_F12(ADDR, 0); + break; + } +} + + +int main() + { + unsigned char old_dm_mask = dm_mask; + int angle = 0; + char state = 0; + int time; + + dm_mask &= ~MASK; + dcc_mask = MASK; + + ds_active(&SENSOR_3); + ds_rotation_on(&SENSOR_3); + ds_rotation_set(&SENSOR_3, 0); + + sleep(1); + + cputs("Pwr"); +// dsound_system(0); + dcc_power_on(); + dcc_sleep(1); + + + cputs("Up"); +// dsound_system(0); + dcc_func(ADDR, DCC_FUNC_GRP_1 | DCC_F6); +// dcc_F5_F8(ADDR, DCC_F6); +// dcc_msleep(250); +// dcc_F5_F8(ADDR, 0); + dcc_sleep(5); + + + cputs("Lite"); +// dsound_system(0); + dcc_func(ADDR, DCC_FUNC_GRP_0 | DCC_FL); + dcc_sleep(5); + + cputs("Bell"); +// dsound_system(0); + dcc_func(ADDR, DCC_FUNC_GRP_0 | DCC_F1); +// dcc_func(0, DCC_F1); +// dcc_FL_F4(ADDR, DCC_F1 + DCC_F2); + dcc_sleep(5); + + + cputs("bOff"); +// dsound_system(0); + dcc_func(ADDR, DCC_FUNC_GRP_0 | DCC_F1); +// dcc_FL_F4(ADDR, 0); +// dcc_func(0, DCC_F1); +// dcc_FL_F4(ADDR, DCC_F2); +// dcc_F5_F8(ADDR, DCC_F7); + dcc_sleep(5); + + + cputs("Stat"); +// dsound_system(0); + dcc_func(ADDR, DCC_FUNC_GRP_2 | DCC_F10); +// dcc_F9_F12(ADDR, DCC_F10); + dcc_sleep(10); + + + cputs("Mute"); +// dsound_system(0); + dcc_func(ADDR, DCC_FUNC_GRP_1 | DCC_F8); + dcc_sleep(5); + + +// dsound_system(0); + cputs("OFF"); + dsound_system(0); + +/* + while (!shutdown_requested()) + { + switch (state) + { + case 1: + if (SENSOR_3 >= 0x4000) + { // button released, toggle headlight; + funcs ^= DCC_FL; + state = 0; + } + else + { // button still held down + if (time - (int)get_system_up_time() <= 0) + { // 1/4 second elapsed, stop loco + angle = 0; + ds_rotation_set(&SENSOR_3, 0); + state = 2; + } + } + break; + + case 2: + if (SENSOR_3 >= 0x4000) + // button released, resume + state = 0; + break; + + default: + if (SENSOR_3 >= 0x4000) + { // no button pressed, normal throttle operation + angle = ROTATION_3; + + if (angle < -MAX_ANGLE) + angle = -MAX_ANGLE; + else if (angle > MAX_ANGLE) + angle = MAX_ANGLE; + } + else + { // button pressed + time = (int)get_system_up_time() + 250; // 1/4 second + state = 1; + } + break; + } + + //dcc_speed14(ADDR, angle * 14 / MAX_ANGLE, funcs & DCC_FL); + //dcc_speed28(ADDR, angle * 28 / MAX_ANGLE); + dcc_speed126(ADDR, angle * 126 / MAX_ANGLE); + + dcc_idle(); + dcc_idle(); + + dcc_FL_F4(ADDR, funcs); + + dcc_idle(); + dcc_idle(); + } +*/ + + cputs(""); + dcc_power_off(); + + ds_rotation_off(&SENSOR_3); + ds_passive(&SENSOR_3); + + dm_mask = old_dm_mask; + + return 0; + } + +// EOF // diff --git a/nqc/ldccTest.nqc b/nqc/ldccTest.nqc new file mode 100644 index 0000000..dae3ce6 --- /dev/null +++ b/nqc/ldccTest.nqc @@ -0,0 +1,162 @@ +/****************************************************************************** + Author : Mark Riley + File : ldccdemo.nqc + Created : 6/29/2003 + Purpose : Demonstration of NQC to LDCC comms using standard RCX packets +******************************************************************************/ + +#define LDCC_CMD_SPEED 1 +#define LDCC_CMD_FN_OFF 2 +#define LDCC_CMD_FN_ON 3 +#define LDCC_CMD_STOP_ALL 4 +#define LDCC_CMD_POWER_OFF 5 +#define LDCC_CMD_POWER_ON 6 +#define LDCC_CMD_SWITCH_CLOSED 7 +#define LDCC_CMD_SWITCH_THROWN 8 + +#define LDCC_REPEAT 3 + +void ldcc_power(int state) + { + SetSerialData(2, state ? LDCC_CMD_POWER_ON : LDCC_CMD_POWER_OFF); + SendSerial(0, 3); + } + +void ldcc_stop_all() + { + SetSerialData(2, LDCC_CMD_STOP_ALL); + SendSerial(0, 3); + } + +void ldcc_speed(int loco, int speed) + { + SetSerialData(2, LDCC_CMD_SPEED); + SetSerialData(3, loco); + SetSerialData(4, speed >> 8); + SetSerialData(5, speed & 0xFF); + SendSerial(0, 6); + } + +void ldcc_function(int loco, int fn, int state) + { + SetSerialData(2, state ? LDCC_CMD_FN_ON : LDCC_CMD_FN_OFF); + SetSerialData(3, loco); + SetSerialData(4, fn); + SendSerial(0, 5); + } + +#define MAX_ANGLE 48 +#define LOCO 3 + +task main() + { + + // Initialization + SetSerialComm(SERIAL_COMM_DEFAULT); + SetSerialPacket(SERIAL_PACKET_RCX); + SetSerialData(0, 0xF5); + SetSerialData(1, 0x01); + + Wait(200); + + PlaySound(SOUND_UP); + ldcc_function(LOCO, 1, !0); + Wait(300); + ldcc_function(LOCO, 1, 0); + + PlaySound(SOUND_CLICK); + + ldcc_function(LOCO, 10, !0); + Wait(10); + ldcc_function(LOCO, 10, 0); + Wait(1000); + PlaySound(SOUND_DOWN); + + + /* + int angle = 0; + int last_angle = -1; + int state = 0; + int headlight = 0; + int headlight_repeat = LDCC_REPEAT; + int speed_repeat = LDCC_REPEAT; + int time; + + SetSensor(SENSOR_3, SENSOR_ROTATION); + ClearSensor(SENSOR_3); + + SetSerialComm(SERIAL_COMM_DEFAULT); + SetSerialPacket(SERIAL_PACKET_RCX); + SetSerialData(0, 0xF5); + SetSerialData(1, 0x01); + + while (1) + { + switch (state) + { + case 1: + if (SensorValueRaw(SENSOR_3) >= 256) + { // button released, toggle headlight; + headlight = !headlight; + headlight_repeat = LDCC_REPEAT; + state = 0; + } + else + { // button still held down + if (FastTimer(0) >= 25) + { // 1/4 second elapsed, stop loco + ClearSensor(SENSOR_3); + angle = 0; + speed_repeat = LDCC_REPEAT; + state = 2; + } + } + break; + + case 2: + if (SensorValueRaw(SENSOR_3) >= 256) + // button released, resume + state = 0; + break; + + default: + if (SensorValueRaw(SENSOR_3) >= 256) + { // no button pressed, normal throttle operation + angle = SENSOR_3; + + if (angle < -MAX_ANGLE) + angle = -MAX_ANGLE; + else if (angle > MAX_ANGLE) + angle = MAX_ANGLE; + + if (angle != last_angle) + { + last_angle = angle; + speed_repeat = LDCC_REPEAT; + } + } + else + { // button pressed + ClearTimer(0); + state = 1; + } + break; + } + + if (speed_repeat) + { + speed_repeat--; + ldcc_speed(LOCO, angle * (16384 / MAX_ANGLE)); + } + + if (headlight_repeat) + { + headlight_repeat--; + ldcc_function(LOCO, 0, headlight); + } + } + */ + } + +// eof // + diff --git a/nqc/ldccdemo.nqc b/nqc/ldccdemo.nqc new file mode 100644 index 0000000..6df65a2 --- /dev/null +++ b/nqc/ldccdemo.nqc @@ -0,0 +1,137 @@ +/****************************************************************************** + Author : Mark Riley + File : ldccdemo.nqc + Created : 6/29/2003 + Purpose : Demonstration of NQC to LDCC comms using standard RCX packets +******************************************************************************/ + +#define LDCC_CMD_SPEED 1 +#define LDCC_CMD_FN_OFF 2 +#define LDCC_CMD_FN_ON 3 +#define LDCC_CMD_STOP_ALL 4 +#define LDCC_CMD_POWER_OFF 5 +#define LDCC_CMD_POWER_ON 6 +#define LDCC_CMD_SWITCH_CLOSED 7 +#define LDCC_CMD_SWITCH_THROWN 8 + +#define LDCC_REPEAT 3 + +void ldcc_power(int state) + { + SetSerialData(2, state ? LDCC_CMD_POWER_ON : LDCC_CMD_POWER_OFF); + SendSerial(0, 3); + } + +void ldcc_stop_all() + { + SetSerialData(2, LDCC_CMD_STOP_ALL); + SendSerial(0, 3); + } + +void ldcc_speed(int loco, int speed) + { + SetSerialData(2, LDCC_CMD_SPEED); + SetSerialData(3, loco); + SetSerialData(4, speed >> 8); + SetSerialData(5, speed & 0xFF); + SendSerial(0, 6); + } + +void ldcc_function(int loco, int fn, int state) + { + SetSerialData(2, state ? LDCC_CMD_FN_ON : LDCC_CMD_FN_OFF); + SetSerialData(3, loco); + SetSerialData(4, fn); + SendSerial(0, 5); + } + +#define MAX_ANGLE 48 +#define LOCO 3 + +task main() + { + int angle = 0; + int last_angle = -1; + int state = 0; + int headlight = 0; + int headlight_repeat = LDCC_REPEAT; + int speed_repeat = LDCC_REPEAT; + int time; + + SetSensor(SENSOR_3, SENSOR_ROTATION); + ClearSensor(SENSOR_3); + + SetSerialComm(SERIAL_COMM_DEFAULT); + SetSerialPacket(SERIAL_PACKET_RCX); + SetSerialData(0, 0xF5); + SetSerialData(1, 0x01); + + while (1) + { + switch (state) + { + case 1: + if (SensorValueRaw(SENSOR_3) >= 256) + { // button released, toggle headlight; + headlight = !headlight; + headlight_repeat = LDCC_REPEAT; + state = 0; + } + else + { // button still held down + if (FastTimer(0) >= 25) + { // 1/4 second elapsed, stop loco + ClearSensor(SENSOR_3); + angle = 0; + speed_repeat = LDCC_REPEAT; + state = 2; + } + } + break; + + case 2: + if (SensorValueRaw(SENSOR_3) >= 256) + // button released, resume + state = 0; + break; + + default: + if (SensorValueRaw(SENSOR_3) >= 256) + { // no button pressed, normal throttle operation + angle = SENSOR_3; + + if (angle < -MAX_ANGLE) + angle = -MAX_ANGLE; + else if (angle > MAX_ANGLE) + angle = MAX_ANGLE; + + if (angle != last_angle) + { + last_angle = angle; + speed_repeat = LDCC_REPEAT; + } + } + else + { // button pressed + ClearTimer(0); + state = 1; + } + break; + } + + if (speed_repeat) + { + speed_repeat--; + ldcc_speed(LOCO, angle * (16384 / MAX_ANGLE)); + } + + if (headlight_repeat) + { + headlight_repeat--; + ldcc_function(LOCO, 0, headlight); + } + } + } + +// eof // +