Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
Making money with Erlang
having your Pi and selling it with a margin
Torben HoffmannProduct & Research Manager
Erlang Solutions@LeHoff
Wednesday, 1 May 2013 W
Erlang History
Wednesday, 1 May 2013 W
wantedshort time-to-market
on-the-fly upgrades
quality and reliability
and more...
Wednesday, 1 May 2013 W
wantedproductivity
no down-time
something that always works
Wednesday, 1 May 2013 W
wantedmoney
money
money
Wednesday, 1 May 2013 W
Semantic Gap
Wednesday, 1 May 2013 W
© 1999-2012 Erlang Solutions Ltd.
Small semantic gap
7
Telecom
General vs Domain Specific
Wednesday, 1 May 2013 W
© 1999-2012 Erlang Solutions Ltd.
Small semantic gap
7
Telecom
C++/Java
General vs Domain Specific
Wednesday, 1 May 2013 W
© 1999-2012 Erlang Solutions Ltd.
Small semantic gap
7
Telecom
C++/Java
General vs Domain Specific
Wednesday, 1 May 2013 W
© 1999-2012 Erlang Solutions Ltd.
Small semantic gap
7
Telecom
Erlang
C++/Java
General vs Domain Specific
Wednesday, 1 May 2013 W
© 1999-2012 Erlang Solutions Ltd.
Small semantic gap
7
Telecom
Erlang
C++/Java
General vs Domain Specific
Wednesday, 1 May 2013 W
© 1999-2012 Erlang Solutions Ltd.
Small semantic gap
7
Telecom
Erlang
C++/Java
Smaller gap =
money!
General vs Domain Specific
Wednesday, 1 May 2013 W
The Sweet SpotGUI
Drivers
MiddlewareCoordination
Control
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fit
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fitTelecom
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fit
C
Telecom
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fit
C
Erlang
Telecom
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
• Very large software systems
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
• Very large software systems
• Complex functionality
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
• Very large software systems
• Complex functionality
• Continuous operation for many years
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
• Very large software systems
• Complex functionality
• Continuous operation for many years
• Software maintenance on-the-fly
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
• Very large software systems
• Complex functionality
• Continuous operation for many years
• Software maintenance on-the-fly
• High quality and reliability
Wednesday, 1 May 2013 W
Erlang’s Original Requirements
• Large scale concurrency
• Soft real-time
• Distributed systems
• Hardware interaction
• Very large software systems
• Complex functionality
• Continuous operation for many years
• Software maintenance on-the-fly
• High quality and reliability
• Fault tolerance
Wednesday, 1 May 2013 W
Simplicity
Wednesday, 1 May 2013 W
Erlang doesn’t need an IDE!
Simplicity
Wednesday, 1 May 2013 W
Erlang doesn’t need an IDE!
InspirationDies inExpansion
Simplicity
Wednesday, 1 May 2013 W
Wednesday, 1 May 2013 W
Accepting Erlang
Wednesday, 1 May 2013 W
•So if Erlang is the best thing since sliced bread, how come it is so hard to convince people to use it?
Wednesday, 1 May 2013 W
A detour:Understanding
Technology Adoptation
Wednesday, 1 May 2013 W
16
Technology Adaptation Life Cycle
Originally developed by Joe M. Bohlen, George M. Beal and Everett M. Rogers
Wednesday, 1 May 2013 W
16
Technology Adaptation Life Cycle
Originally developed by Joe M. Bohlen, George M. Beal and Everett M. Rogers
Technology enthusiasts
Wednesday, 1 May 2013 W
16
Technology Adaptation Life Cycle
Originally developed by Joe M. Bohlen, George M. Beal and Everett M. Rogers
Technology enthusiasts
Visionaries
Wednesday, 1 May 2013 W
16
Technology Adaptation Life Cycle
Originally developed by Joe M. Bohlen, George M. Beal and Everett M. Rogers
Technology enthusiasts
Visionaries
Pragmatists
Wednesday, 1 May 2013 W
16
Technology Adaptation Life Cycle
Originally developed by Joe M. Bohlen, George M. Beal and Everett M. Rogers
Technology enthusiasts
Visionaries
PragmatistsConservatives
Wednesday, 1 May 2013 W
16
Technology Adaptation Life Cycle
Originally developed by Joe M. Bohlen, George M. Beal and Everett M. Rogers
Technology enthusiasts
Visionaries
PragmatistsConservatives
Laggards
Wednesday, 1 May 2013 W
Cracks and a Chasm
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
Pragmatists
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
PragmatistsConservatives
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
PragmatistsConservatives
Laggards
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
PragmatistsConservatives
Laggards
Crack
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
PragmatistsConservatives
Laggards
Crack
Crack
Wednesday, 1 May 2013 W
Cracks and a Chasm
Technology enthusiasts
Visionaries
PragmatistsConservatives
Laggards
Crack
CrackChasm
Wednesday, 1 May 2013 W
Visionaries vs Pragmatists
Visionaries have four characteristics that alienate Pragmatists:
Wednesday, 1 May 2013 W
Visionaries vs Pragmatists
• Lack of respect for their colleagues’ experiences
Visionaries have four characteristics that alienate Pragmatists:
Wednesday, 1 May 2013 W
Visionaries vs Pragmatists
• Lack of respect for their colleagues’ experiences
• Takes greater interest in technology than in their industry
Visionaries have four characteristics that alienate Pragmatists:
Wednesday, 1 May 2013 W
Visionaries vs Pragmatists
• Lack of respect for their colleagues’ experiences
• Takes greater interest in technology than in their industry
• Fail to recognise the importance of existing product infrastructure
Visionaries have four characteristics that alienate Pragmatists:
Wednesday, 1 May 2013 W
Visionaries vs Pragmatists
• Lack of respect for their colleagues’ experiences
• Takes greater interest in technology than in their industry
• Fail to recognise the importance of existing product infrastructure
• Overall disruptiveness
Visionaries have four characteristics that alienate Pragmatists:
Wednesday, 1 May 2013 W
The Whole Product
Wednesday, 1 May 2013 W
Whole Product
See Levitt’s “The Marketing Imagination” for details
Wednesday, 1 May 2013 W
Whole Product
Generic Product
See Levitt’s “The Marketing Imagination” for details
Wednesday, 1 May 2013 W
Whole Product
Generic ProductExpected Product
See Levitt’s “The Marketing Imagination” for details
Wednesday, 1 May 2013 W
Whole Product
Generic ProductExpected Product
Augmented Product
See Levitt’s “The Marketing Imagination” for details
Wednesday, 1 May 2013 W
Whole Product
Generic ProductExpected Product
Augmented ProductPotential Product
See Levitt’s “The Marketing Imagination” for details
Wednesday, 1 May 2013 W
Whole Product
Generic ProductExpected Product
Augmented ProductPotential Product
See Levitt’s “The Marketing Imagination” for details
Pragmatists evaluate and buy whole products!
Wednesday, 1 May 2013 W
Whole Product Planning
GenericProduct
Standards&
Procedures AdditionalSoftware
SystemIntegration
Training&
Support
Installation&
Debugging
AdditionalHardware
Anything elseto achieve your
compelling reason to buy
Simplified for chasm crossing
Wednesday, 1 May 2013 W
Whole Product Planning
GenericProduct
Standards&
Procedures AdditionalSoftware
SystemIntegration
Training&
Support
Installation&
Debugging
AdditionalHardware
Anything elseto achieve your
compelling reason to buy
Simplified for chasm crossing
= marketing promise to win the sale
Wednesday, 1 May 2013 W
Erlang Whole Product 1/2
•Generic product:
- Erlang compiler and runtime
•Additional software:
- rich library shipped with each release
- many open source libraries
•Training & support:
- ESL provides many courses
- ErlangCamp also provides training
Wednesday, 1 May 2013 W
Erlang Whole Product 2/2
• System integration:
- mostly case-by-case
- few public success stories
• Installation & Debugging:
- Adequate functionalities for installing applications
- Lack of good mass deployment tools
- Good debugging tools, but not well publicised
Wednesday, 1 May 2013 W
Advice?
Wednesday, 1 May 2013 W
Advice?
Find a visionary with money as your sponsor!
Wednesday, 1 May 2013 W
Erlang/ALE
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fit
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fitEmbedded
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fit
C
Embedded
Wednesday, 1 May 2013 W
If the glove fits...
drivers coordination GUI
needs/fit
C
Erlang
Embedded
Wednesday, 1 May 2013 W
Introducing
Wednesday, 1 May 2013 W
Introducing
Erlang
Wednesday, 1 May 2013 W
Introducing
Erlang Actor
Wednesday, 1 May 2013 W
Introducing
Erlang ActorLibrary
Wednesday, 1 May 2013 W
Introducing
Erlang ActorLibraryfor
Wednesday, 1 May 2013 W
Introducing
Erlang ActorLibraryfor
Embedded
Wednesday, 1 May 2013 W
Introducing
Erlang ActorLibraryfor
Embedded
Erlang/ALE
Wednesday, 1 May 2013 W
Opportunities
Wednesday, 1 May 2013 W
Opportunities
Cheap, powerful hardware
Wednesday, 1 May 2013 W
Opportunities
Cheap, powerful hardwareInternet of things
Wednesday, 1 May 2013 W
Opportunities
Cheap, powerful hardwareInternet of thingsExtending solutions in field - both HW & SW
Wednesday, 1 May 2013 W
Opportunities
Cheap, powerful hardwareInternet of thingsExtending solutions in field - both HW & SWDealing with more complex problems
Wednesday, 1 May 2013 W
Opportunities
Cheap, powerful hardwareInternet of thingsExtending solutions in field - both HW & SWDealing with more complex problemsShort time-to-market
Wednesday, 1 May 2013 W
Hardware
Wednesday, 1 May 2013 W
HardwareRaspberry-Pi for fun and prototypesFor production:
Gumstix, Beaglebone.Later:
OLinuXino (<€20)
Wednesday, 1 May 2013 W
Raspberry-Pi is
NOTfor
production
Wednesday, 1 May 2013 W
Architecture
Wednesday, 1 May 2013 W
Architecture
HardwareWednesday, 1 May 2013 W
Architecture
Driver
HardwareWednesday, 1 May 2013 W
Architecture
Driver
I/F X Process
HardwareWednesday, 1 May 2013 W
Architecture
Driver
I/F X Process
UserProcess
HardwareWednesday, 1 May 2013 W
Architecture
Driver
I/F X Process
UserProcess
Hardware
Erlang
Wednesday, 1 May 2013 W
Architecture
Driver
I/F X Process
UserProcess
Hardware
Erlang
C
Wednesday, 1 May 2013 W
Architecture
Driver
I/F X Process
UserProcess
Erlang/ALE
Hardware
Erlang
C
Wednesday, 1 May 2013 W
Driver
Wednesday, 1 May 2013 W
Driver
C port driver
Wednesday, 1 May 2013 W
Driver
C port drivererl_marshal
Wednesday, 1 May 2013 W
Driver
C port drivererl_marshalpthread
Wednesday, 1 May 2013 W
erl_marshalETERM*gpio_port_write(ETERM* pin_t, ETERM* value_t) { unsigned int pin; unsigned int val; pin = ERL_INT_VALUE(pin_t); val = ERL_INT_VALUE(value_t);
if (!gpio_write(pin, val)) return erl_format("{error, gpio_port_write}"); return erl_format(“ok”)
}
Wednesday, 1 May 2013 W
pthreads for
interrupts
static void *isr_handler (void *isr) { struct pollfd fdset[2]; int nfds = 2, gpio_fd, rc; char *buf[64];
isr_t i = *(isr_t *) isr;
if (isr_handler_flag) { printf ("isr_handler running\n");
/* Get /value fd TODO: Add check here */ gpio_fd = gpio_valfd (ERL_INT_VALUE(i.pinp));
if ( gpio_fd == -1) { fprintf(stderr, "Unable to open gpio fd\n\r"); return NULL; }
while (1) { memset ((void *) fdset, 0, sizeof (fdset));
fdset[0].fd = STDIN_FILENO; fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd; fdset[1].events = POLLPRI;
rc = poll (fdset, nfds, 1000);! /* Timeout in ms */
if (rc < 0) { debug ("\npoll() failed!\n"); return (void *) -1; }
if (rc == 0) { /* debug ("poll() timeout.\n"); */ if (isr_handler_flag == 0) { debug ("exiting isr_handler (timeout)"); pthread_exit (NULL); } }
if (fdset[1].revents & POLLPRI) {/* We have an interrupt! */ if (-1 == read (fdset[1].fd, buf, 64)) { debug ("read failed for interrupt"); return (void *) -1; }
(*i.isr) (i.pinp, i.pidp, i.modep);! /* Call the ISR */ }
if (fdset[0].revents & POLLIN) { if (-1 == read (fdset[0].fd, buf, 1)) { debug ("read failed for stdin read"); return (void *) -1; }
printf ("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]); }
fflush (stdout); } } else { debug ("exiting isr_handler (flag)"); pthread_exit (NULL); }
}
Wednesday, 1 May 2013 W
I/F X Process
set_int(Pin, Condition) when Condition == rising; Condition == falling; Condition == both; Condition == none -> Requestor = self(), call_existing(Pin, {set_int, Condition, Requestor});set_int(_Pin, _Condition) -> {error, wrong_condition}.
Wednesday, 1 May 2013 W
I/F X Processhandle_call({set_int, Condition, Requestor}, From, #state{direction=input, interrupt=none, pending=Pending, port=Port}=State) -> port_lib:call_to_port(Port, From, {set_int, Condition}), NewPending = [From | Pending], {noreply, State#state{interrupt={Condition, [Requestor]}, pending=NewPending}};
Wednesday, 1 May 2013 W
I/F X Process
Wednesday, 1 May 2013 W
I/F X Processhandle_info({Port, {data, Msg}}, #state{port=Port, pin=Pin}=State) -> apply_after(0, ?MODULE, from_port, [Pin, Msg]), {noreply, State}.
Wednesday, 1 May 2013 W
I/F X Processhandle_info({Port, {data, Msg}}, #state{port=Port, pin=Pin}=State) -> apply_after(0, ?MODULE, from_port, [Pin, Msg]), {noreply, State}.
from_port(Pin, Msg) -> call_existing(Pin, {from_port, Msg}).
Wednesday, 1 May 2013 W
I/F X Processhandle_info({Port, {data, Msg}}, #state{port=Port, pin=Pin}=State) -> apply_after(0, ?MODULE, from_port, [Pin, Msg]), {noreply, State}.
from_port(Pin, Msg) -> call_existing(Pin, {from_port, Msg}).
handle_call({from_port, {port_reply, To, Msg}}, _From, #state{pending=Pending}=State) -> NewPending = lists:delete(To, Pending), gen_server:reply(To, Msg), {reply, ok, State#state{pending=NewPending}}.
Wednesday, 1 May 2013 W
User ProcessSpecification
Two LEDscount up & down between 0 and 3
One button to act as +1One button to act as -1
Wednesday, 1 May 2013 W
User ProcessInitialisation
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) ->
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input),
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input), {ok, _} = gpio:start_link(?DOWN_PIN, input),
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input), {ok, _} = gpio:start_link(?DOWN_PIN, input), ok = gpio:pin_set_int(?UP_PIN, rising),
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input), {ok, _} = gpio:start_link(?DOWN_PIN, input), ok = gpio:pin_set_int(?UP_PIN, rising), ok = gpio:pin_set_int(?DOWN_PIN, rising),
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input), {ok, _} = gpio:start_link(?DOWN_PIN, input), ok = gpio:pin_set_int(?UP_PIN, rising), ok = gpio:pin_set_int(?DOWN_PIN, rising), {ok, _} = gpio:start_link(?ONES_PIN, output),
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input), {ok, _} = gpio:start_link(?DOWN_PIN, input), ok = gpio:pin_set_int(?UP_PIN, rising), ok = gpio:pin_set_int(?DOWN_PIN, rising), {ok, _} = gpio:start_link(?ONES_PIN, output), {ok, _} = gpio:start_link(?TWOS_PIN, output),
Wednesday, 1 May 2013 W
User ProcessInitialisation
init([]) -> {ok, _} = gpio:start_link(?UP_PIN, input), {ok, _} = gpio:start_link(?DOWN_PIN, input), ok = gpio:pin_set_int(?UP_PIN, rising), ok = gpio:pin_set_int(?DOWN_PIN, rising), {ok, _} = gpio:start_link(?ONES_PIN, output), {ok, _} = gpio:start_link(?TWOS_PIN, output), {ok, #state{count=0}}.
Wednesday, 1 May 2013 W
User ProcessReacting
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising},
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 ->
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1,
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1),
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1), {noreply, State#state{count=N1}};
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1), {noreply, State#state{count=N1}};handle_info({gpio_interrupt, ?DOWN_PIN, rising},
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1), {noreply, State#state{count=N1}};handle_info({gpio_interrupt, ?DOWN_PIN, rising}, #state{count=N}=State) when N > 0 ->
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1), {noreply, State#state{count=N1}};handle_info({gpio_interrupt, ?DOWN_PIN, rising}, #state{count=N}=State) when N > 0 -> N1 = N - 1,
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1), {noreply, State#state{count=N1}};handle_info({gpio_interrupt, ?DOWN_PIN, rising}, #state{count=N}=State) when N > 0 -> N1 = N - 1, set_counter_pins(N1),
Wednesday, 1 May 2013 W
User ProcessReacting
handle_info({gpio_interrupt, ?UP_PIN, rising}, #state{count=N}=State) when N < 3 -> N1 = N + 1, set_counter_pins(N1), {noreply, State#state{count=N1}};handle_info({gpio_interrupt, ?DOWN_PIN, rising}, #state{count=N}=State) when N > 0 -> N1 = N - 1, set_counter_pins(N1), {noreply, State#state{count=N1}};
Wednesday, 1 May 2013 W
User ProcessLight my LEDs baby
Wednesday, 1 May 2013 W
User ProcessLight my LEDs baby
set_counter_pins(N1) ->
Wednesday, 1 May 2013 W
User ProcessLight my LEDs baby
set_counter_pins(N1) -> <<Twos:1, Ones:1>> = <<N1:2>>,
Wednesday, 1 May 2013 W
User ProcessLight my LEDs baby
set_counter_pins(N1) -> <<Twos:1, Ones:1>> = <<N1:2>>, gpio:pin_write(?ONES_PIN, Ones),
Wednesday, 1 May 2013 W
User ProcessLight my LEDs baby
set_counter_pins(N1) -> <<Twos:1, Ones:1>> = <<N1:2>>, gpio:pin_write(?ONES_PIN, Ones), gpio:pin_write(?TWOS_PIN, Twos).
Wednesday, 1 May 2013 W
Testing w/o Port Drivers
API
Erlang process
Port driver
Async interaction
client
Wednesday, 1 May 2013 W
Testing w/o Port Drivers
API
Erlang process
Port driver
Async interaction
client
How do we test this guy?
Wednesday, 1 May 2013 W
Simulating port driver
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) ->
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive {Owner, {command, Cmd}} ->
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive {Owner, {command, Cmd}} -> case Cmd of
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive {Owner, {command, Cmd}} -> case Cmd of {call, From, {write, V}} ->
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive {Owner, {command, Cmd}} -> case Cmd of {call, From, {write, V}} -> Owner ! port_reply({port_reply, From, ok}),
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive {Owner, {command, Cmd}} -> case Cmd of {call, From, {write, V}} -> Owner ! port_reply({port_reply, From, ok}), gpio_port(S#state{value=V});
Wednesday, 1 May 2013 W
Simulating port driver
gpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> receive {Owner, {command, Cmd}} -> case Cmd of {call, From, {write, V}} -> Owner ! port_reply({port_reply, From, ok}), gpio_port(S#state{value=V}); ...
Wednesday, 1 May 2013 W
Hardware Backdoor
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) ->
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ...
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} ->
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond ->
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond});
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change,
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both ->
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both -> Owner ! port_reply({gpio_interrupt, Cond});
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both -> Owner ! port_reply({gpio_interrupt, Cond}); _ ->
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both -> Owner ! port_reply({gpio_interrupt, Cond}); _ -> ok
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both -> Owner ! port_reply({gpio_interrupt, Cond}); _ -> ok end,
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both -> Owner ! port_reply({gpio_interrupt, Cond}); _ -> ok end, gpio_port(S#state{value=V})
Wednesday, 1 May 2013 W
Hardware Backdoorgpio_port(#state{owner=Owner, value=Value, interrupt=Cond}=S) -> ... %% pure testing {set_value, V} -> case value_change(Value, V) of Cond -> Owner ! port_reply({gpio_interrupt, Cond}); C when C /= no_change, Cond == both -> Owner ! port_reply({gpio_interrupt, Cond}); _ -> ok end, gpio_port(S#state{value=V}) ...
Wednesday, 1 May 2013 W
Mocking
mock_gpio(Config) -> meck:new(port_lib, [passthrough]), meck:expect(port_lib, load_driver, fun(_) -> ok end), Port =spawn( fun gpio_port_sim:gpio_port/0 ), meck:expect(port_lib, open_port, fun(_) -> Owner = self(), Port ! {context, Owner}, Port end), [{port_pid, Port}|Config].
Wednesday, 1 May 2013 W
Mocking
mock_gpio(Config) -> meck:new(port_lib, [passthrough]), meck:expect(port_lib, load_driver, fun(_) -> ok end), Port =spawn( fun gpio_port_sim:gpio_port/0 ), meck:expect(port_lib, open_port, fun(_) -> Owner = self(), Port ! {context, Owner}, Port end), [{port_pid, Port}|Config].
Make sure the port knows its context
Wednesday, 1 May 2013 W
Interrupt Test Case
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) ->
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23,
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input),
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config),
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising,
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising, InitialValue = 0,
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising, InitialValue = 0, Port ! {set_value, InitialValue},
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising, InitialValue = 0, Port ! {set_value, InitialValue}, ok = gpio:set_int(Pin, Condition),
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising, InitialValue = 0, Port ! {set_value, InitialValue}, ok = gpio:set_int(Pin, Condition), TriggerValue = 1,
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising, InitialValue = 0, Port ! {set_value, InitialValue}, ok = gpio:set_int(Pin, Condition), TriggerValue = 1, Port ! {set_value, TriggerValue},
Wednesday, 1 May 2013 W
Interrupt Test Case
one_interrupt(Config) -> Pin = 23, {ok, _} = gpio:init(Pin, input), Port = ?config(port_pid, Config), Condition = rising, InitialValue = 0, Port ! {set_value, InitialValue}, ok = gpio:set_int(Pin, Condition), TriggerValue = 1, Port ! {set_value, TriggerValue}, ok = receive_interrupt(Pin, Condition).
Wednesday, 1 May 2013 W
Conclusions
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what Erlang/OTP is for telecom
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what Erlang/OTP is for telecom
Productivity = Money
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what Erlang/OTP is for telecom
Productivity = MoneyTime-to-market = Money
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what Erlang/OTP is for telecom
Productivity = MoneyTime-to-market = MoneySimplicity = Money
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what Erlang/OTP is for telecom
Productivity = MoneyTime-to-market = MoneySimplicity = MoneyRobustness = Money
Wednesday, 1 May 2013 W
ConclusionsPitch Erlang to Visionaries with money ;-)Expect resistance from Pragmatists
Erlang/ALE is for embedded what Erlang/OTP is for telecom
Productivity = MoneyTime-to-market = MoneySimplicity = MoneyRobustness = Money
Wednesday, 1 May 2013 W