Ivo van Poorten
/
SiLabs_C2
Basis for the C2 protocol from Silicon Labs.
main.cpp@7:65a72aad87b8, 2014-05-25 (annotated)
- Committer:
- Ivop
- Date:
- Sun May 25 17:17:40 2014 +0000
- Revision:
- 7:65a72aad87b8
- Parent:
- 6:deb670cb8105
- Child:
- 8:af5d402396fb
better fatal() function (varargs version)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Ivop | 1:7a82f806fe92 | 1 | /* |
Ivop | 1:7a82f806fe92 | 2 | * SiLabs C2 Protocol on mbed pins p5/p6 |
Ivop | 1:7a82f806fe92 | 3 | * |
Ivop | 1:7a82f806fe92 | 4 | * Copyright (c) 2014, Ivo van Poorten <ivopvp@gmail.com> |
Ivop | 1:7a82f806fe92 | 5 | * All rights reserved. |
Ivop | 1:7a82f806fe92 | 6 | * |
Ivop | 1:7a82f806fe92 | 7 | * Redistribution and use in source and binary forms, with or without |
Ivop | 1:7a82f806fe92 | 8 | * modification, are permitted provided that the following conditions |
Ivop | 1:7a82f806fe92 | 9 | * are met: |
Ivop | 1:7a82f806fe92 | 10 | * 1. Redistributions of source code must retain the above copyright |
Ivop | 1:7a82f806fe92 | 11 | * notice, this list of conditions and the following disclaimer. |
Ivop | 1:7a82f806fe92 | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
Ivop | 1:7a82f806fe92 | 13 | * notice, this list of conditions and the following disclaimer in the |
Ivop | 1:7a82f806fe92 | 14 | * documentation and/or other materials provided with the distribution. |
Ivop | 1:7a82f806fe92 | 15 | * |
Ivop | 1:7a82f806fe92 | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
Ivop | 1:7a82f806fe92 | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
Ivop | 1:7a82f806fe92 | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
Ivop | 1:7a82f806fe92 | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
Ivop | 1:7a82f806fe92 | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
Ivop | 1:7a82f806fe92 | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
Ivop | 1:7a82f806fe92 | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
Ivop | 1:7a82f806fe92 | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
Ivop | 1:7a82f806fe92 | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
Ivop | 1:7a82f806fe92 | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Ivop | 1:7a82f806fe92 | 26 | */ |
Ivop | 1:7a82f806fe92 | 27 | |
Ivop | 0:902f10e5d3e0 | 28 | #include "mbed.h" |
Ivop | 7:65a72aad87b8 | 29 | #include <stdarg.h> |
Ivop | 0:902f10e5d3e0 | 30 | |
Ivop | 0:902f10e5d3e0 | 31 | DigitalOut c2ck(p5); |
Ivop | 0:902f10e5d3e0 | 32 | DigitalInOut c2d(p6); |
Ivop | 0:902f10e5d3e0 | 33 | |
Ivop | 4:a9e3ee5741be | 34 | static struct devices { |
Ivop | 4:a9e3ee5741be | 35 | char *name; |
Ivop | 4:a9e3ee5741be | 36 | int devid; |
Ivop | 4:a9e3ee5741be | 37 | } devices[] = { |
Ivop | 4:a9e3ee5741be | 38 | { "F30x", 0x04 }, |
Ivop | 4:a9e3ee5741be | 39 | { "F31x", 0x08 }, |
Ivop | 4:a9e3ee5741be | 40 | { "F32x", 0x09 }, |
Ivop | 4:a9e3ee5741be | 41 | { "F326/7", 0x0d }, |
Ivop | 4:a9e3ee5741be | 42 | { "F33x", 0x0a }, |
Ivop | 4:a9e3ee5741be | 43 | { "F336/7", 0x14 }, |
Ivop | 4:a9e3ee5741be | 44 | { "F34x", 0x0f }, |
Ivop | 4:a9e3ee5741be | 45 | { "F35x", 0x0b }, |
Ivop | 4:a9e3ee5741be | 46 | { "F36x", 0x12 }, |
Ivop | 4:a9e3ee5741be | 47 | { "F38x", 0x28 }, |
Ivop | 4:a9e3ee5741be | 48 | { "F39x/F37x", 0x2b }, |
Ivop | 4:a9e3ee5741be | 49 | { "F41x", 0x0c }, |
Ivop | 4:a9e3ee5741be | 50 | { "F50x/F51x", 0x1c }, |
Ivop | 4:a9e3ee5741be | 51 | { "F52xA/F53xA", 0x11 }, |
Ivop | 4:a9e3ee5741be | 52 | { "F54x", 0x21 }, |
Ivop | 4:a9e3ee5741be | 53 | { "F55x/F56x/F57x", 0x22 }, |
Ivop | 4:a9e3ee5741be | 54 | { "F58x/F59x", 0x20 }, |
Ivop | 4:a9e3ee5741be | 55 | { "F70x/F71x", 0x1e }, |
Ivop | 4:a9e3ee5741be | 56 | { "F80x/F81x/F82x/F83x", 0x23 }, |
Ivop | 4:a9e3ee5741be | 57 | { "F90x/F91x", 0x1f }, |
Ivop | 4:a9e3ee5741be | 58 | { "F92x/F93x", 0x16 }, |
Ivop | 4:a9e3ee5741be | 59 | { "F96x", 0x2a }, |
Ivop | 4:a9e3ee5741be | 60 | { "F99x", 0x25 }, |
Ivop | 4:a9e3ee5741be | 61 | { "T60x", 0x10 }, |
Ivop | 4:a9e3ee5741be | 62 | { "T606", 0x1b }, |
Ivop | 4:a9e3ee5741be | 63 | { "T61x", 0x13 }, |
Ivop | 4:a9e3ee5741be | 64 | { "T62x/T32x", 0x18 }, |
Ivop | 4:a9e3ee5741be | 65 | { "T622/T623/T326/T327", 0x19 }, |
Ivop | 4:a9e3ee5741be | 66 | { "T63x", 0x17 }, |
Ivop | 4:a9e3ee5741be | 67 | { NULL, 0 } |
Ivop | 4:a9e3ee5741be | 68 | }; |
Ivop | 4:a9e3ee5741be | 69 | |
Ivop | 6:deb670cb8105 | 70 | #define C2_MASK_FLBUSY 0x80 |
Ivop | 6:deb670cb8105 | 71 | #define C2_MASK_INBUSY 0x02 |
Ivop | 6:deb670cb8105 | 72 | #define C2_MASK_OUTREADY 0x01 |
Ivop | 6:deb670cb8105 | 73 | |
Ivop | 4:a9e3ee5741be | 74 | #define C2_DEVID 0 |
Ivop | 4:a9e3ee5741be | 75 | #define C2_REVID 1 |
Ivop | 4:a9e3ee5741be | 76 | #define C2_FPCTL 2 |
Ivop | 4:a9e3ee5741be | 77 | static int C2_FPDAT = 0xb4; // or 0xad |
Ivop | 4:a9e3ee5741be | 78 | static int page_size = 512; // not seen 4096 yet |
Ivop | 4:a9e3ee5741be | 79 | |
Ivop | 7:65a72aad87b8 | 80 | static void fatal(char *f, ...) { |
Ivop | 7:65a72aad87b8 | 81 | va_list ap; |
Ivop | 7:65a72aad87b8 | 82 | va_start(ap,f); |
Ivop | 7:65a72aad87b8 | 83 | printf("\n\rFATAL: "); |
Ivop | 7:65a72aad87b8 | 84 | vprintf(f, ap); |
Ivop | 7:65a72aad87b8 | 85 | va_end(ap); |
Ivop | 7:65a72aad87b8 | 86 | exit(1); |
Ivop | 7:65a72aad87b8 | 87 | } |
Ivop | 7:65a72aad87b8 | 88 | |
Ivop | 1:7a82f806fe92 | 89 | static void c2ck_reset(void) { |
Ivop | 1:7a82f806fe92 | 90 | c2ck = 0; |
Ivop | 1:7a82f806fe92 | 91 | wait_us(25); |
Ivop | 1:7a82f806fe92 | 92 | c2ck = 1; |
Ivop | 1:7a82f806fe92 | 93 | wait_us(1); |
Ivop | 1:7a82f806fe92 | 94 | } |
Ivop | 1:7a82f806fe92 | 95 | |
Ivop | 1:7a82f806fe92 | 96 | static void c2ck_strobe(void) { |
Ivop | 1:7a82f806fe92 | 97 | c2ck = 0; |
Ivop | 1:7a82f806fe92 | 98 | wait_us(1); |
Ivop | 1:7a82f806fe92 | 99 | c2ck = 1; |
Ivop | 1:7a82f806fe92 | 100 | wait_us(1); |
Ivop | 1:7a82f806fe92 | 101 | } |
Ivop | 1:7a82f806fe92 | 102 | |
Ivop | 1:7a82f806fe92 | 103 | // Four basic C2 Instructions |
Ivop | 1:7a82f806fe92 | 104 | // |
Ivop | 1:7a82f806fe92 | 105 | // 00b Data Read |
Ivop | 1:7a82f806fe92 | 106 | // 01b Data Write |
Ivop | 1:7a82f806fe92 | 107 | // 10b Address Read |
Ivop | 1:7a82f806fe92 | 108 | // 11b Address Write |
Ivop | 2:9092d0d1558b | 109 | // |
Ivop | 2:9092d0d1558b | 110 | // Remember, ALL fields are sent LSB first(!) |
Ivop | 1:7a82f806fe92 | 111 | |
Ivop | 2:9092d0d1558b | 112 | #define START do{ c2ck_strobe(); }while(0) |
Ivop | 2:9092d0d1558b | 113 | #define STOP START |
Ivop | 2:9092d0d1558b | 114 | #define INS(a,b) do{ c2d = a; c2ck_strobe(); c2d = b; c2ck_strobe(); }while(0) |
Ivop | 2:9092d0d1558b | 115 | #define LENGTH(a,b) INS(a,b) |
Ivop | 2:9092d0d1558b | 116 | #define WAIT do{\ |
Ivop | 2:9092d0d1558b | 117 | while(t-- && !c2d) { \ |
Ivop | 2:9092d0d1558b | 118 | c2ck_strobe(); \ |
Ivop | 2:9092d0d1558b | 119 | wait_us(1); \ |
Ivop | 2:9092d0d1558b | 120 | } if (!t) return -1; \ |
Ivop | 2:9092d0d1558b | 121 | } while(0) |
Ivop | 4:a9e3ee5741be | 122 | #define READV do{\ |
Ivop | 4:a9e3ee5741be | 123 | for (i=0; i<8; i++) { \ |
Ivop | 4:a9e3ee5741be | 124 | v >>= 1; \ |
Ivop | 4:a9e3ee5741be | 125 | c2ck_strobe(); \ |
Ivop | 4:a9e3ee5741be | 126 | if (c2d) v |= 0x80; \ |
Ivop | 4:a9e3ee5741be | 127 | } } while(0) |
Ivop | 4:a9e3ee5741be | 128 | #define WRITEV do{\ |
Ivop | 4:a9e3ee5741be | 129 | for(i=0; i<8; i++) { \ |
Ivop | 4:a9e3ee5741be | 130 | c2d = v & 1; \ |
Ivop | 4:a9e3ee5741be | 131 | c2ck_strobe(); \ |
Ivop | 4:a9e3ee5741be | 132 | v >>= 1; \ |
Ivop | 4:a9e3ee5741be | 133 | } } while(0) |
Ivop | 2:9092d0d1558b | 134 | |
Ivop | 2:9092d0d1558b | 135 | static int c2_read_dr(void) { |
Ivop | 4:a9e3ee5741be | 136 | int t = 20, i, v = 0; |
Ivop | 2:9092d0d1558b | 137 | |
Ivop | 2:9092d0d1558b | 138 | START; |
Ivop | 2:9092d0d1558b | 139 | c2d.output(); |
Ivop | 2:9092d0d1558b | 140 | INS(0,0); |
Ivop | 2:9092d0d1558b | 141 | LENGTH(0,0); |
Ivop | 2:9092d0d1558b | 142 | c2d.input(); |
Ivop | 2:9092d0d1558b | 143 | WAIT; |
Ivop | 4:a9e3ee5741be | 144 | READV; |
Ivop | 2:9092d0d1558b | 145 | STOP; |
Ivop | 2:9092d0d1558b | 146 | |
Ivop | 4:a9e3ee5741be | 147 | return v; |
Ivop | 2:9092d0d1558b | 148 | } |
Ivop | 2:9092d0d1558b | 149 | |
Ivop | 4:a9e3ee5741be | 150 | static int c2_write_dr(int v) { |
Ivop | 2:9092d0d1558b | 151 | int t = 20, i; |
Ivop | 2:9092d0d1558b | 152 | |
Ivop | 2:9092d0d1558b | 153 | START; |
Ivop | 2:9092d0d1558b | 154 | c2d.output(); |
Ivop | 2:9092d0d1558b | 155 | INS(1,0); |
Ivop | 2:9092d0d1558b | 156 | LENGTH(0,0); |
Ivop | 4:a9e3ee5741be | 157 | WRITEV; |
Ivop | 2:9092d0d1558b | 158 | c2d.input(); |
Ivop | 2:9092d0d1558b | 159 | WAIT; |
Ivop | 2:9092d0d1558b | 160 | STOP; |
Ivop | 2:9092d0d1558b | 161 | |
Ivop | 2:9092d0d1558b | 162 | return 0; |
Ivop | 2:9092d0d1558b | 163 | } |
Ivop | 2:9092d0d1558b | 164 | |
Ivop | 2:9092d0d1558b | 165 | static int c2_read_ar(void) { |
Ivop | 4:a9e3ee5741be | 166 | int i, v = 0; |
Ivop | 2:9092d0d1558b | 167 | |
Ivop | 2:9092d0d1558b | 168 | START; |
Ivop | 2:9092d0d1558b | 169 | c2d.output(); |
Ivop | 2:9092d0d1558b | 170 | INS(0,1); |
Ivop | 2:9092d0d1558b | 171 | c2d.input(); |
Ivop | 4:a9e3ee5741be | 172 | READV; |
Ivop | 4:a9e3ee5741be | 173 | STOP; |
Ivop | 2:9092d0d1558b | 174 | |
Ivop | 4:a9e3ee5741be | 175 | return v; |
Ivop | 2:9092d0d1558b | 176 | } |
Ivop | 2:9092d0d1558b | 177 | |
Ivop | 4:a9e3ee5741be | 178 | static void c2_write_ar(int v) { |
Ivop | 2:9092d0d1558b | 179 | int i; |
Ivop | 2:9092d0d1558b | 180 | |
Ivop | 2:9092d0d1558b | 181 | START; |
Ivop | 2:9092d0d1558b | 182 | c2d.output(); |
Ivop | 2:9092d0d1558b | 183 | INS(1,1); |
Ivop | 4:a9e3ee5741be | 184 | WRITEV; |
Ivop | 2:9092d0d1558b | 185 | c2d.input(); |
Ivop | 2:9092d0d1558b | 186 | STOP; |
Ivop | 2:9092d0d1558b | 187 | } |
Ivop | 1:7a82f806fe92 | 188 | |
Ivop | 6:deb670cb8105 | 189 | static int poll_status(int mask) { |
Ivop | 6:deb670cb8105 | 190 | int t = 20; |
Ivop | 6:deb670cb8105 | 191 | do { |
Ivop | 6:deb670cb8105 | 192 | if (!(c2_read_ar() & mask)) return 0; |
Ivop | 6:deb670cb8105 | 193 | wait_us(1); |
Ivop | 6:deb670cb8105 | 194 | } while(--t); |
Ivop | 6:deb670cb8105 | 195 | return -1; |
Ivop | 6:deb670cb8105 | 196 | } |
Ivop | 7:65a72aad87b8 | 197 | |
Ivop | 0:902f10e5d3e0 | 198 | int main() { |
Ivop | 4:a9e3ee5741be | 199 | int i, c, devid, revid; |
Ivop | 1:7a82f806fe92 | 200 | |
Ivop | 1:7a82f806fe92 | 201 | c2d.input(); |
Ivop | 1:7a82f806fe92 | 202 | c2ck = 1; |
Ivop | 1:7a82f806fe92 | 203 | |
Ivop | 4:a9e3ee5741be | 204 | printf("\033[H\033[J"); |
Ivop | 1:7a82f806fe92 | 205 | printf("SiLabs C2 Protocol\n\r\n\r"); |
Ivop | 1:7a82f806fe92 | 206 | printf("Connect C2CK (clock) to p5 and C2D (data) to p6\n\r\n\r"); |
Ivop | 1:7a82f806fe92 | 207 | printf("Press any key to continue\n\r"); |
Ivop | 4:a9e3ee5741be | 208 | |
Ivop | 4:a9e3ee5741be | 209 | getc(stdin); |
Ivop | 3:b30605f1c435 | 210 | |
Ivop | 5:53d4a67cd657 | 211 | c2_write_ar(C2_DEVID); |
Ivop | 3:b30605f1c435 | 212 | devid = c2_read_dr(); |
Ivop | 5:53d4a67cd657 | 213 | if (devid <= 0) fatal("unable to read devid\n\r"); |
Ivop | 1:7a82f806fe92 | 214 | |
Ivop | 5:53d4a67cd657 | 215 | c2_write_ar(C2_REVID); |
Ivop | 3:b30605f1c435 | 216 | revid = c2_read_dr(); |
Ivop | 3:b30605f1c435 | 217 | if (revid < 0) fatal("unable to read revid\n\r"); |
Ivop | 3:b30605f1c435 | 218 | |
Ivop | 4:a9e3ee5741be | 219 | for (i=0; devices[i].name; i++) { |
Ivop | 4:a9e3ee5741be | 220 | if (devices[i].devid == devid) break; |
Ivop | 4:a9e3ee5741be | 221 | } |
Ivop | 4:a9e3ee5741be | 222 | |
Ivop | 7:65a72aad87b8 | 223 | if (!i) fatal("unknown device: %02X:%02X\n\r", devid, revid); |
Ivop | 4:a9e3ee5741be | 224 | |
Ivop | 4:a9e3ee5741be | 225 | switch(devid) { |
Ivop | 4:a9e3ee5741be | 226 | case 0x0f: case 0x28: case 0x18: case 0x19: C2_FPDAT = 0xad; |
Ivop | 4:a9e3ee5741be | 227 | default: break; |
Ivop | 4:a9e3ee5741be | 228 | } |
Ivop | 4:a9e3ee5741be | 229 | |
Ivop | 4:a9e3ee5741be | 230 | printf("\n\rDevice found: %s (%02X:%02X)", devices[i].name, devid, revid); |
Ivop | 4:a9e3ee5741be | 231 | printf("\n\rFPDAT Address: 0x%02X", C2_FPDAT); |
Ivop | 4:a9e3ee5741be | 232 | printf("\n\rPage Size: %i\n\r", page_size); |
Ivop | 4:a9e3ee5741be | 233 | } |