diff options
author | Dave Hodder <dave.hodder@focusrite.com> | 2017-11-20 13:54:16 +0000 |
---|---|---|
committer | Dave Hodder <dave.hodder@focusrite.com> | 2017-11-20 13:54:16 +0000 |
commit | d910a607b308c5ed02e476a5051fac184f61c86f (patch) | |
tree | da05174d3c8c6846359e4d16f0cee06bb4703aba | |
parent | af0c758cceb310b69c9192d7cdc8133ba63a3f98 (diff) | |
parent | 7ff741e4206b75e941aa982360402bc8f8e58198 (diff) | |
download | launchpad-polymaker-d910a607b308c5ed02e476a5051fac184f61c86f.tar.gz launchpad-polymaker-d910a607b308c5ed02e476a5051fac184f61c86f.zip |
Merge branch 'raw-adc' (bringing in ADC and flash access)
-rw-r--r-- | README.md | 17 | ||||
-rw-r--r-- | include/app.h | 43 | ||||
-rw-r--r-- | include/app_defs.h | 28 | ||||
-rw-r--r-- | lib/launchpad_pro.a | bin | 16869730 -> 16874030 bytes | |||
-rw-r--r-- | src/app.c | 153 | ||||
-rw-r--r-- | tools/simulator.c | 14 |
6 files changed, 179 insertions, 76 deletions
@@ -9,8 +9,6 @@ Open source firmware for the Novation Launchpad Pro grid controller! By customi | |||
9 | 9 | ||
10 | You'll definitely need *some* C programming experience, but we've deliberately kept much of the firmwarey nastiness tucked away, to make the process a little friendlier. | 10 | You'll definitely need *some* C programming experience, but we've deliberately kept much of the firmwarey nastiness tucked away, to make the process a little friendlier. |
11 | 11 | ||
12 | This project is still at an early stage, and no "interesting" example apps have yet been developed. You might want to hang on until there's something more detailed before you get stuck in. Or not! | ||
13 | |||
14 | # Philosophy | 12 | # Philosophy |
15 | We could have released the full source for the factory shipping firmware, but we decided not to for a variety of reasons. Instead, we created a simplified framework for developing "apps" on Launchpad Pro, which comprises a build environment, application entry points / API, and a library of low level source code. Our reasoning is as follows: | 13 | We could have released the full source for the factory shipping firmware, but we decided not to for a variety of reasons. Instead, we created a simplified framework for developing "apps" on Launchpad Pro, which comprises a build environment, application entry points / API, and a library of low level source code. Our reasoning is as follows: |
16 | 14 | ||
@@ -71,9 +69,9 @@ Once your new "box" is up and running, you can build the app in one of two ways. | |||
71 | 69 | ||
72 | Either of the above methods will generate the firmware image, `launchpad_pro.syx`, in the project `build` directory. You can then upload this to your Launchpad Pro from the host! | 70 | Either of the above methods will generate the firmware image, `launchpad_pro.syx`, in the project `build` directory. You can then upload this to your Launchpad Pro from the host! |
73 | 71 | ||
74 | ## Using OS X | 72 | ## Using macOS |
75 | 73 | ||
76 | On OS X you can easily install the GCC ARM toolchain using the [homebrew package manager](http://brew.sh). The EABI tools are maintained in an external repository which you need to put on tap first. You can then run ```make``` to directly compile the code: | 74 | On macOS you can easily install the GCC ARM toolchain using the [homebrew package manager](http://brew.sh). The EABI tools are maintained in an external repository which you need to put on tap first. You can then run ```make``` to directly compile the code: |
77 | 75 | ||
78 | ``` | 76 | ``` |
79 | brew tap PX4/homebrew-px4 | 77 | brew tap PX4/homebrew-px4 |
@@ -82,7 +80,7 @@ make | |||
82 | ``` | 80 | ``` |
83 | 81 | ||
84 | # Uploading to a Launchpad Pro | 82 | # Uploading to a Launchpad Pro |
85 | Now you've got some nice new code to run! To upload it to your Launchpad Pro, you'll need a sysex tool for your host platform (I'd love to get it working from the virtual machine, but that's for later). I recommend [Sysex Librarian](http://www.snoize.com/SysExLibrarian/) on OS X, and [MIDI OX](http://www.midiox.com/) on Windows. On Linux, I'll bet you already have a tool in mind. | 83 | Now you've got some nice new code to run! To upload it to your Launchpad Pro, you'll need a sysex tool for your host platform (I'd love to get it working from the virtual machine, but that's for later). I recommend [Sysex Librarian](http://www.snoize.com/SysExLibrarian/) on macOS, and [MIDI OX](http://www.midiox.com/) on Windows. On Linux, I'll bet you already have a tool in mind. |
86 | 84 | ||
87 | I won't describe how to use these tools, I'm sure you already know - and if you don't, their documentation is superior to mine! Here's what you need to do: | 85 | I won't describe how to use these tools, I'm sure you already know - and if you don't, their documentation is superior to mine! Here's what you need to do: |
88 | 86 | ||
@@ -109,17 +107,16 @@ By calling into the HAL, your app can: | |||
109 | 107 | ||
110 | - Write colours to the LEDs | 108 | - Write colours to the LEDs |
111 | - Send messages to the MIDI/USB ports | 109 | - Send messages to the MIDI/USB ports |
110 | - Store and recall a little bit of data on the Launchpad Pro's flash memory | ||
112 | 111 | ||
113 | The best way to learn about these is to read the documentation in `app.h`, and to study the (very basic) example code! | 112 | The best way to learn about these is to read the documentation in `app.h`, and to study the (very basic) example code! |
114 | 113 | ||
115 | Currently the HAL/app interface does not support reading or writing the flash memory. | ||
116 | |||
117 | # Debugging | 114 | # Debugging |
118 | We decided not to support or encourage using a hardware debugger, as opening a Launchpad Pro to fit a debugging header can easily damage the FSR (force sensitive resistor) sheet. | 115 | We decided not to support or encourage using a hardware debugger, as opening a Launchpad Pro to fit a debugging header can easily damage the FSR (force sensitive resistor) sheet. |
119 | 116 | ||
120 | Instead, you're going to have to do things the old fashioned way - by blinking LEDs or sending MIDI messages (though hopefully no need for a 'scope!). For what it's worth, that's the way I've developed this version of the firmware - dogfooding all the way ;) | 117 | Instead, you're going to have to do things the old fashioned way - by blinking LEDs or sending MIDI messages (though hopefully no need for a 'scope!). For what it's worth, that's the way I've developed this version of the firmware - dogfooding all the way ;) |
121 | 118 | ||
122 | If do you want to debug interactively (and of course you do), you can use the interactive desktop simulator on OS X. | 119 | If do you want to debug interactively (and of course you do), you can use the interactive desktop simulator on macOS: |
123 | 120 | ||
124 | 1. Build the Xcode project located in `/tools/osx` | 121 | 1. Build the Xcode project located in `/tools/osx` |
125 | 2. Connect your Launchpad Pro | 122 | 2. Connect your Launchpad Pro |
@@ -127,7 +124,7 @@ If do you want to debug interactively (and of course you do), you can use the in | |||
127 | 4. Put the Launchpad Pro into "Programmer" mode using the Setup button (you'll get odd behaviour otherwise) | 124 | 4. Put the Launchpad Pro into "Programmer" mode using the Setup button (you'll get odd behaviour otherwise) |
128 | 5. Start debugging in Xcode! | 125 | 5. Start debugging in Xcode! |
129 | 126 | ||
130 | Currently it only supports button presses and LED messages - there's no virtual MIDI IO, setup button or aftertouch (yet). It has a really awful busywaiting timer for the 1kHz tick. However, it does allow you to debug your application logic using Xcode! | 127 | Currently it only supports button presses and LED messages - there's no setup button, flash storage or aftertouch (yet). It has a really awful busywaiting timer for the 1kHz tick. However, it does allow you to debug your application logic using Xcode! |
131 | 128 | ||
132 | You can also use the simple command-line simulator located in the `/tools` directory. It is compiled and ran as part of the build process, so it serves as a very basic test of your app before it is baked into a sysex dump - more of a test harness. | 129 | You can also use the simple command-line simulator located in the `/tools` directory. It is compiled and ran as part of the build process, so it serves as a very basic test of your app before it is baked into a sysex dump - more of a test harness. |
133 | 130 | ||
@@ -142,7 +139,7 @@ To debug the simulator interactively in Eclipse: | |||
142 | # The Hardware | 139 | # The Hardware |
143 | The Launchpad Pro is based around an ARM Cortex M3 from STMicroelectronics. Specifically, an [STM32F103RBT6](http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1031/LN1565/PF164487). It's clocked at 72MHz, and has 20k RAM (I'm not sure how much of this we're using in the open build yet - should be a fair amount left but I haven't measured it). The low level LED multiplexing and pad/switch scanning consume a fair bit of CPU time in interrupt mode, but have changed a little in the open firmware library (so again, I don't have measurements for how many cycles they're using). | 140 | The Launchpad Pro is based around an ARM Cortex M3 from STMicroelectronics. Specifically, an [STM32F103RBT6](http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1031/LN1565/PF164487). It's clocked at 72MHz, and has 20k RAM (I'm not sure how much of this we're using in the open build yet - should be a fair amount left but I haven't measured it). The low level LED multiplexing and pad/switch scanning consume a fair bit of CPU time in interrupt mode, but have changed a little in the open firmware library (so again, I don't have measurements for how many cycles they're using). |
144 | 141 | ||
145 | It has 128k of flash memory, but I'm pretty sure we won't be exposing all of it as part of this API (dangerously easy to corrupt things!). Current thinking is to expose a few pages for use by apps, though this would still introduce risks (accidentally wearing out sectors, for example). To be continued... | 142 | It has 128k of flash memory, but we won't be exposing all of it as part of this API (dangerously easy to corrupt things!). |
146 | 143 | ||
147 | # Vagrant tips | 144 | # Vagrant tips |
148 | When you're done developing, simply type `vagrant suspend` to halt your VM without destroying it - this will make `vagrant up` a lot quicker next time. If you're really finished, `vagrant destroy` will completely remove the VM from your system (but not any of your code). | 145 | When you're done developing, simply type `vagrant suspend` to halt your VM without destroying it - this will make `vagrant up` a lot quicker next time. If you're really finished, `vagrant destroy` will completely remove the VM from your system (but not any of your code). |
diff --git a/include/app.h b/include/app.h index ed946d5..96801eb 100644 --- a/include/app.h +++ b/include/app.h | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | /****************************************************************************** | 44 | /****************************************************************************** |
45 | Button indexing is as follows - numbers in brackets do not correspond to real | 45 | Button indexing is as follows - numbers in brackets do not correspond to real |
46 | buttons, but can be harmessly sent in hal_set_led. | 46 | buttons, but can be harmessly sent in hal_set_led. |
47 | 47 | ||
48 | (90)91 92 93 94 95 96 97 98 (99) | 48 | (90)91 92 93 94 95 96 97 98 (99) |
49 | ....... | 49 | ....... |
@@ -92,6 +92,40 @@ void hal_send_midi(u8 port, u8 status, u8 data1, u8 data2); | |||
92 | */ | 92 | */ |
93 | void hal_send_sysex(u8 port, const u8* data, u16 length); | 93 | void hal_send_sysex(u8 port, const u8* data, u16 length); |
94 | 94 | ||
95 | /** | ||
96 | * Read some data from flash. | ||
97 | * | ||
98 | * Flash storage is in a single block, currently corresponding to one page. | ||
99 | * The block is always USER_AREA_SIZE bytes long. You can read/write any bytes | ||
100 | * within it - you do not need to worry about paging, that's handled by the HAL. | ||
101 | * | ||
102 | * The block size may increase to span multiple pages in future :) | ||
103 | * | ||
104 | * @param offset - how far into the USER_AREA_SIZE byte block to start reading | ||
105 | * @param data - buffer to receive data (must be at least length bytes long) | ||
106 | * @param length - bytes to read | ||
107 | * | ||
108 | * Attempts to read beyond the end of the block will fail silently. | ||
109 | * | ||
110 | * Note that your first ever read from a new device will contain 0xFF's until | ||
111 | * you overwrite them. | ||
112 | */ | ||
113 | void hal_read_flash(u32 offset, u8 *data, u32 length); | ||
114 | |||
115 | /** | ||
116 | * Write data to flash | ||
117 | * | ||
118 | * Do take care to avoid thrashing it, as you can wear it out with excessive | ||
119 | * writes. The HAL does not currently do anything clever to mitigate this. | ||
120 | * | ||
121 | * @param offset - how far into the USER_AREA_SIZE byte block to start writing | ||
122 | * @param data - buffer to write (must be at least length bytes long) | ||
123 | * @param length - bytes to write | ||
124 | * | ||
125 | * Attempts to write beyond the end of the block will fail silently | ||
126 | */ | ||
127 | void hal_write_flash(u32 offset,const u8 *data, u32 length); | ||
128 | |||
95 | // ____________________________________________________________________________ | 129 | // ____________________________________________________________________________ |
96 | // | 130 | // |
97 | // Callbacks from the hardware (implemented in your app.c) | 131 | // Callbacks from the hardware (implemented in your app.c) |
@@ -99,8 +133,13 @@ void hal_send_sysex(u8 port, const u8* data, u16 length); | |||
99 | 133 | ||
100 | /** | 134 | /** |
101 | * Called on startup, this is a good place to do any initialisation. | 135 | * Called on startup, this is a good place to do any initialisation. |
136 | * | ||
137 | * @param adc_buffer - this is a pointer to the raw ADC frame buffer. The | ||
138 | * data is 12 bit unsigned. Note the indexing is strange - | ||
139 | * translate ADC indices to LED/button indices using the | ||
140 | * ADC_MAP table declared in app_defs.h. | ||
102 | */ | 141 | */ |
103 | void app_init(); | 142 | void app_init(const u16 *adc_buffer); |
104 | 143 | ||
105 | /** | 144 | /** |
106 | * 1kHz (1ms) timer. You can set LEDs and send MIDI out from this function, | 145 | * 1kHz (1ms) timer. You can set LEDs and send MIDI out from this function, |
diff --git a/include/app_defs.h b/include/app_defs.h index 829f8a6..d9b4311 100644 --- a/include/app_defs.h +++ b/include/app_defs.h | |||
@@ -100,5 +100,33 @@ typedef unsigned char u8; | |||
100 | #define MIDI_OUT_CABLE 1 | 100 | #define MIDI_OUT_CABLE 1 |
101 | 101 | ||
102 | // ____________________________________________________________________________ | 102 | // ____________________________________________________________________________ |
103 | // | ||
104 | // Flash storage | ||
105 | // ____________________________________________________________________________ | ||
106 | |||
107 | #define USER_AREA_SIZE 1024 | ||
108 | |||
109 | // ____________________________________________________________________________ | ||
110 | // | ||
111 | // Raw ADC reads. For technical reasons, the ADC layout is not the same as the | ||
112 | // LED layout. Be sure to translate ADC values using the table below as you | ||
113 | // need them! | ||
114 | // ____________________________________________________________________________ | ||
115 | |||
116 | #define PAD_COUNT 64 | ||
117 | |||
118 | static const u8 ADC_MAP[PAD_COUNT] = | ||
119 | { | ||
120 | 11, 51, 12, 52, 13, 53, 14, 54, | ||
121 | 15, 55, 16, 56, 17 ,57, 18, 58, | ||
122 | 21, 61, 22, 62, 23, 63, 24, 64, | ||
123 | 25, 65, 26, 66, 27, 67, 28, 68, | ||
124 | 31, 71, 32, 72, 33, 73, 34, 74, | ||
125 | 35, 75, 36, 76, 37, 77, 38, 78, | ||
126 | 41, 81, 42, 82, 43, 83, 44, 84, | ||
127 | 45, 85, 46, 86, 47, 87, 48, 88, | ||
128 | }; | ||
129 | |||
130 | // ____________________________________________________________________________ | ||
103 | 131 | ||
104 | #endif | 132 | #endif |
diff --git a/lib/launchpad_pro.a b/lib/launchpad_pro.a index 712626d..c2c9af2 100644 --- a/lib/launchpad_pro.a +++ b/lib/launchpad_pro.a | |||
Binary files differ | |||
@@ -41,51 +41,57 @@ | |||
41 | // | 41 | // |
42 | // This is where the fun is! Add your code to the callbacks below to define how | 42 | // This is where the fun is! Add your code to the callbacks below to define how |
43 | // your app behaves. | 43 | // your app behaves. |
44 | // | ||
45 | // In this example, we render the raw ADC data as LED rainbows. | ||
46 | //______________________________________________________________________________ | ||
47 | |||
48 | static const u16 *g_ADC = 0; | ||
49 | |||
44 | //______________________________________________________________________________ | 50 | //______________________________________________________________________________ |
45 | 51 | ||
46 | void app_surface_event(u8 type, u8 index, u8 value) | 52 | void app_surface_event(u8 type, u8 index, u8 value) |
47 | { | 53 | { |
48 | switch (type) | 54 | switch (type) |
49 | { | 55 | { |
50 | case TYPEPAD: | 56 | case TYPEPAD: |
51 | { | 57 | { |
52 | // example - light / extinguish pad LEDs, send MIDI | 58 | // example - light / extinguish pad LEDs, send MIDI |
53 | hal_plot_led(TYPEPAD, index, value, value, value); | 59 | hal_plot_led(TYPEPAD, index, value, value, value); |
54 | hal_send_midi(DINMIDI, NOTEON | 0, index, value); | 60 | hal_send_midi(DINMIDI, NOTEON | 0, index, value); |
55 | } | 61 | } |
56 | break; | 62 | break; |
57 | 63 | ||
58 | case TYPESETUP: | 64 | case TYPESETUP: |
59 | { | 65 | { |
60 | // example - light the setup LED | 66 | // example - light the setup LED |
61 | hal_plot_led(TYPESETUP, 0, value, value, value); | 67 | hal_plot_led(TYPESETUP, 0, value, value, value); |
62 | } | 68 | } |
63 | break; | 69 | break; |
64 | } | 70 | } |
65 | } | 71 | } |
66 | 72 | ||
67 | //______________________________________________________________________________ | 73 | //______________________________________________________________________________ |
68 | 74 | ||
69 | void app_midi_event(u8 port, u8 status, u8 d1, u8 d2) | 75 | void app_midi_event(u8 port, u8 status, u8 d1, u8 d2) |
70 | { | 76 | { |
71 | // example - MIDI interface functionality for USB "MIDI" port -> DIN port | 77 | // example - MIDI interface functionality for USB "MIDI" port -> DIN port |
72 | if (port == USBMIDI) | 78 | if (port == USBMIDI) |
73 | { | 79 | { |
74 | hal_send_midi(DINMIDI, status, d1, d2); | 80 | hal_send_midi(DINMIDI, status, d1, d2); |
75 | } | 81 | } |
76 | 82 | ||
77 | // // example -MIDI interface functionality for DIN -> USB "MIDI" port port | 83 | // // example -MIDI interface functionality for DIN -> USB "MIDI" port port |
78 | if (port == DINMIDI) | 84 | if (port == DINMIDI) |
79 | { | 85 | { |
80 | hal_send_midi(USBMIDI, status, d1, d2); | 86 | hal_send_midi(USBMIDI, status, d1, d2); |
81 | } | 87 | } |
82 | } | 88 | } |
83 | 89 | ||
84 | //______________________________________________________________________________ | 90 | //______________________________________________________________________________ |
85 | 91 | ||
86 | void app_sysex_event(u8 port, u8 * data, u16 count) | 92 | void app_sysex_event(u8 port, u8 * data, u16 count) |
87 | { | 93 | { |
88 | // example - respond to UDI messages? | 94 | // example - respond to UDI messages? |
89 | } | 95 | } |
90 | 96 | ||
91 | //______________________________________________________________________________ | 97 | //______________________________________________________________________________ |
@@ -93,60 +99,81 @@ void app_sysex_event(u8 port, u8 * data, u16 count) | |||
93 | void app_aftertouch_event(u8 index, u8 value) | 99 | void app_aftertouch_event(u8 index, u8 value) |
94 | { | 100 | { |
95 | // example - send poly aftertouch to MIDI ports | 101 | // example - send poly aftertouch to MIDI ports |
96 | hal_send_midi(USBMIDI, POLYAFTERTOUCH | 0, index, value); | 102 | hal_send_midi(USBMIDI, POLYAFTERTOUCH | 0, index, value); |
97 | 103 | ||
98 | // example - set LED to white, brightness in proportion to pressure | 104 | // example - set LED to white, brightness in proportion to pressure |
99 | hal_plot_led(TYPEPAD, index, value/2, value/2, value/2); | 105 | hal_plot_led(TYPEPAD, index, value/2, value/2, value/2); |
100 | } | 106 | } |
101 | 107 | ||
102 | //______________________________________________________________________________ | 108 | //______________________________________________________________________________ |
103 | 109 | ||
104 | void app_cable_event(u8 type, u8 value) | 110 | void app_cable_event(u8 type, u8 value) |
105 | { | 111 | { |
106 | // example - light the Setup LED to indicate cable connections | 112 | // example - light the Setup LED to indicate cable connections |
107 | if (type == MIDI_IN_CABLE) | 113 | if (type == MIDI_IN_CABLE) |
108 | { | 114 | { |
109 | hal_plot_led(TYPESETUP, 0, 0, value, 0); // green | 115 | hal_plot_led(TYPESETUP, 0, 0, value, 0); // green |
110 | } | 116 | } |
111 | else if (type == MIDI_OUT_CABLE) | 117 | else if (type == MIDI_OUT_CABLE) |
112 | { | 118 | { |
113 | hal_plot_led(TYPESETUP, 0, value, 0, 0); // red | 119 | hal_plot_led(TYPESETUP, 0, value, 0, 0); // red |
114 | } | 120 | } |
115 | } | 121 | } |
116 | 122 | ||
117 | //______________________________________________________________________________ | 123 | //______________________________________________________________________________ |
118 | 124 | ||
119 | |||
120 | void app_timer_event() | 125 | void app_timer_event() |
121 | { | 126 | { |
122 | // example - send MIDI clock at 125bpm | 127 | // example - send MIDI clock at 125bpm |
123 | #define TICK_MS 20 | 128 | #define TICK_MS 20 |
124 | 129 | ||
125 | static u8 ms = TICK_MS; | 130 | static u8 ms = TICK_MS; |
126 | 131 | ||
127 | if (++ms >= TICK_MS) | 132 | if (++ms >= TICK_MS) |
133 | { | ||
134 | ms = 0; | ||
135 | |||
136 | // send a clock pulse up the USB | ||
137 | hal_send_midi(USBSTANDALONE, MIDITIMINGCLOCK, 0, 0); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | // alternative example - show raw ADC data as LEDs | ||
142 | for (int i=0; i < PAD_COUNT; ++i) | ||
128 | { | 143 | { |
129 | ms = 0; | 144 | // raw adc values are 12 bit, but LEDs are 6 bit. |
145 | // Let's saturate into r;g;b for a rainbow effect to show pressure | ||
146 | u16 r = 0; | ||
147 | u16 g = 0; | ||
148 | u16 b = 0; | ||
149 | |||
150 | u16 x = (3 * MAXLED * g_ADC[i]) >> 12; | ||
151 | |||
152 | if (x < MAXLED) | ||
153 | { | ||
154 | r = x; | ||
155 | } | ||
156 | else if (x >= MAXLED && x < (2*MAXLED)) | ||
157 | { | ||
158 | r = MAXLED - x; | ||
159 | g = x - MAXLED; | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | g = MAXLED - x; | ||
164 | b = x - MAXLED; | ||
165 | } | ||
130 | 166 | ||
131 | // send a clock pulse up the USB | 167 | hal_plot_led(TYPEPAD, ADC_MAP[i], r, g, b); |
132 | hal_send_midi(USBSTANDALONE, MIDITIMINGCLOCK, 0, 0); | ||
133 | } | 168 | } |
169 | */ | ||
134 | } | 170 | } |
135 | 171 | ||
136 | //______________________________________________________________________________ | 172 | //______________________________________________________________________________ |
137 | 173 | ||
138 | void app_init() | 174 | void app_init(const u16 *adc_raw) |
139 | { | 175 | { |
140 | // example - light the LEDs to say hello! | 176 | |
141 | for (int i=0; i < 10; ++i) | 177 | // store off the raw ADC frame pointer for later use |
142 | { | 178 | g_ADC = adc_raw; |
143 | for (int j=0; j < 10; ++j) | ||
144 | { | ||
145 | u8 r = i < 5 ? (MAXLED * (5-i))/5 : 0; | ||
146 | u8 g = i < 5 ? (MAXLED * i)/5 : (MAXLED * (10-i))/5; | ||
147 | u8 b = i < 5 ? 0 : (MAXLED * (i-5))/5; | ||
148 | |||
149 | hal_plot_led(TYPEPAD, j*10 + i, r, b, g); | ||
150 | } | ||
151 | } | ||
152 | } | 179 | } |
diff --git a/tools/simulator.c b/tools/simulator.c index 56298d7..138277e 100644 --- a/tools/simulator.c +++ b/tools/simulator.c | |||
@@ -57,16 +57,28 @@ void hal_send_sysex(u8 port, const u8* data, u16 length) | |||
57 | printf("...hal_send_midi(%d, (data), %d);\n", port, length); | 57 | printf("...hal_send_midi(%d, (data), %d);\n", port, length); |
58 | } | 58 | } |
59 | 59 | ||
60 | void hal_read_flash(u32 offset, u8 *data, u32 length) | ||
61 | { | ||
62 | printf("...hal_read_flash(%d, (data), %d);\n", offset, length); | ||
63 | } | ||
64 | |||
65 | void hal_write_flash(u32 offset,const u8 *data, u32 length) | ||
66 | { | ||
67 | printf("...hal_write_flash(%d, (data), %d);\n", offset, length); | ||
68 | } | ||
69 | |||
60 | // ____________________________________________________________________________ | 70 | // ____________________________________________________________________________ |
61 | // | 71 | // |
62 | // App event wrappers - these just log to the console. Would be nice to wire | 72 | // App event wrappers - these just log to the console. Would be nice to wire |
63 | // these up to a MIDI input from the real Launchpad Pro! | 73 | // these up to a MIDI input from the real Launchpad Pro! |
64 | // ____________________________________________________________________________ | 74 | // ____________________________________________________________________________ |
65 | 75 | ||
76 | static u16 raw_ADC[64]; | ||
77 | |||
66 | static void sim_app_init() | 78 | static void sim_app_init() |
67 | { | 79 | { |
68 | printf("calling app_init()...\n"); | 80 | printf("calling app_init()...\n"); |
69 | app_init(); | 81 | app_init(raw_ADC); |
70 | } | 82 | } |
71 | 83 | ||
72 | static void sim_app_surface_event(u8 type, u8 index, u8 value) | 84 | static void sim_app_surface_event(u8 type, u8 index, u8 value) |