A test of creating custom classes for control over RPC. Creates an LED class with member functions callable over serial.
main.cpp@0:b0ab03e03fdc, 2010-09-29 (annotated)
- Committer:
- JimmyTheHack
- Date:
- Wed Sep 29 01:09:48 2010 +0000
- Revision:
- 0:b0ab03e03fdc
- Child:
- 1:ddf1739fcbb8
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JimmyTheHack | 0:b0ab03e03fdc | 1 | /* Test of custom RPC classes. An introduction to the RPC environment. |
JimmyTheHack | 0:b0ab03e03fdc | 2 | |
JimmyTheHack | 0:b0ab03e03fdc | 3 | Based heavily off of code from iva2k |
JimmyTheHack | 0:b0ab03e03fdc | 4 | http://mbed.org/users/iva2k/programs/pub_iva2k_ethrpc/gpdz3x |
JimmyTheHack | 0:b0ab03e03fdc | 5 | in turn based off of servo library |
JimmyTheHack | 0:b0ab03e03fdc | 6 | http://mbed.org/projects/cookbook/svn/Servo/trunk/Servo.h |
JimmyTheHack | 0:b0ab03e03fdc | 7 | http://mbed.org/projects/cookbook/svn/Servo/trunk/Servo.cpp |
JimmyTheHack | 0:b0ab03e03fdc | 8 | |
JimmyTheHack | 0:b0ab03e03fdc | 9 | This code features heavy copy-pasting, so I take little credit for the content. My goal was not to create original code, but to put together a basic introduction |
JimmyTheHack | 0:b0ab03e03fdc | 10 | to help myself and others understand how to implement custom classes in RPC. |
JimmyTheHack | 0:b0ab03e03fdc | 11 | |
JimmyTheHack | 0:b0ab03e03fdc | 12 | This code creates a custom RPC class called LED. The LED class contains two member functions, toggle and blink. |
JimmyTheHack | 0:b0ab03e03fdc | 13 | Normally when compiling a program the original names of the objects are lost. In order to be able to call these functions by name after compiling, we must save the name in a string. |
JimmyTheHack | 0:b0ab03e03fdc | 14 | The name of our object and necessary arguments for the initialization function are saved using the get_rpc_class() function. The name of each member function and their arguments must also be |
JimmyTheHack | 0:b0ab03e03fdc | 15 | registered using get_rpc_methods(). |
JimmyTheHack | 0:b0ab03e03fdc | 16 | |
JimmyTheHack | 0:b0ab03e03fdc | 17 | |
JimmyTheHack | 0:b0ab03e03fdc | 18 | |
JimmyTheHack | 0:b0ab03e03fdc | 19 | |
JimmyTheHack | 0:b0ab03e03fdc | 20 | From: http://mbed.org/cookbook/Interfacing-Using-RPC |
JimmyTheHack | 0:b0ab03e03fdc | 21 | |
JimmyTheHack | 0:b0ab03e03fdc | 22 | RPC Commands are in the format: "/<Object name>/<Method name> <Arguments separated by spaces> |
JimmyTheHack | 0:b0ab03e03fdc | 23 | If you send just "/" mbed will return a list of objects that can be used |
JimmyTheHack | 0:b0ab03e03fdc | 24 | If you send "/<object name>/" then mbed will return the methods which can be used on this object. |
JimmyTheHack | 0:b0ab03e03fdc | 25 | |
JimmyTheHack | 0:b0ab03e03fdc | 26 | I haven't finished digging through this yet, but I think most of the documentation for the RPC functions is in the files: |
JimmyTheHack | 0:b0ab03e03fdc | 27 | http://mbed.org/projects/libraries/svn/mbed/trunk/Base.h |
JimmyTheHack | 0:b0ab03e03fdc | 28 | http://mbed.org/projects/libraries/svn/mbed/trunk/rpc.h |
JimmyTheHack | 0:b0ab03e03fdc | 29 | |
JimmyTheHack | 0:b0ab03e03fdc | 30 | |
JimmyTheHack | 0:b0ab03e03fdc | 31 | */ |
JimmyTheHack | 0:b0ab03e03fdc | 32 | |
JimmyTheHack | 0:b0ab03e03fdc | 33 | #include "mbed.h" |
JimmyTheHack | 0:b0ab03e03fdc | 34 | #include "rpc.h" |
JimmyTheHack | 0:b0ab03e03fdc | 35 | |
JimmyTheHack | 0:b0ab03e03fdc | 36 | |
JimmyTheHack | 0:b0ab03e03fdc | 37 | /*LED class definition*/ |
JimmyTheHack | 0:b0ab03e03fdc | 38 | |
JimmyTheHack | 0:b0ab03e03fdc | 39 | class LED :public Base { //make sure to define the class with inheritance from the Base RPC class. |
JimmyTheHack | 0:b0ab03e03fdc | 40 | public: |
JimmyTheHack | 0:b0ab03e03fdc | 41 | //constructor// |
JimmyTheHack | 0:b0ab03e03fdc | 42 | LED(PinName mypin, const char *name=NULL); |
JimmyTheHack | 0:b0ab03e03fdc | 43 | //LED class functions// |
JimmyTheHack | 0:b0ab03e03fdc | 44 | void blink(int n); |
JimmyTheHack | 0:b0ab03e03fdc | 45 | int toggle(); |
JimmyTheHack | 0:b0ab03e03fdc | 46 | DigitalOut LEDpin; |
JimmyTheHack | 0:b0ab03e03fdc | 47 | int state; |
JimmyTheHack | 0:b0ab03e03fdc | 48 | |
JimmyTheHack | 0:b0ab03e03fdc | 49 | #ifdef MBED_RPC //this code will not compile unless we have included the rpc.h file. So this class can also be used without RPC. |
JimmyTheHack | 0:b0ab03e03fdc | 50 | virtual const struct rpc_method *get_rpc_methods(); |
JimmyTheHack | 0:b0ab03e03fdc | 51 | static struct rpc_class *get_rpc_class(); |
JimmyTheHack | 0:b0ab03e03fdc | 52 | #endif // MBED_RPC |
JimmyTheHack | 0:b0ab03e03fdc | 53 | }; |
JimmyTheHack | 0:b0ab03e03fdc | 54 | |
JimmyTheHack | 0:b0ab03e03fdc | 55 | |
JimmyTheHack | 0:b0ab03e03fdc | 56 | |
JimmyTheHack | 0:b0ab03e03fdc | 57 | LED::LED(PinName mypin, const char *name) : Base(name), LEDpin(mypin) { //initialize pin |
JimmyTheHack | 0:b0ab03e03fdc | 58 | /*Initialization Function*/ |
JimmyTheHack | 0:b0ab03e03fdc | 59 | LEDpin.write(0); |
JimmyTheHack | 0:b0ab03e03fdc | 60 | state=false; //set LED to off |
JimmyTheHack | 0:b0ab03e03fdc | 61 | } |
JimmyTheHack | 0:b0ab03e03fdc | 62 | |
JimmyTheHack | 0:b0ab03e03fdc | 63 | int LED::toggle() { |
JimmyTheHack | 0:b0ab03e03fdc | 64 | /*switch the state of the LED*/ |
JimmyTheHack | 0:b0ab03e03fdc | 65 | if (state==0) { |
JimmyTheHack | 0:b0ab03e03fdc | 66 | state=1; |
JimmyTheHack | 0:b0ab03e03fdc | 67 | } else { |
JimmyTheHack | 0:b0ab03e03fdc | 68 | state=0; |
JimmyTheHack | 0:b0ab03e03fdc | 69 | } |
JimmyTheHack | 0:b0ab03e03fdc | 70 | LEDpin=state; |
JimmyTheHack | 0:b0ab03e03fdc | 71 | return state; //print the current state of the LED |
JimmyTheHack | 0:b0ab03e03fdc | 72 | } |
JimmyTheHack | 0:b0ab03e03fdc | 73 | |
JimmyTheHack | 0:b0ab03e03fdc | 74 | void LED::blink(int n=1) { |
JimmyTheHack | 0:b0ab03e03fdc | 75 | /*blink the LED n times*/ |
JimmyTheHack | 0:b0ab03e03fdc | 76 | do { //blink at least once |
JimmyTheHack | 0:b0ab03e03fdc | 77 | toggle(); //toggle LED state |
JimmyTheHack | 0:b0ab03e03fdc | 78 | wait(.2); |
JimmyTheHack | 0:b0ab03e03fdc | 79 | toggle(); //return LED to original state |
JimmyTheHack | 0:b0ab03e03fdc | 80 | wait(.2); |
JimmyTheHack | 0:b0ab03e03fdc | 81 | n--; |
JimmyTheHack | 0:b0ab03e03fdc | 82 | } while (n>=1); |
JimmyTheHack | 0:b0ab03e03fdc | 83 | } |
JimmyTheHack | 0:b0ab03e03fdc | 84 | |
JimmyTheHack | 0:b0ab03e03fdc | 85 | |
JimmyTheHack | 0:b0ab03e03fdc | 86 | #ifdef MBED_RPC |
JimmyTheHack | 0:b0ab03e03fdc | 87 | const rpc_method *LED::get_rpc_methods() { |
JimmyTheHack | 0:b0ab03e03fdc | 88 | /*Create a list of the available methods which can be called for this class*/ |
JimmyTheHack | 0:b0ab03e03fdc | 89 | static const rpc_method rpc_methods[] = { |
JimmyTheHack | 0:b0ab03e03fdc | 90 | { "toggle", rpc_method_caller<int, LED, &LED::toggle> }, //first specify the name string. The arguments to rpc_method_caller appear to be <outputs, RPC class, inputs, reference to function>. |
JimmyTheHack | 0:b0ab03e03fdc | 91 | //In this case, we have one output and no inputs so they are skipped. We must only specify the class of the object the method belongs to and the address of the method. |
JimmyTheHack | 0:b0ab03e03fdc | 92 | |
JimmyTheHack | 0:b0ab03e03fdc | 93 | { "blink", rpc_method_caller<LED, int, &LED::blink> }, //this method has no outputs so they are skipped, but we must specify the input to be of type int. |
JimmyTheHack | 0:b0ab03e03fdc | 94 | RPC_METHOD_SUPER(Base), |
JimmyTheHack | 0:b0ab03e03fdc | 95 | }; |
JimmyTheHack | 0:b0ab03e03fdc | 96 | return rpc_methods; |
JimmyTheHack | 0:b0ab03e03fdc | 97 | } |
JimmyTheHack | 0:b0ab03e03fdc | 98 | |
JimmyTheHack | 0:b0ab03e03fdc | 99 | rpc_class *LED::get_rpc_class() { |
JimmyTheHack | 0:b0ab03e03fdc | 100 | /*Register the class itself as an RPC-callable class*/ |
JimmyTheHack | 0:b0ab03e03fdc | 101 | static const rpc_function funcs[] = { |
JimmyTheHack | 0:b0ab03e03fdc | 102 | { "new", rpc_function_caller<const char*, PinName, const char*, &Base::construct<LED,PinName,const char*> > }, //still don't fully understand the arguments in this line. I suppose the first argument may just be an output echo of the name. |
JimmyTheHack | 0:b0ab03e03fdc | 103 | RPC_METHOD_END |
JimmyTheHack | 0:b0ab03e03fdc | 104 | }; |
JimmyTheHack | 0:b0ab03e03fdc | 105 | static rpc_class c = { "LED", funcs, NULL }; |
JimmyTheHack | 0:b0ab03e03fdc | 106 | return &c; |
JimmyTheHack | 0:b0ab03e03fdc | 107 | } |
JimmyTheHack | 0:b0ab03e03fdc | 108 | #endif // MBED_RPC |
JimmyTheHack | 0:b0ab03e03fdc | 109 | |
JimmyTheHack | 0:b0ab03e03fdc | 110 | |
JimmyTheHack | 0:b0ab03e03fdc | 111 | /* end LED class definition */ |
JimmyTheHack | 0:b0ab03e03fdc | 112 | |
JimmyTheHack | 0:b0ab03e03fdc | 113 | |
JimmyTheHack | 0:b0ab03e03fdc | 114 | |
JimmyTheHack | 0:b0ab03e03fdc | 115 | |
JimmyTheHack | 0:b0ab03e03fdc | 116 | |
JimmyTheHack | 0:b0ab03e03fdc | 117 | Serial pc(USBTX, USBRX); //set up serial communication |
JimmyTheHack | 0:b0ab03e03fdc | 118 | int main() { |
JimmyTheHack | 0:b0ab03e03fdc | 119 | /*Wait for RPC commands and then call the */ |
JimmyTheHack | 0:b0ab03e03fdc | 120 | |
JimmyTheHack | 0:b0ab03e03fdc | 121 | // specify which classes we would like to be able to call over LED |
JimmyTheHack | 0:b0ab03e03fdc | 122 | Base::add_rpc_class<Timer>(); //a class included in the core mbed RPC library |
JimmyTheHack | 0:b0ab03e03fdc | 123 | Base::add_rpc_class<LED>(); //my own custom LED class |
JimmyTheHack | 0:b0ab03e03fdc | 124 | |
JimmyTheHack | 0:b0ab03e03fdc | 125 | // receive commands, and send back the responses |
JimmyTheHack | 0:b0ab03e03fdc | 126 | char buf[256], outbuf[256]; |
JimmyTheHack | 0:b0ab03e03fdc | 127 | while (1) { |
JimmyTheHack | 0:b0ab03e03fdc | 128 | pc.gets(buf, 256); //grab serial commands |
JimmyTheHack | 0:b0ab03e03fdc | 129 | rpc(buf, outbuf); //interpret the RPC commands |
JimmyTheHack | 0:b0ab03e03fdc | 130 | //this function only requires an input string and output string, so we can obtain RPC commands via a different interface than serial if desired. |
JimmyTheHack | 0:b0ab03e03fdc | 131 | pc.printf("%s\n", outbuf); //print back over serial |
JimmyTheHack | 0:b0ab03e03fdc | 132 | } |
JimmyTheHack | 0:b0ab03e03fdc | 133 | } |
JimmyTheHack | 0:b0ab03e03fdc | 134 | |
JimmyTheHack | 0:b0ab03e03fdc | 135 | |
JimmyTheHack | 0:b0ab03e03fdc | 136 |