diff --git a/stm/adc.c b/stm/adc.c
index e54a464a843f82a5658e5245db95fc10f273952c..a5cdc0e3e8997dc5c2c1b08bc06f88076f11e922 100644
--- a/stm/adc.c
+++ b/stm/adc.c
@@ -2,6 +2,7 @@
 #include <stm32f4xx.h>
 
 #include "misc.h"
+#include "nlr.h"
 #include "mpconfig.h"
 #include "qstr.h"
 #include "obj.h"
@@ -41,7 +42,7 @@ typedef struct {
 } gpio_t;
 
 /* ADC GPIOs */
-static gpio_t adc_gpio[] = {
+static const gpio_t adc_gpio[] = {
     {GPIOA, GPIO_Pin_0},    /* ADC123_IN0 */
     {GPIOA, GPIO_Pin_1},    /* ADC123_IN1 */
     {GPIOA, GPIO_Pin_2},    /* ADC123_IN2 */
@@ -61,7 +62,7 @@ static gpio_t adc_gpio[] = {
 
 };
 
-void adc_init(uint32_t resolution) {
+void adc_init_all(uint32_t resolution) {
   ADC_InitTypeDef       ADC_InitStructure;
   GPIO_InitTypeDef      GPIO_InitStructure;
   ADC_CommonInitTypeDef ADC_CommonInitStructure;
@@ -111,6 +112,54 @@ void adc_init(uint32_t resolution) {
   ADC_TempSensorVrefintCmd(ENABLE);
 }
 
+void adc_init_single(uint32_t channel) {
+  ADC_InitTypeDef       ADC_InitStructure;
+  GPIO_InitTypeDef      GPIO_InitStructure;
+  ADC_CommonInitTypeDef ADC_CommonInitStructure;
+
+  /* Enable ADCx, DMA and GPIO clocks */ 
+#if 0
+  /* GPIO clocks enabled in main */
+  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
+                         RCC_AHB1Periph_GPIOB |
+                         RCC_AHB1Periph_GPIOC, ENABLE);
+#endif
+  RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
+
+  /* ADC Common Init */
+  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
+  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
+  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
+  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
+  ADC_CommonInit(&ADC_CommonInitStructure);
+
+  /* Configure ADC GPIO for the single channel */
+  GPIO_InitStructure.GPIO_Pin = adc_gpio[channel].pin;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_Init(adc_gpio[channel].port, &GPIO_InitStructure);
+
+  /* ADCx Init */
+//  ADC_DeInit();
+  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
+  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
+  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
+  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
+  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
+  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
+  ADC_InitStructure.ADC_NbrOfConversion = 1;
+  ADC_Init(ADCx, &ADC_InitStructure);
+
+  /* Enable ADCx */
+  ADC_Cmd(ADCx, ENABLE);
+
+  /* Enable VBAT/VREF monitor */
+  ADC_VBATCmd(ENABLE);
+
+  /* Enable temperature sensor */
+  ADC_TempSensorVrefintCmd(ENABLE);
+}
+
 uint32_t adc_read_channel(int channel)
 {
     int timeout = 10000;
@@ -213,91 +262,183 @@ float adc_read_core_vref()
 }
 
 /******************************************************************************/
-/* Micro Python bindings                                                      */
+/* Micro Python bindings : adc_all object                                     */
 
-typedef struct _pyb_adc_obj_t {
+typedef struct _pyb_obj_adc_all_t {
     mp_obj_base_t base;
-    int adc_id;
     bool is_enabled;
-} pyb_adc_obj_t;
+} pyb_obj_adc_all_t;
+
+static void adc_all_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+    print(env, "<ADC all>");
+}
 
-static mp_obj_t adc_obj_read_channel(mp_obj_t self_in, mp_obj_t channel) {
-    mp_obj_t ret = mp_const_none;
-    pyb_adc_obj_t *self = self_in;
+static mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) {
+    pyb_obj_adc_all_t *self = self_in;
 
     if (self->is_enabled) {
         uint32_t chan = mp_obj_get_int(channel);
         uint32_t data = adc_read_channel(chan);
-        ret = mp_obj_new_int(data);
+        return mp_obj_new_int(data);
+    } else {
+        return mp_const_none;
     }
-    return ret;
 }
 
-static mp_obj_t adc_obj_read_core_temp(mp_obj_t self_in) {
-    mp_obj_t ret = mp_const_none;
-    pyb_adc_obj_t *self = self_in;
+static mp_obj_t adc_all_read_core_temp(mp_obj_t self_in) {
+    pyb_obj_adc_all_t *self = self_in;
 
     if (self->is_enabled) {
         int data  = adc_read_core_temp();
-        ret = mp_obj_new_int(data);
+        return mp_obj_new_int(data);
+    } else {
+        return mp_const_none;
     }
-    return ret;
 }
 
-static mp_obj_t adc_obj_read_core_vbat(mp_obj_t self_in) {
-    mp_obj_t ret = mp_const_none;
-    pyb_adc_obj_t *self = self_in;
+static mp_obj_t adc_all_read_core_vbat(mp_obj_t self_in) {
+    pyb_obj_adc_all_t *self = self_in;
 
     if (self->is_enabled) {
         float data  = adc_read_core_vbat();
-        ret = mp_obj_new_float(data);
+        return mp_obj_new_float(data);
+    } else {
+        return mp_const_none;
     }
-    return ret;
 }
 
-static mp_obj_t adc_obj_read_core_vref(mp_obj_t self_in) {
-    mp_obj_t ret = mp_const_none;
-    pyb_adc_obj_t *self = self_in;
+static mp_obj_t adc_all_read_core_vref(mp_obj_t self_in) {
+    pyb_obj_adc_all_t *self = self_in;
 
     if (self->is_enabled) {
         float data  = adc_read_core_vref();
-        ret = mp_obj_new_float(data);
+        return mp_obj_new_float(data);
+    } else {
+        return mp_const_none;
     }
-    return ret;
 }
 
-static void adc_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
-    pyb_adc_obj_t *self = self_in;
-    print(env, "<ADC %lu>", self->adc_id);
+static MP_DEFINE_CONST_FUN_OBJ_2(adc_all_read_channel_obj, adc_all_read_channel);
+static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_temp_obj, adc_all_read_core_temp);
+static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vbat_obj, adc_all_read_core_vbat);
+static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vref_obj, adc_all_read_core_vref);
+
+static const mp_method_t adc_all_methods[] = {
+    { "read_channel",   &adc_all_read_channel_obj},
+    { "read_core_temp", &adc_all_read_core_temp_obj},
+    { "read_core_vbat", &adc_all_read_core_vbat_obj},
+    { "read_core_vref", &adc_all_read_core_vref_obj},
+    { NULL, NULL },
+};
+
+static const mp_obj_type_t adc_all_type = {
+    { &mp_const_type },
+    "ADC_all",
+    .print = adc_all_print,
+    .methods = adc_all_methods,
+};
+
+mp_obj_t pyb_ADC_all(mp_obj_t resolution) {
+    /* init ADC */
+    adc_init_all(mp_obj_get_int(resolution));
+
+    pyb_obj_adc_all_t *o = m_new_obj(pyb_obj_adc_all_t);
+    o->base.type = &adc_all_type;
+    o->is_enabled = true;
+    return o;
 }
 
-static MP_DEFINE_CONST_FUN_OBJ_2(adc_obj_read_channel_obj, adc_obj_read_channel);
-static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_temp_obj, adc_obj_read_core_temp);
-static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vbat_obj, adc_obj_read_core_vbat);
-static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vref_obj, adc_obj_read_core_vref);
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_all_obj, pyb_ADC_all);
+
+/******************************************************************************/
+/* Micro Python bindings : adc object (single channel)                        */
+
+typedef struct _pyb_obj_adc_t {
+    mp_obj_base_t base;
+    mp_obj_t pin_name;
+    int channel;
+    bool is_enabled;
+} pyb_obj_adc_t;
+
+static void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+    pyb_obj_adc_t *self = self_in;
+    print(env, "<ADC on ");
+    mp_obj_print_helper(print, env, self->pin_name, PRINT_STR);
+    print(env, " channel=%lu>", self->channel);
+}
+
+static mp_obj_t adc_read(mp_obj_t self_in) {
+    pyb_obj_adc_t *self = self_in;
+
+    if (self->is_enabled) {
+        uint32_t data = adc_read_channel(self->channel);
+        return mp_obj_new_int(data);
+    } else {
+        return mp_const_none;
+    }
+}
+
+static MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
 
 static const mp_method_t adc_methods[] = {
-    { "read_channel",   &adc_obj_read_channel_obj},
-    { "read_core_temp", &adc_obj_read_core_temp_obj},
-    { "read_core_vbat", &adc_obj_read_core_vbat_obj},
-    { "read_core_vref", &adc_obj_read_core_vref_obj},
+    { "read", &adc_read_obj},
     { NULL, NULL },
 };
 
-static const mp_obj_type_t adc_obj_type = {
+static const mp_obj_type_t adc_type = {
     { &mp_const_type },
     "ADC",
-    .print = adc_obj_print,
+    .print = adc_print,
     .methods = adc_methods,
 };
 
-mp_obj_t pyb_ADC(mp_obj_t resolution) {
-    /* init ADC */
-    adc_init(mp_obj_get_int(resolution));
+mp_obj_t pyb_ADC(mp_obj_t pin_name_obj) {
+
+    pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
+    o->base.type = &adc_type;
+    o->pin_name = pin_name_obj;
+
+    // work out the channel from the pin name
+    const char *pin_name = mp_obj_str_get_str(pin_name_obj);
+    GPIO_TypeDef *port;
+    switch (pin_name[0]) {
+        case 'A': case 'a': port = GPIOA; break;
+        case 'B': case 'b': port = GPIOB; break;
+        case 'C': case 'c': port = GPIOC; break;
+        default: goto pin_error;
+    }
+    uint pin_num = 0;
+    for (const char *s = pin_name + 1; *s; s++) {
+        if (!('0' <= *s && *s <= '9')) {
+            goto pin_error;
+        }
+        pin_num = 10 * pin_num + *s - '0';
+    }
+    if (!(0 <= pin_num && pin_num <= 15)) {
+        goto pin_error;
+    }
+
+    int i;
+    for (i = 0; i < ADC_NUM_CHANNELS; i++) {
+        if (adc_gpio[i].port == port && adc_gpio[i].pin == (1 << pin_num)) {
+            o->channel = i;
+            break;
+        }
+    }
+
+    if (i == ADC_NUM_CHANNELS) {
+        nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not have ADC capabilities", pin_name));
+    }
+
+    // init ADC just for this channel
+    adc_init_single(o->channel);
 
-    pyb_adc_obj_t *o = m_new_obj(pyb_adc_obj_t);
-    o->base.type = &adc_obj_type;
-    o->adc_id = 1;
     o->is_enabled = true;
+
     return o;
+
+pin_error:
+    nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not exist", pin_name));
 }
+
+MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_obj, pyb_ADC);
diff --git a/stm/adc.h b/stm/adc.h
index 5805aef42c6ad04ab37821a5b84165dd00ff949a..502da20dde76a6eca0e181fb7deef5e1aece8f78 100644
--- a/stm/adc.h
+++ b/stm/adc.h
@@ -1 +1,2 @@
-mp_obj_t pyb_ADC(mp_obj_t resolution);
+MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_all_obj);
+MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_obj);
diff --git a/stm/lcd.c b/stm/lcd.c
index a7d473bf6aa63f93452e26c23269e373958c9354..e8553a69e3c089713b1e12543f5b81adfaf7522c 100644
--- a/stm/lcd.c
+++ b/stm/lcd.c
@@ -13,7 +13,7 @@
 #include "font_petme128_8x8.h"
 #include "lcd.h"
 
-#if defined(PYBOARD)
+#if defined(PYBOARD3)
 #define PYB_LCD_PORT        (GPIOA)
 #define PYB_LCD_CS1_PIN     (GPIO_Pin_0)
 #define PYB_LCD_RST_PIN     (GPIO_Pin_1)
diff --git a/stm/lib/stm324x7i_eval.c b/stm/lib/stm324x7i_eval.c
index fa9fff31fe3b5234ee4321d88004a7fe6609fd06..c1be681f1db87bae0f908264c5eb01a84b033fa5 100644
--- a/stm/lib/stm324x7i_eval.c
+++ b/stm/lib/stm324x7i_eval.c
@@ -122,7 +122,7 @@ void SD_LowLevel_Init(void)
   GPIO_Init(GPIOC, &GPIO_InitStructure);
   
   /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */
-#if defined(PYBOARD)
+#if defined(PYBOARD3)
   // dpgeorge: PYBv2-v3: switch is normally open, connected to VDD when card inserted
   GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // needs to be 2MHz due to restrictions on PC13
diff --git a/stm/lib/stm324x7i_eval.h b/stm/lib/stm324x7i_eval.h
index a7df96acb06f23b9f51aab8f7312fbe417cced04..9adeecb16e1fa626c6b230d821241c1fe42ac058 100644
--- a/stm/lib/stm324x7i_eval.h
+++ b/stm/lib/stm324x7i_eval.h
@@ -41,7 +41,7 @@
 /**
   * @brief  SD FLASH SDIO Interface
   */
-#if defined(PYBOARD)
+#if defined(PYBOARD3)
 #define SD_DETECT_PIN                    GPIO_Pin_13                 /* PC.13 */
 #define SD_DETECT_GPIO_PORT              GPIOC                       /* GPIOC */
 #define SD_DETECT_GPIO_CLK               RCC_AHB1Periph_GPIOC
diff --git a/stm/lib/stm324x7i_eval_sdio_sd.c b/stm/lib/stm324x7i_eval_sdio_sd.c
index f0e2ffc3e29d463298f67bb322632f95903f3b74..2d6f4b8c94822be0c45f9b581303eb3f1c7eaa93 100644
--- a/stm/lib/stm324x7i_eval_sdio_sd.c
+++ b/stm/lib/stm324x7i_eval_sdio_sd.c
@@ -518,7 +518,7 @@ uint8_t SD_Detect(void)
   __IO uint8_t status = SD_PRESENT;
 
   /*!< Check GPIO to detect SD */
-#if defined(PYBOARD)
+#if defined(PYBOARD3)
   if (GPIO_ReadInputDataBit(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != Bit_SET)
 #elif defined(PYBOARD4)
   if (GPIO_ReadInputDataBit(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) == Bit_SET)
diff --git a/stm/main.c b/stm/main.c
index d2754a2e6a009f31b8310aaea7d256d1d7832aa3..1388a1d900e0b2364912ffeec4506f58e9f323db 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -137,8 +137,10 @@ static const char *help_text =
 "    pyb.switch()   -- return True/False if switch pressed or not\n"
 "    pyb.accel()    -- get accelerometer values\n"
 "    pyb.rand()     -- get a 16-bit random number\n"
-"    pyb.gpio(<port>)           -- get port value (port='a4' for example)\n"
+"    pyb.gpio(<port>)           -- get port value (port='A4' for example)\n"
 "    pyb.gpio(<port>, <val>)    -- set port value, True or False, 1 or 0\n"
+"    pyb.ADC(<port>) -- make an analog port object (port='C0' for example)\n"
+"                       ADC methods: read()\n"
 ;
 
 // get some help about available functions
@@ -348,7 +350,7 @@ int readline(vstr_t *line, const char *prompt) {
 }
 
 void do_repl(void) {
-    stdout_tx_str("Micro Python build <git hash> on 2/1/2014; PYBv3 with STM32F405RG\r\n");
+    stdout_tx_str("Micro Python build <git hash> on 25/1/2014; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
     stdout_tx_str("Type \"help()\" for more information.\r\n");
 
     vstr_t line;
@@ -654,7 +656,8 @@ soft_reset:
         rt_store_attr(m, MP_QSTR_I2C, rt_make_function_n(2, pyb_I2C));
         rt_store_attr(m, MP_QSTR_gpio, (mp_obj_t)&pyb_gpio_obj);
         rt_store_attr(m, MP_QSTR_Usart, rt_make_function_n(2, pyb_Usart));
-        rt_store_attr(m, MP_QSTR_ADC, rt_make_function_n(1, pyb_ADC));
+        rt_store_attr(m, qstr_from_str("ADC_all"), (mp_obj_t)&pyb_ADC_all_obj);
+        rt_store_attr(m, MP_QSTR_ADC, (mp_obj_t)&pyb_ADC_obj);
         rt_store_name(MP_QSTR_pyb, m);
 
         rt_store_name(MP_QSTR_open, rt_make_function_n(2, pyb_io_open));
diff --git a/stm/mpconfigport.h b/stm/mpconfigport.h
index 2851c1ad125cb49cd58ddb9a30d3c1fedc8cc4fa..028aea0f1927841dfa180efa5195b9c257d0089d 100644
--- a/stm/mpconfigport.h
+++ b/stm/mpconfigport.h
@@ -23,11 +23,13 @@ machine_float_t machine_sqrt(machine_float_t x);
 // board specific definitions
 
 // choose 1 of these boards
-//#define PYBOARD
-#define PYBOARD4
+#define PYBOARD3
+//#define PYBOARD4
 //#define STM32F4DISC
 
-#if defined (PYBOARD)
+#if defined (PYBOARD3)
+    #define MICROPY_HW_BOARD_NAME       "PYBv3"
+
     #define MICROPY_HW_HAS_SWITCH       (1)
     #define MICROPY_HW_HAS_SDCARD       (1)
     #define MICROPY_HW_HAS_MMA7660      (1)
@@ -68,6 +70,8 @@ machine_float_t machine_sqrt(machine_float_t x);
     #define PYB_LED_OFF(port, pin) (port->BSRRL = pin)
 
 #elif defined (PYBOARD4)
+    #define MICROPY_HW_BOARD_NAME       "PYBv4"
+
     #define MICROPY_HW_HAS_SWITCH       (1)
     #define MICROPY_HW_HAS_SDCARD       (1)
     #define MICROPY_HW_HAS_MMA7660      (1)
@@ -108,6 +112,8 @@ machine_float_t machine_sqrt(machine_float_t x);
     #define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
 
 #elif defined (STM32F4DISC)
+    #define MICROPY_HW_BOARD_NAME       "F4DISC"
+
     #define MICROPY_HW_HAS_SWITCH       (1)
     #define MICROPY_HW_HAS_SDCARD       (0)
     #define MICROPY_HW_HAS_MMA7660      (0)
diff --git a/stm/usart.c b/stm/usart.c
index 1ab385174d6818b31c3b3d761c93d5e0b037a4c9..d9de599c46ed49cf99b60b7a2a46119504538099 100644
--- a/stm/usart.c
+++ b/stm/usart.c
@@ -77,7 +77,7 @@ void usart_init(pyb_usart_t usart_id, uint32_t baudrate) {
         case PYB_USART_3:
             USARTx = USART3;
 
-#if defined(PYBOARD4)
+#if defined(PYBOARD3) || defined(PYBOARD4)
             GPIO_Port = GPIOB;
             GPIO_AF_USARTx = GPIO_AF_USART3;
             GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
diff --git a/stm/usrsw.c b/stm/usrsw.c
index 162cecfcf0b3a406843b773c69b50720b2a60e97..c3374b847e24b8a9eafbdcd4282fedb48bb3d10c 100644
--- a/stm/usrsw.c
+++ b/stm/usrsw.c
@@ -44,7 +44,7 @@ void switch_init(void) {
 }
 
 int switch_get(void) {
-#if defined (PYBOARD) || defined (PYBOARD4)
+#if defined (PYBOARD3) || defined (PYBOARD4)
     if (USRSW_PORT->IDR & USRSW_PIN) {
         // pulled high, so switch is not pressed
         return 0;